in some cases importing without materials could raise a python error.
[blender.git] / release / scripts / import_obj.py
1 #!BPY
2  
3 """
4 Name: 'Wavefront (.obj)...'
5 Blender: 249
6 Group: 'Import'
7 Tooltip: 'Load a Wavefront OBJ File, Shift: batch import all dir.'
8 """
9
10 __author__= "Campbell Barton", "Jiri Hnidek", "Paolo Ciccone"
11 __url__= ['http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj', 'blender.org', 'blenderartists.org']
12 __version__= "2.11"
13
14 __bpydoc__= """\
15 This script imports a Wavefront OBJ files to Blender.
16
17 Usage:
18 Run this script from "File->Import" menu and then load the desired OBJ file.
19 Note, This loads mesh objects and materials only, nurbs and curves are not supported.
20 """
21
22 # ***** BEGIN GPL LICENSE BLOCK *****
23 #
24 # Script copyright (C) Campbell J Barton 2007
25 #
26 # This program is free software; you can redistribute it and/or
27 # modify it under the terms of the GNU General Public License
28 # as published by the Free Software Foundation; either version 2
29 # of the License, or (at your option) any later version.
30 #
31 # This program is distributed in the hope that it will be useful,
32 # but WITHOUT ANY WARRANTY; without even the implied warranty of
33 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34 # GNU General Public License for more details.
35 #
36 # You should have received a copy of the GNU General Public License
37 # along with this program; if not, write to the Free Software Foundation,
38 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
39 #
40 # ***** END GPL LICENCE BLOCK *****
41 # --------------------------------------------------------------------------
42
43 from Blender import Mesh, Draw, Window, Texture, Material, sys
44 import bpy
45 import BPyMesh
46 import BPyImage
47 import BPyMessages
48
49 try:            import os
50 except:         os= False
51
52 # Generic path functions
53 def stripFile(path):
54         '''Return directory, where the file is'''
55         lastSlash= max(path.rfind('\\'), path.rfind('/'))
56         if lastSlash != -1:
57                 path= path[:lastSlash]
58         return '%s%s' % (path, sys.sep)
59
60 def stripPath(path):
61         '''Strips the slashes from the back of a string'''
62         return path.split('/')[-1].split('\\')[-1]
63
64 def stripExt(name): # name is a string
65         '''Strips the prefix off the name before writing'''
66         index= name.rfind('.')
67         if index != -1:
68                 return name[ : index ]
69         else:
70                 return name
71 # end path funcs
72
73
74
75 def line_value(line_split):
76         '''
77         Returns 1 string represneting the value for this line
78         None will be returned if theres only 1 word
79         '''
80         length= len(line_split)
81         if length == 1:
82                 return None
83         
84         elif length == 2:
85                 return line_split[1]
86         
87         elif length > 2:
88                 return ' '.join( line_split[1:] )
89
90 def obj_image_load(imagepath, DIR, IMAGE_SEARCH):
91         '''
92         Mainly uses comprehensiveImageLoad
93         but tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores.
94         '''
95         
96         if '_' in imagepath:
97                 image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
98                 if image: return image
99                 # Did the exporter rename the image?
100                 image= BPyImage.comprehensiveImageLoad(imagepath.replace('_', ' '), DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH)
101                 if image: return image
102         
103         # Return an image, placeholder if it dosnt exist
104         image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= True, RECURSIVE= IMAGE_SEARCH)
105         return image
106         
107
108 def create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH):
109         '''
110         Create all the used materials in this obj,
111         assign colors and images to the materials from all referenced material libs
112         '''
113         DIR= stripFile(filepath)
114         
115         #==================================================================================#
116         # This function sets textures defined in .mtl file                                 #
117         #==================================================================================#
118         def load_material_image(blender_material, context_material_name, imagepath, type):
119                 
120                 texture= bpy.data.textures.new(type)
121                 texture.setType('Image')
122                 
123                 # Absolute path - c:\.. etc would work here
124                 image= obj_image_load(imagepath, DIR, IMAGE_SEARCH)
125                 has_data = image.has_data
126                 texture.image = image
127                 
128                 # Adds textures for materials (rendering)
129                 if type == 'Kd':
130                         if has_data and image.depth == 32:
131                                 # Image has alpha
132                                 blender_material.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL | Texture.MapTo.ALPHA)
133                                 texture.setImageFlags('MipMap', 'InterPol', 'UseAlpha')
134                                 blender_material.mode |= Material.Modes.ZTRANSP
135                                 blender_material.alpha = 0.0
136                         else:
137                                 blender_material.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL)
138                                 
139                         # adds textures to faces (Textured/Alt-Z mode)
140                         # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func.
141                         unique_material_images[context_material_name]= image, has_data # set the texface image
142                 
143                 elif type == 'Ka':
144                         blender_material.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) # TODO- Add AMB to BPY API
145                         
146                 elif type == 'Ks':
147                         blender_material.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC)
148                 
149                 elif type == 'Bump':
150                         blender_material.setTexture(3, texture, Texture.TexCo.UV, Texture.MapTo.NOR)            
151                 elif type == 'D':
152                         blender_material.setTexture(4, texture, Texture.TexCo.UV, Texture.MapTo.ALPHA)                          
153                         blender_material.mode |= Material.Modes.ZTRANSP
154                         blender_material.alpha = 0.0
155                         # Todo, unset deffuse material alpha if it has an alpha channel
156                         
157                 elif type == 'refl':
158                         blender_material.setTexture(5, texture, Texture.TexCo.UV, Texture.MapTo.REF)            
159         
160         
161         # Add an MTL with the same name as the obj if no MTLs are spesified.
162         temp_mtl= stripExt(stripPath(filepath))+ '.mtl'
163         
164         if sys.exists(DIR + temp_mtl) and temp_mtl not in material_libs:
165                         material_libs.append( temp_mtl )
166         del temp_mtl
167         
168         #Create new materials
169         for name in unique_materials: # .keys()
170                 if name != None:
171                         unique_materials[name]= bpy.data.materials.new(name)
172                         unique_material_images[name]= None, False # assign None to all material images to start with, add to later.
173                 
174         unique_materials[None]= None
175         unique_material_images[None]= None, False
176         
177         for libname in material_libs:
178                 mtlpath= DIR + libname
179                 if not sys.exists(mtlpath):
180                         #print '\tError Missing MTL: "%s"' % mtlpath
181                         pass
182                 else:
183                         #print '\t\tloading mtl: "%s"' % mtlpath
184                         context_material= None
185                         mtl= open(mtlpath, 'rU')
186                         for line in mtl: #.xreadlines():
187                                 if line.startswith('newmtl'):
188                                         context_material_name= line_value(line.split())
189                                         if unique_materials.has_key(context_material_name):
190                                                 context_material = unique_materials[ context_material_name ]
191                                         else:
192                                                 context_material = None
193                                 
194                                 elif context_material:
195                                         # we need to make a material to assign properties to it.
196                                         line_split= line.split()
197                                         line_lower= line.lower().lstrip()
198                                         if line_lower.startswith('ka'):
199                                                 context_material.setMirCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
200                                         elif line_lower.startswith('kd'):
201                                                 context_material.setRGBCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
202                                         elif line_lower.startswith('ks'):
203                                                 context_material.setSpecCol((float(line_split[1]), float(line_split[2]), float(line_split[3])))
204                                         elif line_lower.startswith('ns'):
205                                                 context_material.setHardness( int((float(line_split[1])*0.51)) )
206                                         elif line_lower.startswith('ni'): # Refraction index
207                                                 context_material.setIOR( max(1, min(float(line_split[1]), 3))) # Between 1 and 3
208                                         elif line_lower.startswith('d') or line_lower.startswith('tr'):
209                                                 context_material.setAlpha(float(line_split[1]))
210                                         elif line_lower.startswith('map_ka'):
211                                                 img_filepath= line_value(line.split())
212                                                 if img_filepath:
213                                                         load_material_image(context_material, context_material_name, img_filepath, 'Ka')
214                                         elif line_lower.startswith('map_ks'):
215                                                 img_filepath= line_value(line.split())
216                                                 if img_filepath:
217                                                         load_material_image(context_material, context_material_name, img_filepath, 'Ks')
218                                         elif line_lower.startswith('map_kd'):
219                                                 img_filepath= line_value(line.split())
220                                                 if img_filepath:
221                                                         load_material_image(context_material, context_material_name, img_filepath, 'Kd')
222                                         elif line_lower.startswith('map_bump'):
223                                                 img_filepath= line_value(line.split())
224                                                 if img_filepath:
225                                                         load_material_image(context_material, context_material_name, img_filepath, 'Bump')
226                                         elif line_lower.startswith('map_d') or line_lower.startswith('map_tr'): # Alpha map - Dissolve
227                                                 img_filepath= line_value(line.split())
228                                                 if img_filepath:
229                                                         load_material_image(context_material, context_material_name, img_filepath, 'D')
230                                         
231                                         elif line_lower.startswith('refl'): # Reflectionmap
232                                                 img_filepath= line_value(line.split())
233                                                 if img_filepath:
234                                                         load_material_image(context_material, context_material_name, img_filepath, 'refl')
235                         mtl.close()
236
237
238
239         
240 def split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP, SPLIT_MATERIALS):
241         '''
242         Takes vert_loc and faces, and seperates into multiple sets of 
243         (verts_loc, faces, unique_materials, dataname)
244         This is done so objects do not overload the 16 material limit.
245         '''
246         
247         filename = stripExt(stripPath(filepath))
248         
249         if not SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS:
250                 # use the filename for the object name since we arnt chopping up the mesh.
251                 return [(verts_loc, faces, unique_materials, filename)]
252         
253         
254         def key_to_name(key):
255                 # if the key is a tuple, join it to make a string
256                 if type(key) == tuple:
257                         return '%s_%s' % key
258                 elif not key:
259                         return filename # assume its a string. make sure this is true if the splitting code is changed
260                 else:
261                         return key
262         
263         # Return a key that makes the faces unique.
264         if SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS:
265                 def face_key(face):
266                         return face[4] # object
267         
268         elif not SPLIT_OB_OR_GROUP and SPLIT_MATERIALS:
269                 def face_key(face):
270                         return face[2] # material
271         
272         else: # Both
273                 def face_key(face):
274                         return face[4], face[2] # object,material               
275         
276         
277         face_split_dict= {}
278         
279         oldkey= -1 # initialize to a value that will never match the key
280         
281         for face in faces:
282                 
283                 key= face_key(face)
284                 
285                 if oldkey != key:
286                         # Check the key has changed.
287                         try:
288                                 verts_split, faces_split, unique_materials_split, vert_remap= face_split_dict[key]
289                         except KeyError:
290                                 faces_split= []
291                                 verts_split= []
292                                 unique_materials_split= {}
293                                 vert_remap= [-1]*len(verts_loc)
294                                 
295                                 face_split_dict[key]= (verts_split, faces_split, unique_materials_split, vert_remap)
296                         
297                         oldkey= key
298                         
299                 face_vert_loc_indicies= face[0]
300                 
301                 # Remap verts to new vert list and add where needed
302                 for enum, i in enumerate(face_vert_loc_indicies):
303                         if vert_remap[i] == -1:
304                                 new_index= len(verts_split)
305                                 vert_remap[i]= new_index # set the new remapped index so we only add once and can reference next time.
306                                 face_vert_loc_indicies[enum] = new_index # remap to the local index
307                                 verts_split.append( verts_loc[i] ) # add the vert to the local verts 
308                                 
309                         else:
310                                 face_vert_loc_indicies[enum] = vert_remap[i] # remap to the local index
311                         
312                         matname= face[2]
313                         if matname and not unique_materials_split.has_key(matname):
314                                 unique_materials_split[matname] = unique_materials[matname]
315                 
316                 faces_split.append(face)
317         
318         
319         # remove one of the itemas and reorder
320         return [(value[0], value[1], value[2], key_to_name(key)) for key, value in face_split_dict.iteritems()]
321
322
323 def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, verts_tex, faces, unique_materials, unique_material_images, unique_smooth_groups, vertex_groups, dataname):
324         '''
325         Takes all the data gathered and generates a mesh, adding the new object to new_objects
326         deals with fgons, sharp edges and assigning materials
327         '''
328         if not has_ngons:
329                 CREATE_FGONS= False
330         
331         if unique_smooth_groups:
332                 sharp_edges= {}
333                 smooth_group_users= dict([ (context_smooth_group, {}) for context_smooth_group in unique_smooth_groups.iterkeys() ])
334                 context_smooth_group_old= -1
335         
336         # Split fgons into tri's
337         fgon_edges= {} # Used for storing fgon keys
338         if CREATE_EDGES:
339                 edges= []
340         
341         context_object= None
342         
343         # reverse loop through face indicies
344         for f_idx in xrange(len(faces)-1, -1, -1):
345                 
346                 face_vert_loc_indicies,\
347                 face_vert_tex_indicies,\
348                 context_material,\
349                 context_smooth_group,\
350                 context_object= faces[f_idx]
351                 
352                 len_face_vert_loc_indicies = len(face_vert_loc_indicies)
353                 
354                 if len_face_vert_loc_indicies==1:
355                         faces.pop(f_idx)# cant add single vert faces
356                 
357                 elif not face_vert_tex_indicies or len_face_vert_loc_indicies == 2: # faces that have no texture coords are lines
358                         if CREATE_EDGES:
359                                 # generators are better in python 2.4+ but can't be used in 2.3
360                                 # edges.extend( (face_vert_loc_indicies[i], face_vert_loc_indicies[i+1]) for i in xrange(len_face_vert_loc_indicies-1) )
361                                 edges.extend( [(face_vert_loc_indicies[i], face_vert_loc_indicies[i+1]) for i in xrange(len_face_vert_loc_indicies-1)] )
362
363                         faces.pop(f_idx)
364                 else:
365                         
366                         # Smooth Group
367                         if unique_smooth_groups and context_smooth_group:
368                                 # Is a part of of a smooth group and is a face
369                                 if context_smooth_group_old is not context_smooth_group:
370                                         edge_dict= smooth_group_users[context_smooth_group]
371                                         context_smooth_group_old= context_smooth_group
372                                 
373                                 for i in xrange(len_face_vert_loc_indicies):
374                                         i1= face_vert_loc_indicies[i]
375                                         i2= face_vert_loc_indicies[i-1]
376                                         if i1>i2: i1,i2= i2,i1
377                                         
378                                         try:
379                                                 edge_dict[i1,i2]+= 1
380                                         except KeyError:
381                                                 edge_dict[i1,i2]=  1
382                         
383                         # FGons into triangles
384                         if has_ngons and len_face_vert_loc_indicies > 4:
385                                 
386                                 ngon_face_indices= BPyMesh.ngon(verts_loc, face_vert_loc_indicies)
387                                 faces.extend(\
388                                 [(\
389                                 [face_vert_loc_indicies[ngon[0]], face_vert_loc_indicies[ngon[1]], face_vert_loc_indicies[ngon[2]] ],\
390                                 [face_vert_tex_indicies[ngon[0]], face_vert_tex_indicies[ngon[1]], face_vert_tex_indicies[ngon[2]] ],\
391                                 context_material,\
392                                 context_smooth_group,\
393                                 context_object)\
394                                 for ngon in ngon_face_indices]\
395                                 )
396                                 
397                                 # edges to make fgons
398                                 if CREATE_FGONS:
399                                         edge_users= {}
400                                         for ngon in ngon_face_indices:
401                                                 for i in (0,1,2):
402                                                         i1= face_vert_loc_indicies[ngon[i  ]]
403                                                         i2= face_vert_loc_indicies[ngon[i-1]]
404                                                         if i1>i2: i1,i2= i2,i1
405                                                         
406                                                         try:
407                                                                 edge_users[i1,i2]+=1
408                                                         except KeyError:
409                                                                 edge_users[i1,i2]= 1
410                                         
411                                         for key, users in edge_users.iteritems():
412                                                 if users>1:
413                                                         fgon_edges[key]= None
414                                 
415                                 # remove all after 3, means we dont have to pop this one.
416                                 faces.pop(f_idx)
417                 
418                 
419         # Build sharp edges
420         if unique_smooth_groups:
421                 for edge_dict in smooth_group_users.itervalues():
422                         for key, users in edge_dict.iteritems():
423                                 if users==1: # This edge is on the boundry of a group
424                                         sharp_edges[key]= None
425         
426         
427         # map the material names to an index
428         material_mapping= dict([(name, i) for i, name in enumerate(unique_materials)]) # enumerate over unique_materials keys()
429         
430         materials= [None] * len(unique_materials)
431         
432         for name, index in material_mapping.iteritems():
433                 materials[index]= unique_materials[name]
434         
435         me= bpy.data.meshes.new(dataname)
436         
437         me.materials= materials[0:16] # make sure the list isnt too big.
438         #me.verts.extend([(0,0,0)]) # dummy vert
439         me.verts.extend(verts_loc)
440         
441         face_mapping= me.faces.extend([f[0] for f in faces], indexList=True)
442         
443         if verts_tex and me.faces:
444                 me.faceUV= 1
445                 # TEXMODE= Mesh.FaceModes['TEX']
446         
447         context_material_old= -1 # avoid a dict lookup
448         mat= 0 # rare case it may be un-initialized.
449         me_faces= me.faces
450         ALPHA= Mesh.FaceTranspModes.ALPHA
451         
452         for i, face in enumerate(faces):
453                 if len(face[0]) < 2:
454                         pass #raise "bad face"
455                 elif len(face[0])==2:
456                         if CREATE_EDGES:
457                                 edges.append(face[0])
458                 else:
459                         face_index_map= face_mapping[i]
460                         if face_index_map!=None: # None means the face wasnt added
461                                 blender_face= me_faces[face_index_map]
462                                 
463                                 face_vert_loc_indicies,\
464                                 face_vert_tex_indicies,\
465                                 context_material,\
466                                 context_smooth_group,\
467                                 context_object= face
468                                 
469                                 
470                                 
471                                 if context_smooth_group:
472                                         blender_face.smooth= True
473                                 
474                                 if context_material:
475                                         if context_material_old is not context_material:
476                                                 mat= material_mapping[context_material]
477                                                 if mat>15:
478                                                         mat= 15
479                                                 context_material_old= context_material
480                                         
481                                         blender_face.mat= mat
482                                 
483                                 
484                                 if verts_tex:   
485                                         if context_material:
486                                                 image, has_data= unique_material_images[context_material]
487                                                 if image: # Can be none if the material dosnt have an image.
488                                                         blender_face.image= image
489                                                         if has_data and image.depth == 32:
490                                                                 blender_face.transp |= ALPHA
491                                         
492                                         # BUG - Evil eekadoodle problem where faces that have vert index 0 location at 3 or 4 are shuffled.
493                                         if len(face_vert_loc_indicies)==4:
494                                                 if face_vert_loc_indicies[2]==0 or face_vert_loc_indicies[3]==0:
495                                                         face_vert_tex_indicies= face_vert_tex_indicies[2], face_vert_tex_indicies[3], face_vert_tex_indicies[0], face_vert_tex_indicies[1]
496                                         else: # length of 3
497                                                 if face_vert_loc_indicies[2]==0:
498                                                         face_vert_tex_indicies= face_vert_tex_indicies[1], face_vert_tex_indicies[2], face_vert_tex_indicies[0]
499                                         # END EEEKADOODLE FIX
500                                         
501                                         # assign material, uv's and image
502                                         for ii, uv in enumerate(blender_face.uv):
503                                                 uv.x, uv.y=  verts_tex[face_vert_tex_indicies[ii]]
504         del me_faces
505         del ALPHA
506         
507         # Add edge faces.
508         me_edges= me.edges
509         if CREATE_FGONS and fgon_edges:
510                 FGON= Mesh.EdgeFlags.FGON
511                 for ed in me.findEdges( fgon_edges.keys() ):
512                         if ed!=None:
513                                 me_edges[ed].flag |= FGON
514                 del FGON
515         
516         if unique_smooth_groups and sharp_edges:
517                 SHARP= Mesh.EdgeFlags.SHARP
518                 for ed in me.findEdges( sharp_edges.keys() ):
519                         if ed!=None:
520                                 me_edges[ed].flag |= SHARP
521                 del SHARP
522         
523         if CREATE_EDGES:
524                 me_edges.extend( edges )
525         
526         del me_edges
527         
528         me.calcNormals()
529         
530         ob= scn.objects.new(me)
531         new_objects.append(ob)
532
533         # Create the vertex groups. No need to have the flag passed here since we test for the 
534         # content of the vertex_groups. If the user selects to NOT have vertex groups saved then
535         # the following test will never run
536         for group_name, group_indicies in vertex_groups.iteritems():
537                 me.addVertGroup(group_name)
538                 me.assignVertsToGroup(group_name, group_indicies,1.00, Mesh.AssignModes.REPLACE)
539
540
541 def create_nurbs(scn, context_nurbs, vert_loc, new_objects):
542         '''
543         Add nurbs object to blender, only support one type at the moment
544         '''
545         deg = context_nurbs.get('deg', (3,))
546         curv_range = context_nurbs.get('curv_range', None)
547         curv_idx = context_nurbs.get('curv_idx', [])
548         parm_u = context_nurbs.get('parm_u', [])
549         parm_v = context_nurbs.get('parm_v', [])
550         name = context_nurbs.get('name', 'ObjNurb')
551         cstype = context_nurbs.get('cstype', None)
552         
553         if cstype == None:
554                 print '\tWarning, cstype not found'
555                 return
556         if cstype != 'bspline':
557                 print '\tWarning, cstype is not supported (only bspline)'
558                 return
559         if not curv_idx:
560                 print '\tWarning, curv argument empty or not set'
561                 return
562         if len(deg) > 1 or parm_v:
563                 print '\tWarning, surfaces not supported'
564                 return
565         
566         cu = bpy.data.curves.new(name, 'Curve')
567         cu.flag |= 1 # 3D curve
568         
569         nu = None
570         for pt in curv_idx:
571                 
572                 pt = vert_loc[pt]
573                 pt = (pt[0], pt[1], pt[2], 1.0)
574                 
575                 if nu == None:
576                         nu = cu.appendNurb(pt)
577                 else:
578                         nu.append(pt)
579         
580         nu.orderU = deg[0]+1
581         
582         # get for endpoint flag from the weighting
583         if curv_range and len(parm_u) > deg[0]+1:
584                 do_endpoints = True
585                 for i in xrange(deg[0]+1):
586                         
587                         if abs(parm_u[i]-curv_range[0]) > 0.0001:
588                                 do_endpoints = False
589                                 break
590                         
591                         if abs(parm_u[-(i+1)]-curv_range[1]) > 0.0001:
592                                 do_endpoints = False
593                                 break
594                         
595         else:
596                 do_endpoints = False
597         
598         if do_endpoints:
599                 nu.flagU |= 2
600         
601         
602         # close
603         '''
604         do_closed = False
605         if len(parm_u) > deg[0]+1:
606                 for i in xrange(deg[0]+1):
607                         #print curv_idx[i], curv_idx[-(i+1)]
608                         
609                         if curv_idx[i]==curv_idx[-(i+1)]:
610                                 do_closed = True
611                                 break
612         
613         if do_closed:
614                 nu.flagU |= 1
615         '''
616         
617         ob = scn.objects.new(cu)
618         new_objects.append(ob)
619
620
621 def strip_slash(line_split):
622         if line_split[-1][-1]== '\\':
623                 if len(line_split[-1])==1:
624                         line_split.pop() # remove the \ item
625                 else:
626                         line_split[-1]= line_split[-1][:-1] # remove the \ from the end last number
627                 return True
628         return False
629
630
631
632 def get_float_func(filepath):
633         '''
634         find the float function for this obj file
635         - weather to replace commas or not
636         '''
637         file= open(filepath, 'rU')
638         for line in file: #.xreadlines():
639                 line = line.lstrip()
640                 if line.startswith('v'): # vn vt v 
641                         if ',' in line:
642                                 return lambda f: float(f.replace(',', '.'))
643                         elif '.' in line:
644                                 return float
645         
646         # incase all vert values were ints 
647         return float
648
649 def load_obj(filepath,
650                                                  CLAMP_SIZE= 0.0, 
651                                                  CREATE_FGONS= True, 
652                                                  CREATE_SMOOTH_GROUPS= True, 
653                                                  CREATE_EDGES= True, 
654                                                  SPLIT_OBJECTS= True, 
655                                                  SPLIT_GROUPS= True, 
656                                                  SPLIT_MATERIALS= True, 
657                                                  ROTATE_X90= True, 
658                                                  IMAGE_SEARCH=True,
659                                                  POLYGROUPS=False):
660         '''
661         Called by the user interface or another script.
662         load_obj(path) - should give acceptable results.
663         This function passes the file and sends the data off
664                 to be split into objects and then converted into mesh objects
665         '''
666         print '\nimporting obj "%s"' % filepath
667         
668         if SPLIT_OBJECTS or SPLIT_GROUPS or SPLIT_MATERIALS:
669                 POLYGROUPS = False
670         
671         time_main= sys.time()
672         
673         verts_loc= []
674         verts_tex= []
675         faces= [] # tuples of the faces
676         material_libs= [] # filanems to material libs this uses
677         vertex_groups = {} # when POLYGROUPS is true
678         
679         # Get the string to float conversion func for this file- is 'float' for almost all files.
680         float_func= get_float_func(filepath)
681         
682         # Context variables
683         context_material= None
684         context_smooth_group= None
685         context_object= None
686         context_vgroup = None
687         
688         # Nurbs
689         context_nurbs = {}
690         nurbs = []
691         context_parm = '' # used by nurbs too but could be used elsewhere
692
693         has_ngons= False
694         # has_smoothgroups= False - is explicit with len(unique_smooth_groups) being > 0
695         
696         # Until we can use sets
697         unique_materials= {}
698         unique_material_images= {}
699         unique_smooth_groups= {}
700         # unique_obects= {} - no use for this variable since the objects are stored in the face.
701         
702         # when there are faces that end with \
703         # it means they are multiline- 
704         # since we use xreadline we cant skip to the next line
705         # so we need to know weather 
706         context_multi_line= ''
707         
708         print '\tparsing obj file "%s"...' % filepath,
709         time_sub= sys.time()
710
711         file= open(filepath, 'rU')
712         for line in file: #.xreadlines():
713                 line = line.lstrip() # rare cases there is white space at the start of the line
714                 
715                 if line.startswith('v '):
716                         line_split= line.split()
717                         # rotate X90: (x,-z,y)
718                         verts_loc.append( (float_func(line_split[1]), -float_func(line_split[3]), float_func(line_split[2])) )
719                                 
720                 elif line.startswith('vn '):
721                         pass
722                 
723                 elif line.startswith('vt '):
724                         line_split= line.split()
725                         verts_tex.append( (float_func(line_split[1]), float_func(line_split[2])) ) 
726                 
727                 # Handel faces lines (as faces) and the second+ lines of fa multiline face here
728                 # use 'f' not 'f ' because some objs (very rare have 'fo ' for faces)
729                 elif line.startswith('f') or context_multi_line == 'f':
730                         
731                         if context_multi_line:
732                                 # use face_vert_loc_indicies and face_vert_tex_indicies previously defined and used the obj_face
733                                 line_split= line.split()
734                                 
735                         else:
736                                 line_split= line[2:].split()
737                                 face_vert_loc_indicies= []
738                                 face_vert_tex_indicies= []
739                                 
740                                 # Instance a face
741                                 faces.append((\
742                                 face_vert_loc_indicies,\
743                                 face_vert_tex_indicies,\
744                                 context_material,\
745                                 context_smooth_group,\
746                                 context_object\
747                                 ))
748                         
749                         if strip_slash(line_split):
750                                 context_multi_line = 'f'
751                         else:
752                                 context_multi_line = ''
753                         
754                         for v in line_split:
755                                 obj_vert= v.split('/')
756                                 
757                                 vert_loc_index= int(obj_vert[0])-1
758                                 # Add the vertex to the current group
759                                 # *warning*, this wont work for files that have groups defined around verts
760                                 if      POLYGROUPS and context_vgroup:
761                                         vertex_groups[context_vgroup].append(vert_loc_index)
762                                 
763                                 # Make relative negative vert indicies absolute
764                                 if vert_loc_index < 0:
765                                         vert_loc_index= len(verts_loc) + vert_loc_index + 1
766                                 
767                                 face_vert_loc_indicies.append(vert_loc_index)
768                                 
769                                 if len(obj_vert)>1 and obj_vert[1]:
770                                         # formatting for faces with normals and textures us 
771                                         # loc_index/tex_index/nor_index
772                                         
773                                         vert_tex_index= int(obj_vert[1])-1
774                                         # Make relative negative vert indicies absolute
775                                         if vert_tex_index < 0:
776                                                 vert_tex_index= len(verts_tex) + vert_tex_index + 1
777                                         
778                                         face_vert_tex_indicies.append(vert_tex_index)
779                                 else:
780                                         # dummy
781                                         face_vert_tex_indicies.append(0)
782                         
783                         if len(face_vert_loc_indicies) > 4:
784                                 has_ngons= True
785                 
786                 elif CREATE_EDGES and (line.startswith('l ') or context_multi_line == 'l'):
787                         # very similar to the face load function above with some parts removed
788                         
789                         if context_multi_line:
790                                 # use face_vert_loc_indicies and face_vert_tex_indicies previously defined and used the obj_face
791                                 line_split= line.split()
792                                 
793                         else:
794                                 line_split= line[2:].split()
795                                 face_vert_loc_indicies= []
796                                 face_vert_tex_indicies= []
797                                 
798                                 # Instance a face
799                                 faces.append((\
800                                 face_vert_loc_indicies,\
801                                 face_vert_tex_indicies,\
802                                 context_material,\
803                                 context_smooth_group,\
804                                 context_object\
805                                 ))
806                         
807                         if strip_slash(line_split):
808                                 context_multi_line = 'l'
809                         else:
810                                 context_multi_line = ''
811                         
812                         isline= line.startswith('l')
813                         
814                         for v in line_split:
815                                 vert_loc_index= int(v)-1
816                                 
817                                 # Make relative negative vert indicies absolute
818                                 if vert_loc_index < 0:
819                                         vert_loc_index= len(verts_loc) + vert_loc_index + 1
820                                 
821                                 face_vert_loc_indicies.append(vert_loc_index)
822                 
823                 elif line.startswith('s'):
824                         if CREATE_SMOOTH_GROUPS:
825                                 context_smooth_group= line_value(line.split())
826                                 if context_smooth_group=='off':
827                                         context_smooth_group= None
828                                 elif context_smooth_group: # is not None
829                                         unique_smooth_groups[context_smooth_group]= None
830                 
831                 elif line.startswith('o'):
832                         if SPLIT_OBJECTS:
833                                 context_object= line_value(line.split())
834                                 # unique_obects[context_object]= None
835                         
836                 elif line.startswith('g'):
837                         if SPLIT_GROUPS:
838                                 context_object= line_value(line.split())
839                                 # print 'context_object', context_object
840                                 # unique_obects[context_object]= None
841                         elif POLYGROUPS:
842                                 context_vgroup = line_value(line.split())
843                                 if context_vgroup and context_vgroup != '(null)':
844                                         vertex_groups.setdefault(context_vgroup, [])
845                                 else:
846                                         context_vgroup = None # dont assign a vgroup
847                 
848                 elif line.startswith('usemtl'):
849                         context_material= line_value(line.split())
850                         unique_materials[context_material]= None
851                 elif line.startswith('mtllib'): # usemap or usemat
852                         material_libs.extend( line.split()[1:] ) # can have multiple mtllib filenames per line
853                         
854                         
855                         # Nurbs support
856                 elif line.startswith('cstype '):
857                         context_nurbs['cstype']= line_value(line.split()) # 'rat bspline' / 'bspline'
858                 elif line.startswith('curv ') or context_multi_line == 'curv':
859                         line_split= line.split()
860                         
861                         curv_idx = context_nurbs['curv_idx'] = context_nurbs.get('curv_idx', []) # incase were multiline
862                         
863                         if not context_multi_line:
864                                 context_nurbs['curv_range'] = float_func(line_split[1]), float_func(line_split[2])
865                                 line_split[0:3] = [] # remove first 3 items
866                         
867                         if strip_slash(line_split):
868                                 context_multi_line = 'curv'
869                         else:
870                                 context_multi_line = ''
871                                 
872                         
873                         for i in line_split:
874                                 vert_loc_index = int(i)-1
875                                 
876                                 if vert_loc_index < 0:
877                                         vert_loc_index= len(verts_loc) + vert_loc_index + 1
878                                 
879                                 curv_idx.append(vert_loc_index)
880                         
881                 elif line.startswith('parm') or context_multi_line == 'parm':
882                         line_split= line.split()
883                         
884                         if context_multi_line:
885                                 context_multi_line = ''
886                         else:
887                                 context_parm = line_split[1]
888                                 line_split[0:2] = [] # remove first 2
889                         
890                         if strip_slash(line_split):
891                                 context_multi_line = 'parm'
892                         else:
893                                 context_multi_line = ''
894                         
895                         if context_parm.lower() == 'u':
896                                 context_nurbs.setdefault('parm_u', []).extend( [float_func(f) for f in line_split] )
897                         elif context_parm.lower() == 'v': # surfaces not suported yet
898                                 context_nurbs.setdefault('parm_v', []).extend( [float_func(f) for f in line_split] )
899                         # else: # may want to support other parm's ?
900                 
901                 elif line.startswith('deg '):
902                         context_nurbs['deg']= [int(i) for i in line.split()[1:]]
903                 elif line.startswith('end'):
904                         # Add the nurbs curve
905                         if context_object:
906                                 context_nurbs['name'] = context_object
907                         nurbs.append(context_nurbs)
908                         context_nurbs = {}
909                         context_parm = ''
910                 
911                 ''' # How to use usemap? depricated?
912                 elif line.startswith('usema'): # usemap or usemat
913                         context_image= line_value(line.split())
914                 '''
915         
916         file.close()
917         time_new= sys.time()
918         print '%.4f sec' % (time_new-time_sub)
919         time_sub= time_new
920         
921         
922         print '\tloading materials and images...',
923         create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH)
924         
925         time_new= sys.time()
926         print '%.4f sec' % (time_new-time_sub)
927         time_sub= time_new
928         
929         if not ROTATE_X90:
930                 verts_loc[:] = [(v[0], v[2], -v[1]) for v in verts_loc]
931         
932         # deselect all
933         scn = bpy.data.scenes.active
934         scn.objects.selected = []
935         new_objects= [] # put new objects here
936         
937         print '\tbuilding geometry...\n\tverts:%i faces:%i materials: %i smoothgroups:%i ...' % ( len(verts_loc), len(faces), len(unique_materials), len(unique_smooth_groups) ),
938         # Split the mesh by objects/materials, may 
939         if SPLIT_OBJECTS or SPLIT_GROUPS:       SPLIT_OB_OR_GROUP = True
940         else:                                                           SPLIT_OB_OR_GROUP = False
941         
942         for verts_loc_split, faces_split, unique_materials_split, dataname in split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP, SPLIT_MATERIALS):
943                 # Create meshes from the data, warning 'vertex_groups' wont support splitting
944                 create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc_split, verts_tex, faces_split, unique_materials_split, unique_material_images, unique_smooth_groups, vertex_groups, dataname)
945         
946         # nurbs support
947         for context_nurbs in nurbs:
948                 create_nurbs(scn, context_nurbs, verts_loc, new_objects)
949         
950         
951         axis_min= [ 1000000000]*3
952         axis_max= [-1000000000]*3
953         
954         if CLAMP_SIZE:
955                 # Get all object bounds
956                 for ob in new_objects:
957                         for v in ob.getBoundBox():
958                                 for axis, value in enumerate(v):
959                                         if axis_min[axis] > value:      axis_min[axis]= value
960                                         if axis_max[axis] < value:      axis_max[axis]= value
961                 
962                 # Scale objects
963                 max_axis= max(axis_max[0]-axis_min[0], axis_max[1]-axis_min[1], axis_max[2]-axis_min[2])
964                 scale= 1.0
965                 
966                 while CLAMP_SIZE < max_axis * scale:
967                         scale= scale/10.0
968                 
969                 for ob in new_objects:
970                         ob.setSize(scale, scale, scale)
971         
972         # Better rotate the vert locations
973         #if not ROTATE_X90:
974         #       for ob in new_objects:
975         #               ob.RotX = -1.570796326794896558
976         
977         time_new= sys.time()
978         
979         print '%.4f sec' % (time_new-time_sub)
980         print 'finished importing: "%s" in %.4f sec.' % (filepath, (time_new-time_main))
981
982
983 DEBUG= True
984
985
986 def load_obj_ui(filepath, BATCH_LOAD= False):
987         if BPyMessages.Error_NoFile(filepath):
988                 return
989         
990         global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90
991         
992         CREATE_SMOOTH_GROUPS= Draw.Create(0)
993         CREATE_FGONS= Draw.Create(1)
994         CREATE_EDGES= Draw.Create(1)
995         SPLIT_OBJECTS= Draw.Create(0)
996         SPLIT_GROUPS= Draw.Create(0)
997         SPLIT_MATERIALS= Draw.Create(0)
998         CLAMP_SIZE= Draw.Create(10.0)
999         IMAGE_SEARCH= Draw.Create(1)
1000         POLYGROUPS= Draw.Create(0)
1001         KEEP_VERT_ORDER= Draw.Create(1)
1002         ROTATE_X90= Draw.Create(1)
1003         
1004         
1005         # Get USER Options
1006         # Note, Works but not pretty, instead use a more complicated GUI
1007         '''
1008         pup_block= [\
1009         'Import...',\
1010         ('Smooth Groups', CREATE_SMOOTH_GROUPS, 'Surround smooth groups by sharp edges'),\
1011         ('Create FGons', CREATE_FGONS, 'Import faces with more then 4 verts as fgons.'),\
1012         ('Lines', CREATE_EDGES, 'Import lines and faces with 2 verts as edges'),\
1013         'Separate objects from obj...',\
1014         ('Object', SPLIT_OBJECTS, 'Import OBJ Objects into Blender Objects'),\
1015         ('Group', SPLIT_GROUPS, 'Import OBJ Groups into Blender Objects'),\
1016         ('Material', SPLIT_MATERIALS, 'Import each material into a seperate mesh (Avoids > 16 per mesh error)'),\
1017         'Options...',\
1018         ('Keep Vert Order', KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\
1019         ('Clamp Scale:', CLAMP_SIZE, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)'),\
1020         ('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\
1021         ]
1022         
1023         if not Draw.PupBlock('Import OBJ...', pup_block):
1024                 return
1025         
1026         if KEEP_VERT_ORDER.val:
1027                 SPLIT_OBJECTS.val = False
1028                 SPLIT_GROUPS.val = False
1029                 SPLIT_MATERIALS.val = False
1030         '''
1031         
1032         
1033         
1034         # BEGIN ALTERNATIVE UI *******************
1035         if True: 
1036                 
1037                 EVENT_NONE = 0
1038                 EVENT_EXIT = 1
1039                 EVENT_REDRAW = 2
1040                 EVENT_IMPORT = 3
1041                 
1042                 GLOBALS = {}
1043                 GLOBALS['EVENT'] = EVENT_REDRAW
1044                 #GLOBALS['MOUSE'] = Window.GetMouseCoords()
1045                 GLOBALS['MOUSE'] = [i/2 for i in Window.GetScreenSize()]
1046                 
1047                 def obj_ui_set_event(e,v):
1048                         GLOBALS['EVENT'] = e
1049                 
1050                 def do_split(e,v):
1051                         global SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, KEEP_VERT_ORDER, POLYGROUPS
1052                         if SPLIT_OBJECTS.val or SPLIT_GROUPS.val or SPLIT_MATERIALS.val:
1053                                 KEEP_VERT_ORDER.val = 0
1054                                 POLYGROUPS.val = 0
1055                         else:
1056                                 KEEP_VERT_ORDER.val = 1
1057                         
1058                 def do_vertorder(e,v):
1059                         global SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, KEEP_VERT_ORDER
1060                         if KEEP_VERT_ORDER.val:
1061                                 SPLIT_OBJECTS.val = SPLIT_GROUPS.val = SPLIT_MATERIALS.val = 0
1062                         else:
1063                                 if not (SPLIT_OBJECTS.val or SPLIT_GROUPS.val or SPLIT_MATERIALS.val):
1064                                         KEEP_VERT_ORDER.val = 1
1065                         
1066                 def do_polygroups(e,v):
1067                         global SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, KEEP_VERT_ORDER, POLYGROUPS
1068                         if POLYGROUPS.val:
1069                                 SPLIT_OBJECTS.val = SPLIT_GROUPS.val = SPLIT_MATERIALS.val = 0
1070                         
1071                 def do_help(e,v):
1072                         url = __url__[0]
1073                         print 'Trying to open web browser with documentation at this address...'
1074                         print '\t' + url
1075                         
1076                         try:
1077                                 import webbrowser
1078                                 webbrowser.open(url)
1079                         except:
1080                                 print '...could not open a browser window.'
1081                 
1082                 def obj_ui():
1083                         ui_x, ui_y = GLOBALS['MOUSE']
1084                         
1085                         # Center based on overall pup size
1086                         ui_x -= 165
1087                         ui_y -= 90
1088                         
1089                         global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90
1090                         
1091                         Draw.Label('Import...', ui_x+9, ui_y+159, 220, 21)
1092                         Draw.BeginAlign()
1093                         CREATE_SMOOTH_GROUPS = Draw.Toggle('Smooth Groups', EVENT_NONE, ui_x+9, ui_y+139, 110, 20, CREATE_SMOOTH_GROUPS.val, 'Surround smooth groups by sharp edges')
1094                         CREATE_FGONS = Draw.Toggle('NGons as FGons', EVENT_NONE, ui_x+119, ui_y+139, 110, 20, CREATE_FGONS.val, 'Import faces with more then 4 verts as fgons')
1095                         CREATE_EDGES = Draw.Toggle('Lines as Edges', EVENT_NONE, ui_x+229, ui_y+139, 110, 20, CREATE_EDGES.val, 'Import lines and faces with 2 verts as edges')
1096                         Draw.EndAlign()
1097                         
1098                         Draw.Label('Separate objects by OBJ...', ui_x+9, ui_y+110, 220, 20)
1099                         Draw.BeginAlign()
1100                         SPLIT_OBJECTS = Draw.Toggle('Object', EVENT_REDRAW, ui_x+9, ui_y+89, 55, 21, SPLIT_OBJECTS.val, 'Import OBJ Objects into Blender Objects', do_split)
1101                         SPLIT_GROUPS = Draw.Toggle('Group', EVENT_REDRAW, ui_x+64, ui_y+89, 55, 21, SPLIT_GROUPS.val, 'Import OBJ Groups into Blender Objects', do_split)
1102                         SPLIT_MATERIALS = Draw.Toggle('Material', EVENT_REDRAW, ui_x+119, ui_y+89, 60, 21, SPLIT_MATERIALS.val, 'Import each material into a seperate mesh (Avoids > 16 per mesh error)', do_split)
1103                         Draw.EndAlign()
1104                         
1105                         # Only used for user feedback
1106                         KEEP_VERT_ORDER = Draw.Toggle('Keep Vert Order', EVENT_REDRAW, ui_x+184, ui_y+89, 113, 21, KEEP_VERT_ORDER.val, 'Keep vert and face order, disables split options, enable for morph targets', do_vertorder)
1107                         
1108                         ROTATE_X90 = Draw.Toggle('-X90', EVENT_REDRAW, ui_x+302, ui_y+89, 38, 21, ROTATE_X90.val, 'Rotate X 90.')
1109                         
1110                         Draw.Label('Options...', ui_x+9, ui_y+60, 211, 20)
1111                         CLAMP_SIZE = Draw.Number('Clamp Scale: ', EVENT_NONE, ui_x+9, ui_y+39, 130, 21, CLAMP_SIZE.val, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)')
1112                         POLYGROUPS = Draw.Toggle('Poly Groups', EVENT_REDRAW, ui_x+144, ui_y+39, 90, 21, POLYGROUPS.val, 'Import OBJ groups as vertex groups.', do_polygroups)
1113                         IMAGE_SEARCH = Draw.Toggle('Image Search', EVENT_NONE, ui_x+239, ui_y+39, 100, 21, IMAGE_SEARCH.val, 'Search subdirs for any assosiated images (Warning, may be slow)')
1114                         Draw.BeginAlign()
1115                         Draw.PushButton('Online Help', EVENT_REDRAW, ui_x+9, ui_y+9, 110, 21, 'Load the wiki page for this script', do_help)
1116                         Draw.PushButton('Cancel', EVENT_EXIT, ui_x+119, ui_y+9, 110, 21, '', obj_ui_set_event)
1117                         Draw.PushButton('Import', EVENT_IMPORT, ui_x+229, ui_y+9, 110, 21, 'Import with these settings', obj_ui_set_event)
1118                         Draw.EndAlign()
1119                         
1120                 
1121                 # hack so the toggle buttons redraw. this is not nice at all
1122                 while GLOBALS['EVENT'] not in (EVENT_EXIT, EVENT_IMPORT):
1123                         Draw.UIBlock(obj_ui, 0)
1124                 
1125                 if GLOBALS['EVENT'] != EVENT_IMPORT:
1126                         return
1127                 
1128         # END ALTERNATIVE UI *********************
1129         
1130         
1131         
1132         
1133         
1134         
1135         
1136         Window.WaitCursor(1)
1137         
1138         if BATCH_LOAD: # load the dir
1139                 try:
1140                         files= [ f for f in os.listdir(filepath) if f.lower().endswith('.obj') ]
1141                 except:
1142                         Window.WaitCursor(0)
1143                         Draw.PupMenu('Error%t|Could not open path ' + filepath)
1144                         return
1145                 
1146                 if not files:
1147                         Window.WaitCursor(0)
1148                         Draw.PupMenu('Error%t|No files at path ' + filepath)
1149                         return
1150                 
1151                 for f in files:
1152                         scn= bpy.data.scenes.new( stripExt(f) )
1153                         scn.makeCurrent()
1154                         
1155                         load_obj(sys.join(filepath, f),\
1156                           CLAMP_SIZE.val,\
1157                           CREATE_FGONS.val,\
1158                           CREATE_SMOOTH_GROUPS.val,\
1159                           CREATE_EDGES.val,\
1160                           SPLIT_OBJECTS.val,\
1161                           SPLIT_GROUPS.val,\
1162                           SPLIT_MATERIALS.val,\
1163                           ROTATE_X90.val,\
1164                           IMAGE_SEARCH.val,\
1165                           POLYGROUPS.val
1166                         )
1167         
1168         else: # Normal load
1169                 load_obj(filepath,\
1170                   CLAMP_SIZE.val,\
1171                   CREATE_FGONS.val,\
1172                   CREATE_SMOOTH_GROUPS.val,\
1173                   CREATE_EDGES.val,\
1174                   SPLIT_OBJECTS.val,\
1175                   SPLIT_GROUPS.val,\
1176                   SPLIT_MATERIALS.val,\
1177                   ROTATE_X90.val,\
1178                   IMAGE_SEARCH.val,\
1179                   POLYGROUPS.val
1180                 )
1181         
1182         Window.WaitCursor(0)
1183
1184
1185 def load_obj_ui_batch(file):
1186         load_obj_ui(file, True)
1187
1188 DEBUG= False
1189
1190 if __name__=='__main__' and not DEBUG:
1191         if os and Window.GetKeyQualifiers() & Window.Qual.SHIFT:
1192                 Window.FileSelector(load_obj_ui_batch, 'Import OBJ Dir', '')
1193         else:
1194                 Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ', '*.obj')
1195
1196         # For testing compatibility
1197 '''
1198 else:
1199         # DEBUG ONLY
1200         TIME= sys.time()
1201         DIR = '/fe/obj'
1202         import os
1203         print 'Searching for files'
1204         def fileList(path):
1205                 for dirpath, dirnames, filenames in os.walk(path):
1206                         for filename in filenames:
1207                                 yield os.path.join(dirpath, filename)
1208         
1209         files = [f for f in fileList(DIR) if f.lower().endswith('.obj')]
1210         files.sort()
1211         
1212         for i, obj_file in enumerate(files):
1213                 if 0 < i < 20:
1214                         print 'Importing', obj_file, '\nNUMBER', i, 'of', len(files)
1215                         newScn= bpy.data.scenes.new(os.path.basename(obj_file))
1216                         newScn.makeCurrent()
1217                         load_obj(obj_file, False, IMAGE_SEARCH=0)
1218
1219         print 'TOTAL TIME: %.6f' % (sys.time() - TIME)
1220 '''
1221 #load_obj('/test.obj')
1222 #load_obj('/fe/obj/mba1.obj')