2.5: Top Menu
[blender.git] / release / scripts / flt_import.py
1 #!BPY
2 """ Registration info for Blender menus:
3 Name: 'OpenFlight (.flt)...'
4 Blender: 245
5 Group: 'Import'
6 Tip: 'Import OpenFlight (.flt)'
7 """
8
9
10
11 __author__ = "Greg MacDonald, Campbell Barton, Geoffrey Bantle"
12 __version__ = "2.0 11/21/07"
13 __url__ = ("blender", "blenderartists.org", "Author's homepage, http://sourceforge.net/projects/blight/")
14 __bpydoc__ = """\
15 This script imports OpenFlight files into Blender. OpenFlight is a
16 registered trademark of MultiGen-Paradigm, Inc.
17
18 Feature overview and more availible at:
19 http://wiki.blender.org/index.php/Scripts/Manual/Import/openflight_fltss
20
21 Note: This file is a grab-bag of old and new code. It needs some cleanup still.
22 """
23
24 # flt_import.py is an OpenFlight importer for blender.
25 # Copyright (C) 2005 Greg MacDonald, 2007  Blender Foundation
26 #
27 # This program is free software; you can redistribute it and/or
28 # modify it under the terms of the GNU General Public License
29 # as published by the Free Software Foundation; either version 2
30 # of the License, or (at your option) any later version.
31 #
32 # This program is distributed in the hope that it will be useful,
33 # but WITHOUT ANY WARRANTY; without even the implied warranty of
34 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35 # GNU General Public License for more details.
36 #
37 # You should have received a copy of the GNU General Public License
38 # along with this program; if not, write to the Free Software
39 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
40
41 import Blender
42 import os
43 import BPyMesh
44 import BPyImage
45 import flt_filewalker 
46 import flt_properties
47 import sys
48 reload(flt_properties)
49 from flt_properties import *
50
51 #Globals. Should Clean these up and minimize their usage.
52
53 typecodes = ['c','C','s','S','i','I','f','d','t']
54 records = dict()
55
56 FLTBaseLabel = None
57 FLTBaseString = None
58 FLTBaseChooser = None
59 FLTExport = None
60 FLTClose = None
61 FLTDoXRef = None
62 FLTScale = None
63 FLTShadeImport = None
64 FLTAttrib = None
65 FLTWarn = None
66
67 Vector= Blender.Mathutils.Vector
68 FLOAT_TOLERANCE = 0.01
69
70 FF = flt_filewalker.FileFinder()
71 current_layer = 0x01
72
73 global_prefs = dict()
74 global_prefs['verbose']= 4
75 global_prefs['get_texture'] = True
76 global_prefs['get_diffuse'] = True
77 global_prefs['get_specular'] = False
78 global_prefs['get_emissive'] = False
79 global_prefs['get_alpha'] = True
80 global_prefs['get_ambient'] = False
81 global_prefs['get_shininess'] = True
82 global_prefs['color_from_face'] = True
83 global_prefs['fltfile']= ''
84 global_prefs['smoothshading'] = 1
85 global_prefs['doxrefs'] = 1
86 global_prefs['scale'] = 1.0
87 global_prefs['attrib'] = 0
88 msg_once = False
89
90 reg = Blender.Registry.GetKey('flt_import',1)
91 if reg:
92         for key in global_prefs:
93                 if reg.has_key(key):
94                         global_prefs[key] = reg[key]
95                 
96
97
98 throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63,111] # Opcodes that indicate its time to return control to parent.
99 do_not_report_opcodes = [76, 78, 79, 80, 81, 82, 94, 83, 33, 112, 101, 102, 97, 31, 103, 104, 117, 118, 120, 121, 124, 125]
100
101 #Process FLT record definitions
102 for record in FLT_Records:
103         props = dict()
104         for prop in FLT_Records[record]:
105                 position = ''
106                 slice = 0
107                 (format,name) = prop.split('!')
108                 for i in format:
109                         if i not in typecodes:
110                                 position = position + i
111                                 slice = slice + 1
112                         else:
113                                 break
114                 type = format[slice:]
115                 length = type[1:] 
116                 if len(length) == 0:
117                         length = 1
118                 else:
119                         type = type[0]
120                         length = int(length)
121                 
122                 props[int(position)] = (type,length,prop)
123         records[record] = props
124
125 def col_to_gray(c):
126         return 0.3*c[0] + 0.59*c[1] + 0.11*c[2]
127 class MaterialDesc:
128         # Was going to use int(f*1000.0) instead of round(f,3), but for some reason
129         # round produces better results, as in less dups.
130         def make_key(self):
131                 key = list()
132                 if global_prefs['get_texture']:
133                         if self.tex0:
134                                 key.append(self.tex0.getName())
135                         else:
136                                 key.append(None)
137                 
138                 if global_prefs['get_alpha']:
139                         key.append(round(self.alpha, 3))
140                 else:
141                         key.append(None)
142                         
143                 if global_prefs['get_shininess']:
144                         key.append(round(self.shininess, 3))
145                 else:
146                         key.append(None)
147                 
148                 if global_prefs['get_emissive']:
149                         key.append(round(self.emissive, 3))
150                 else:
151                         key.append(None)
152                 
153                 if global_prefs['get_ambient']:
154                         key.append(round(self.ambient, 3))
155                 else:
156                         key.append(None)
157                 
158                 if global_prefs['get_specular']:
159                         for n in self.specular:
160                                 key.append(round(n, 3))
161                 else:
162                         key.extend([None, None, None])
163                 
164                 if global_prefs['get_diffuse']:
165                         for n in self.diffuse:
166                                 key.append(round(n, 3))
167                 else:
168                         key.extend([None, None, None])
169                 
170 #        key.extend(self.face_props.values())
171                 
172                 return tuple(key)
173
174         def __init__(self):
175                 self.name = 'Material'
176                 # Colors, List of 3 floats.
177                 self.diffuse = [1.0, 1.0, 1.0]
178                 self.specular = [1.0, 1.0, 1.0]
179
180                 # Scalars
181                 self.ambient = 0.0 # [0.0, 1.0]
182                 self.emissive = 0.0 # [0.0, 1.0]
183                 self.shininess = 0.5 # Range is [0.0, 2.0]
184                 self.alpha = 1.0 # Range is [0.0, 1.0]
185
186                 self.tex0 = None
187                 
188                 # OpenFlight Face attributes
189                 self.face_props = dict.fromkeys(['comment', 'ir color', 'priority', 
190                                                         'draw type', 'texture white', 'template billboard',
191                                                         'smc', 'fid', 'ir material', 'lod generation control',
192                                                         'flags', 'light mode'])
193
194 class VertexDesc:
195         def make_key(self):
196                 return round(self.x, 6), round(self.y, 6), round(self.z, 6)
197                 
198         def __init__(self):
199                 
200                 # Assign later, save memory, all verts have a loc
201                 self.x = 0.0
202                 self.y = 0.0
203                 self.z = 0.0
204                 
205                 
206                 self.nx = 0.0
207                 self.ny = 0.0
208                 self.nz = 0.0
209                 
210                 self.uv= Vector(0,0)
211                 self.cindex = 127 #default/lowest
212                 self.cnorm = False        
213
214 class LightPointAppDesc:
215         def make_key(self):
216                 d = dict(self.props)
217                 del d['id']
218                 del d['type']
219                 
220                 if d['directionality'] != 0: # not omni
221                         d['nx'] = 0.0
222                         d['ny'] = 0.0
223                         d['nz'] = 0.0
224                 
225                 return tuple(d.values())
226                 
227         def __init__(self):
228                 self.props = dict()
229                 self.props.update({'type': 'LPA'})
230                 self.props.update({'id': 'ap'})
231                 # Attribs not found in inline lightpoint.
232                 self.props.update({'visibility range': 0.0})
233                 self.props.update({'fade range ratio': 0.0})
234                 self.props.update({'fade in duration': 0.0})
235                 self.props.update({'fade out duration': 0.0})
236                 self.props.update({'LOD range ratio': 0.0})
237                 self.props.update({'LOD scale': 0.0})
238
239 class GlobalResourceRepository:
240         def request_lightpoint_app(self, desc, scene):
241                 match = self.light_point_app.get(desc.make_key())
242                 
243                 if match:
244                         return match.getName()
245                 else:
246                         # Create empty and fill with properties.
247                         name = desc.props['type'] + ': ' + desc.props['id']
248                         object = Blender.Object.New('Empty', name)
249                         scene.objects.link(object)
250                         object.Layers= current_layer
251                         object.sel= 1
252                         
253                         # Attach properties
254                         for name, value in desc.props.iteritems():
255                                 object.addProperty(name, value)
256                         
257                         self.light_point_app.update({desc.make_key(): object})
258                         
259                         return object.getName()
260         
261         # Dont use request_vert - faster to make it from the vector direct.
262         """
263         def request_vert(self, desc):
264                 match = self.vert_dict.get(desc.make_key())
265
266                 if match:
267                         return match
268                 else:
269                         vert = Blender.Mathutils.Vector(desc.x, desc.y, desc.z)
270                         ''' IGNORE_NORMALS
271                         vert.no[0] = desc.nx
272                         vert.no[1] = desc.ny
273                         vert.no[2] = desc.nz
274                         '''
275                         self.vert_dict.update({desc.make_key(): vert})
276                         return vert
277         """
278         def request_mat(self, mat_desc):
279                 match = self.mat_dict.get(mat_desc.make_key())
280                 if match: return match
281                 
282                 mat = Blender.Material.New(mat_desc.name)
283
284                 if mat_desc.tex0 != None:
285                         mat.setTexture(0, mat_desc.tex0, Blender.Texture.TexCo.UV)
286
287                 mat.setAlpha(mat_desc.alpha)
288                 mat.setSpec(mat_desc.shininess)
289                 mat.setHardness(255)
290                 mat.setEmit(mat_desc.emissive)
291                 mat.setAmb(mat_desc.ambient)
292                 mat.setSpecCol(mat_desc.specular)
293                 mat.setRGBCol(mat_desc.diffuse)
294                 
295                 # Create a text object to store openflight face attribs until
296                 # user properties can be set on materials.
297 #        t = Blender.Text.New('FACE: ' + mat.getName())
298 #
299 #        for name, value in mat_desc.face_props.items():
300 #            t.write(name + '\n' + str(value) + '\n\n')    
301                                 
302                 self.mat_dict.update({mat_desc.make_key(): mat})
303
304                 return mat
305                 
306         def request_image(self, filename_with_path):
307                 if not global_prefs['get_texture']: return None
308                 return BPyImage.comprehensiveImageLoad(filename_with_path, global_prefs['fltfile']) # Use join in case of spaces 
309                 
310         def request_texture(self, image):
311                 if not global_prefs['get_texture']:
312                         return None
313
314                 tex = self.tex_dict.get(image.filename)
315                 if tex: return tex
316                 
317                 tex = Blender.Texture.New(Blender.sys.basename(image.filename))
318                 tex.setImage(image)
319                 tex.setType('Image')
320                 self.tex_dict.update({image.filename: tex})
321                 return tex
322                 
323         def __init__(self):
324                 
325                 #list of scenes xrefs belong to.
326                 self.xrefs = dict()
327                 # material
328                 self.mat_dict = dict()
329                 mat_lst = Blender.Material.Get()
330                 for mat in mat_lst:
331                         mat_desc = MaterialDesc()
332                         mapto_lst = mat.getTextures()
333                         if mapto_lst[0]:
334                                 mat_desc.tex0 = mapto_lst[0].tex
335                         else:
336                                 mat_desc.tex0 = None
337                         mat_desc.alpha = mat.getAlpha()
338                         mat_desc.shininess = mat.getSpec()
339                         mat_desc.emissive = mat.getEmit()
340                         mat_desc.ambient = mat.getAmb()
341                         mat_desc.specular = mat.getSpecCol()
342                         mat_desc.diffuse = mat.getRGBCol()
343                         
344                         self.mat_dict.update({mat_desc.make_key(): mat})
345                         
346                 # texture
347                 self.tex_dict = dict()
348                 tex_lst = Blender.Texture.Get()
349                 
350                 for tex in tex_lst:
351                         img = tex.getImage()
352                         # Only interested in textures with images.
353                         if img:
354                                 self.tex_dict.update({img.filename: tex})
355                         
356                 # vertex
357                 # self.vert_dict = dict()
358                 
359                 # light point
360                 self.light_point_app = dict()
361                 
362 class Handler:
363         def in_throw_back_lst(self, opcode):
364                 return opcode in self.throw_back_lst
365                 
366         def handle(self, opcode):
367                 return self.handler[opcode]()
368         
369         def handles(self, opcode):
370                 return opcode in self.handler.iterkeys()
371         
372         def throws_back_all_unhandled(self):
373                 return self.throw_back_unhandled
374                 
375         def set_throw_back_lst(self, a):
376                 self.throw_back_lst = a
377                 
378         def set_throw_back_all_unhandled(self):
379                 self.throw_back_unhandled = True
380                 
381         def set_only_throw_back_specified(self):
382                 self.throw_back_unhandled = False
383                 
384         def set_handler(self, d):
385                 self.handler = d
386                 
387         def __init__(self):
388                 # Dictionary of opcodes to handler methods.
389                 self.handler = dict()
390                 # Send all opcodes not handled to the parent node.
391                 self.throw_back_unhandled = False
392                 # If throw_back_unhandled is False then only throw back
393                 # if the opcodes in throw_back are encountered.
394                 self.throw_back_lst = list()
395                 
396 class Node:
397         def blender_import(self):
398                 if self.opcode in opcode_name and global_prefs['verbose'] >= 2:
399                         for i in xrange(self.get_level()):
400                                 print ' ',
401                         print opcode_name[self.opcode],
402                         print '-', self.props['id'],
403                         print '-', self.props['comment'],
404
405                         print
406                 
407                 for child in self.children:
408                         child.blender_import()
409                         
410 # Import comment.
411 #        if self.props['comment'] != '':
412 #            name = 'COMMENT: ' + self.props['id']
413 #            t = Blender.Text.New(name)
414 #            t.write(self.props['comment'])
415 #            self.props['comment'] = name
416                 
417         # Always ignore extensions and anything in between them.
418         def parse_push_extension(self):
419                 self.saved_handler = self.active_handler
420                 self.active_handler = self.extension_handler
421                 return True
422         
423         def parse_pop_extension(self):
424                 self.active_handler = self.saved_handler
425                 return True
426         
427         def parse_push(self):
428                 self.header.fw.up_level()
429                 # Ignore unknown children.
430                 self.ignore_unhandled = True
431                 # Don't do child records that might overwrite parent info. ex: longid
432                 self.active_handler = self.child_handler
433                 return True
434                 
435         def parse_pop(self):
436                 self.header.fw.down_level()
437                 
438                 if self.header.fw.get_level() == self.level:
439                         return False
440                 
441                 return True
442         
443         def parse(self):
444                 while self.header.fw.begin_record():
445                         opcode = self.header.fw.get_opcode()
446
447                         # Print out info on opcode and tree level.
448                         if global_prefs['verbose'] >= 3:
449                                 p = ''
450                                 for i in xrange(self.header.fw.get_level()):
451                                         p = p + '  '
452                                 if opcode in opcode_name:
453                                         p = p + opcode_name[opcode]
454                                 else:
455                                         if global_prefs['verbose'] >= 1:
456                                                 print 'undocumented opcode', opcode
457                                         continue
458                                                         
459                         if self.global_handler.handles(opcode):
460                                 if global_prefs['verbose'] >= 3:
461                                         print p + ' handled globally'
462                                 if self.global_handler.handle(opcode) == False:
463                                         break
464                                         
465                         elif self.active_handler.handles(opcode):
466                                 if global_prefs['verbose'] >= 4:
467                                         print p + ' handled'
468                                 if self.active_handler.handle(opcode) == False:
469                                         break
470                                         
471                         else:
472                                 if self.active_handler.throws_back_all_unhandled():
473                                         if global_prefs['verbose'] >= 3:
474                                                 print p + ' handled elsewhere'              
475                                         self.header.fw.repeat_record()
476                                         break
477
478                                 elif self.active_handler.in_throw_back_lst(opcode):
479                                         if global_prefs['verbose'] >= 3:
480                                                 print p + ' handled elsewhere'              
481                                         self.header.fw.repeat_record()
482                                         break
483
484                                 else:
485                                         if global_prefs['verbose'] >= 3:
486                                                 print p + ' ignored'
487                                         elif global_prefs['verbose'] >= 1 and not opcode in do_not_report_opcodes and opcode in opcode_name:   
488                                                 print 'not handled'
489                                         
490         def get_level(self):
491                 return self.level
492                 
493         def parse_long_id(self):
494                 self.props['id'] = self.header.fw.read_string(self.header.fw.get_length()-4)
495                 return True
496
497         def parse_comment(self):
498                 self.props['comment'] = self.header.fw.read_string(self.header.fw.get_length()-4)
499                 return True
500         
501         def parse_extension(self):
502                 extension = dict()
503                 props = records[100]
504                 propkeys = props.keys()
505                 propkeys.sort()
506                 for position in propkeys:
507                         (type,length,name) = props[position]
508                         extension[name] = read_prop(self.header.fw,type,length)
509                 #read extension data.
510                 dstring = list()
511                 for i in xrange(self.header.fw.get_length()-24):
512                         dstring.append(self.header.fw.read_char())
513                 extension['data'] = dstring
514                 self.extension = extension
515         def parse_record(self):
516                 self.props['type'] = self.opcode
517                 props = records[self.opcode]
518                 propkeys = props.keys()
519                 propkeys.sort()
520                 for position in propkeys:
521                         (type,length,name) = props[position]
522                         self.props[name] = read_prop(self.header.fw,type,length)
523                 try: #remove me!
524                         self.props['id'] = self.props['3t8!id']
525                 except:
526                         pass
527         def __init__(self, parent, header):
528                 self.root_handler = Handler()
529                 self.child_handler = Handler()
530                 self.extension_handler = Handler()
531                 self.global_handler = Handler()
532                 
533                 self.global_handler.set_handler({21: self.parse_push_extension})
534                 self.active_handler = self.root_handler
535                 
536                 # used by parse_*_extension
537                 self.extension_handler.set_handler({22: self.parse_pop_extension})
538                 self.saved_handler = None
539                 
540                 self.header = header
541                 self.children = list()
542
543                 self.parent = parent
544
545                 if parent:
546                         parent.children.append(self)
547
548                 self.level = self.header.fw.get_level()
549                 self.opcode = self.header.fw.get_opcode()
550
551                 self.props = {'id': 'unnamed', 'comment': '', 'type': 'untyped'}
552
553 class VertexPalette(Node):
554         def __init__(self, parent):
555                 Node.__init__(self, parent, parent.header)
556                 self.root_handler.set_handler({68: self.parse_vertex_c,
557                                                                            69: self.parse_vertex_cn,
558                                                                            70: self.parse_vertex_cnuv,
559                                                                            71: self.parse_vertex_cuv})
560                 self.root_handler.set_throw_back_all_unhandled()
561
562                 self.vert_desc_lst = list()
563                 self.blender_verts = list()
564                 self.offset = 8
565                 # Used to create a map from byte offset to vertex index.
566                 self.index = dict()
567         
568         
569         def blender_import(self):
570                 self.blender_verts.extend([Vector(vert_desc.x, vert_desc.y, vert_desc.z) for vert_desc in self.vert_desc_lst ])
571
572         def parse_vertex_common(self):
573                 # Add this vertex to an offset to index dictionary.
574                 #self.index_lst.append( (self.offset, self.next_index) )
575                 self.index[self.offset]= len(self.index)
576                 
577                 # Get ready for next record.
578                 self.offset += self.header.fw.get_length()
579
580                 v = VertexDesc()
581
582                 self.header.fw.read_ahead(2)
583                 v.flags = self.header.fw.read_short()
584
585                 v.x = self.header.fw.read_double()
586                 v.y = self.header.fw.read_double()
587                 v.z = self.header.fw.read_double()
588
589                 return v
590
591         def parse_vertex_post_common(self, v):
592                 #if not v.flags & 0x2000: # 0x2000 = no color
593                         #if v.flags & 0x1000: # 0x1000 = packed color
594                         #       v.a = self.header.fw.read_uchar()
595                         #       v.b = self.header.fw.read_uchar()
596                         #       v.g = self.header.fw.read_uchar()
597                         #       v.r = self.header.fw.read_uchar()
598                         #else:
599                 self.header.fw.read_ahead(4) #skip packed color
600                 v.cindex = self.header.fw.read_uint()
601                 self.vert_desc_lst.append(v)
602                 return True
603
604         def parse_vertex_c(self):
605                 v = self.parse_vertex_common()
606
607                 self.parse_vertex_post_common(v)
608                 
609                 return True
610
611         def parse_vertex_cn(self):
612                 v = self.parse_vertex_common()
613                 v.cnorm = True
614                 v.nx = self.header.fw.read_float()
615                 v.ny = self.header.fw.read_float()
616                 v.nz = self.header.fw.read_float()
617                 
618                 self.parse_vertex_post_common(v)
619                 
620                 return True
621
622         def parse_vertex_cuv(self):
623                 v = self.parse_vertex_common()
624
625                 v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
626
627                 self.parse_vertex_post_common(v)
628                 
629                 return True
630
631         def parse_vertex_cnuv(self):
632                 v = self.parse_vertex_common()
633                 v.cnorm = True
634                 v.nx = self.header.fw.read_float()
635                 v.ny = self.header.fw.read_float()
636                 v.nz = self.header.fw.read_float()
637                 
638                 v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
639
640                 self.parse_vertex_post_common(v)
641                 
642                 return True
643
644         def parse(self): # Run once per import
645                 Node.parse(self)
646
647
648 class InterNode(Node):
649         def __init__(self):
650                 self.object = None
651                 self.mesh = None
652                 self.swapmesh = None
653                 self.hasMesh = False
654                 self.faceLs= []
655                 self.matrix = None
656                 self.vis = True
657                 self.hasmtex = False
658                 self.uvlayers = dict()
659                 self.blayernames = dict()
660                 self.subfacelevel = 0
661                 self.extension = None
662                 
663                 mask = 2147483648
664                 for i in xrange(7):
665                         self.uvlayers[mask] = False
666                         mask = mask / 2
667                 
668         #######################################################
669         ##              Begin Remove Doubles Replacement     ##
670         #######################################################
671         def __xvertsort(self,__a,__b):
672                 (__vert, __x1) = __a
673                 (__vert2,__x2) = __b
674                 
675                 if __x1 > __x2:
676                         return 1
677                 elif __x1 < __x2:
678                         return -1
679                 return 0        
680         def __calcFaceNorm(self,__face):
681                 if len(__face) == 3:
682                         return Blender.Mathutils.TriangleNormal(__face[0].co, __face[1].co, __face[2].co)
683                 elif len(__face) == 4:
684                         return Blender.Mathutils.QuadNormal(__face[0].co, __face[1].co, __face[2].co, __face[3].co)
685                         
686         def __replaceFaceVert(self,__weldface, __oldvert, __newvert):
687                 __index = None
688                 for __i, __v in enumerate(__weldface):
689                         if __v == __oldvert:
690                                 __index = __i
691                                 break
692                 __weldface[__index] = __newvert
693         
694         def __matchEdge(self,__weldmesh, __edge1, __edge2):
695                 if __edge1[0] in __weldmesh['Vertex Disk'][__edge2[1]] and __edge1[1] in __weldmesh['Vertex Disk'][__edge2[0]]:
696                         return True
697                 return False
698         #have to compare original faces!
699         def __faceWinding(self, __weldmesh, __face1, __face2):
700                 
701                 __f1edges = list()
702                 __f2edges = list()
703                 
704                 __f1edges.append((__face1.verts[0], __face1.verts[1]))
705                 __f1edges.append((__face1.verts[1], __face1.verts[2]))
706                 if len(__face1.verts) == 3:
707                         __f1edges.append((__face1.verts[2], __face1.verts[0]))
708                 else:
709                         __f1edges.append((__face1.verts[2], __face1.verts[3]))
710                         __f1edges.append((__face1.verts[3], __face1.verts[0]))
711
712                 __f2edges.append((__face2.verts[0], __face2.verts[1]))
713                 __f2edges.append((__face2.verts[1], __face2.verts[2]))
714                 if len(__face2.verts) == 3:
715                         __f2edges.append((__face2.verts[2], __face2.verts[0]))
716                 else:
717                         __f2edges.append((__face2.verts[2], __face2.verts[3]))
718                         __f2edges.append((__face2.verts[3], __face2.verts[0]))
719
720                         
721                 #find a matching edge
722                 for __edge1 in __f1edges:
723                         for __edge2 in __f2edges:
724                                 if self.__matchEdge(__weldmesh, __edge1, __edge2): #no more tests nessecary
725                                         return True
726                 
727                 return False
728                 
729         def __floatcompare(self, __f1, __f2):
730                 epsilon = 0.1
731                 if ((__f1 + epsilon) > __f2) and ((__f1 - epsilon) < __f2):
732                         return True
733                 return False
734         def __testFace(self,__weldmesh,__v1face, __v2face, __v1bface, __v2bface):
735                 limit = 0.01
736                 __matchvert = None
737                 #frst test (for real this time!). Are the faces the same face?
738                 if __v1face == __v2face:
739                         return False
740                 
741                 #first test: Do the faces possibly geometrically share more than two vertices? we should be comparing original faces for this? - Yes.....
742                 __match = 0
743                 for __vert in __v1bface.verts:
744                         for __vert2 in __v2bface.verts:
745                                 #if (abs(__vert.co[0] - __vert2.co[0]) <= limit) and (abs(__vert.co[1] - __vert2.co[1]) <= limit) and (abs(__vert.co[2] - __vert2.co[2]) <= limit): #this needs to be fixed!
746                                 if __vert2 in __weldmesh['Vertex Disk'][__vert] or __vert == __vert2:
747                                         __match += 1
748                                         __matchvert = __vert2
749                 #avoid faces sharing more than two verts
750                 if __match > 2:
751                         return False
752
753                 #consistent winding for face normals
754                 if __match == 2:
755                         if not self.__faceWinding(__weldmesh, __v1bface, __v2bface):
756                                 return False
757
758                 #second test: Compatible normals.Anything beyond almost exact opposite is 'ok'
759                 __v1facenorm = self.__calcFaceNorm(__v1face)
760                 __v2facenorm = self.__calcFaceNorm(__v2face)
761
762                 #dont even mess with zero length faces
763                 if __v1facenorm.length < limit:
764                         return False
765                 if __v2facenorm.length < limit:
766                         return False
767
768                 __v1facenorm.normalize()
769                 __v2facenorm.normalize()
770
771                 if __match == 1:
772                         #special case, look for comparison of normals angle
773                         __angle = Blender.Mathutils.AngleBetweenVecs(__v1facenorm, __v2facenorm)
774                         if __angle > 70.0:
775                                 return False    
776
777
778
779                 __v2facenorm = __v2facenorm.negate()
780
781                 if self.__floatcompare(__v1facenorm[0], __v2facenorm[0]) and self.__floatcompare(__v1facenorm[1], __v2facenorm[1]) and self.__floatcompare(__v1facenorm[2], __v2facenorm[2]):
782                         return False
783
784                 #next test: dont weld a subface to a non-subface!
785                 if __v1bface.getProperty("FLT_SFLEVEL") != __v2bface.getProperty("FLT_SFLEVEL"):
786                         return False    
787                         
788                 #final test: edge test - We dont want to create a non-manifold edge through our weld operation  
789         
790                 return True
791
792         def __copyFaceData(self, __source, __target):
793                 #copy vcolor layers.
794                 __actColLayer = self.mesh.activeColorLayer
795                 for __colorlayer in self.mesh.getColorLayerNames():
796                         self.mesh.activeColorLayer = __colorlayer
797                         for __i, __col in enumerate(__source.col):
798                                 __target.col[__i].r = __col.r
799                                 __target.col[__i].g = __col.g
800                                 __target.col[__i].b = __col.b                   
801                         
802                 self.mesh.activeColorLayer = __actColLayer
803                 #copy uv layers.
804                 __actUVLayer = self.mesh.activeUVLayer
805                 for __uvlayer in self.mesh.getUVLayerNames():
806                         self.mesh.activeUVLayer = __uvlayer
807                         __target.image = __source.image
808                         __target.mode = __source.mode
809                         __target.smooth = __source.smooth
810                         __target.transp = __source.transp
811                         for __i, __uv in enumerate(__source.uv):
812                                 __target.uv[__i][0] = __uv[0]
813                                 __target.uv[__i][1] = __uv[1]
814                         
815                 self.mesh.activeUVLayer = __actUVLayer
816                 #copy property layers
817                 for __property in self.mesh.faces.properties:
818                         __target.setProperty(__property, __source.getProperty(__property))      
819
820         def findDoubles(self):
821                 limit = 0.01
822                 sortblock = list()
823                 double = dict()
824                 for vert in self.mesh.verts:
825                         double[vert] = None
826                         sortblock.append((vert, vert.co[0] + vert.co[1] + vert.co[2]))
827                 sortblock.sort(self.__xvertsort)
828                 
829                 a = 0
830                 while a < len(self.mesh.verts):
831                         (vert,xsort) = sortblock[a]
832                         b = a+1
833                         if not double[vert]:
834                                 while b < len(self.mesh.verts):
835                                         (vert2, xsort2) = sortblock[b]
836                                         if not double[vert2]:
837                                                 #first test, simple distance
838                                                 if (xsort2 - xsort) > limit: 
839                                                         break
840                                                 #second test, more expensive
841                                                 if (abs(vert.co[0] - vert2.co[0]) <= limit) and (abs(vert.co[1] - vert2.co[1]) <= limit) and (abs(vert.co[2] - vert2.co[2]) <= limit):
842                                                         double[vert2] = vert
843                                         b+=1                            
844                         a+=1
845         
846                 return double
847
848         def buildWeldMesh(self):
849                 
850                 weldmesh = dict()
851                 weldmesh['Vertex Disk'] = dict() #this is geometric adjacency
852                 weldmesh['Vertex Faces'] = dict() #topological adjacency
853                 
854                 #find the doubles for this mesh
855                 double = self.findDoubles()
856                 
857                 for vert in self.mesh.verts:
858                         weldmesh['Vertex Faces'][vert] = list()
859         
860                 #create weld faces      
861                 weldfaces = list()
862                 originalfaces = list()
863                 for face in self.mesh.faces:
864                         weldface = list()
865                         for vert in face.verts:
866                                 weldface.append(vert)
867                         weldfaces.append(weldface)
868                         originalfaces.append(face)
869                 for i, weldface in enumerate(weldfaces):
870                         for vert in weldface:
871                                 weldmesh['Vertex Faces'][vert].append(i)
872                 weldmesh['Weld Faces'] = weldfaces
873                 weldmesh['Original Faces'] = originalfaces
874                 
875                 #Now we need to build the vertex disk data. first we do just the 'target' vertices
876                 for vert in self.mesh.verts:
877                         if not double[vert]: #its a target
878                                 weldmesh['Vertex Disk'][vert] = list()
879                 for vert in self.mesh.verts:
880                         if double[vert]: #its a double
881                                 weldmesh['Vertex Disk'][double[vert]].append(vert)
882                                 
883                 #Now we need to create the disk information for the remaining vertices
884                 targets = weldmesh['Vertex Disk'].keys()
885                 for target in targets:
886                         for doublevert in weldmesh['Vertex Disk'][target]:
887                                 weldmesh['Vertex Disk'][doublevert] = [target]
888                                 for othervert in weldmesh['Vertex Disk'][target]:
889                                         if othervert != doublevert:
890                                                 weldmesh['Vertex Disk'][doublevert].append(othervert)           
891                 
892                 return weldmesh                 
893
894         def weldFuseFaces(self,weldmesh):
895
896                 #retain original loose vertices
897                 looseverts = dict()
898                 for vert in self.mesh.verts:
899                         looseverts[vert] = 0
900                 for edge in self.mesh.edges:
901                         looseverts[edge.v1] += 1
902                         looseverts[edge.v2] += 1
903
904
905
906                 #slight modification here: we need to walk around the mesh as many times as it takes to have no more matches
907                 done = 0
908                 while not done:
909                         done = 1
910                         for windex, weldface in enumerate(weldmesh['Weld Faces']):
911                                 for vertex in weldface:
912                                         #we walk around the faces of the doubles of this vertex and if possible, we weld them.
913                                         for doublevert in weldmesh['Vertex Disk'][vertex]:
914                                                 removeFaces = list() #list of faces to remove from doubleverts face list
915                                                 for doublefaceindex in weldmesh['Vertex Faces'][doublevert]:
916                                                         doubleface = weldmesh['Weld Faces'][doublefaceindex]
917                                                         oface1 = self.mesh.faces[windex]
918                                                         oface2 = self.mesh.faces[doublefaceindex]
919                                                         ok = self.__testFace(weldmesh, weldface, doubleface, oface1, oface2)
920                                                         if ok:
921                                                                 done = 0
922                                                                 removeFaces.append(doublefaceindex)
923                                                                 self.__replaceFaceVert(doubleface, doublevert, vertex)
924                                                 for doublefaceindex in removeFaces:
925                                                         weldmesh['Vertex Faces'][doublevert].remove(doublefaceindex)
926                 #old faces first
927                 oldindices = list()
928                 for face in self.mesh.faces:
929                         oldindices.append(face.index)
930                 #make our new faces.
931                 newfaces = list()
932                 for weldface in weldmesh['Weld Faces']:
933                         newfaces.append(weldface)
934                 newindices = self.mesh.faces.extend(newfaces, indexList=True, ignoreDups=True)
935                 #copy custom data over
936                 for i, newindex in enumerate(newindices):
937                         try:
938                                 self.__copyFaceData(self.mesh.faces[oldindices[i]], self.mesh.faces[newindex])
939                         except:
940                                 print "warning, could not copy face data!"
941                 #delete the old faces
942                 self.mesh.faces.delete(1, oldindices)
943                 
944                 #Clean up stray vertices
945                 vertuse = dict()
946                 for vert in self.mesh.verts:
947                         vertuse[vert] = 0
948                 for face in self.mesh.faces:
949                         for vert in face.verts:
950                                 vertuse[vert] += 1
951                 delverts = list()
952                 for vert in self.mesh.verts:
953                         if not vertuse[vert] and vert.index != 0 and looseverts[vert]:
954                                 delverts.append(vert)
955                 
956                 self.mesh.verts.delete(delverts)        
957
958
959         #######################################################
960         ##             End Remove Doubles Replacement        ##
961         #######################################################
962
963         def blender_import_my_faces(self):
964
965                 # Add the verts onto the mesh
966                 blender_verts= self.header.vert_pal.blender_verts
967                 vert_desc_lst= self.header.vert_pal.vert_desc_lst
968                 
969                 vert_list= [ i for flt_face in self.faceLs for i in flt_face.indices] #splitting faces apart. Is this a good thing?
970                 face_edges= []
971                 face_verts= []
972                 self.mesh.verts.extend([blender_verts[i] for i in vert_list])
973                 
974                 new_faces= []
975                 new_faces_props= []
976                 ngon= BPyMesh.ngon
977                 vert_index= 1
978                 
979                 #add vertex color layer for baked face colors.
980                 self.mesh.addColorLayer("FLT_Fcol")
981                 self.mesh.activeColorLayer = "FLT_Fcol"
982                 
983                 FLT_OrigIndex = 0
984                 for flt_face in self.faceLs:
985                         if flt_face.tex_index != -1:
986                                 try:
987                                         image= self.header.tex_pal[flt_face.tex_index][1]
988                                 except KeyError:
989                                         image= None
990                         else:
991                                 image= None
992                         face_len= len(flt_face.indices)
993                         
994                         #create dummy uvert dicts
995                         if len(flt_face.uverts) == 0:
996                                 for i in xrange(face_len):
997                                         flt_face.uverts.append(dict())
998                         #May need to patch up MTex info
999                         if self.hasmtex:
1000                                 #For every layer in mesh, there should be corresponding layer in the face
1001                                 for mask in self.uvlayers.keys():
1002                                         if self.uvlayers[mask]:
1003                                                 if not flt_face.uvlayers.has_key(mask): #Does the face have this layer?
1004                                                         #Create Layer info for this face
1005                                                         flt_face.uvlayers[mask] = dict()
1006                                                         flt_face.uvlayers[mask]['texture index'] = -1
1007                                                         flt_face.uvlayers[mask]['texture enviorment'] = 3
1008                                                         flt_face.uvlayers[mask]['texture mapping'] = 0
1009                                                         flt_face.uvlayers[mask]['texture data'] = 0
1010                                                         
1011                                                         #now go through and create dummy uvs for this layer
1012                                                         for uvert in flt_face.uverts:
1013                                                                         uv = Vector(0.0,0.0)
1014                                                                         uvert[mask] = uv
1015
1016                         # Get the indicies in reference to the mesh.
1017                         uvs= [vert_desc_lst[j].uv for j in flt_face.indices]
1018                         if face_len == 1:
1019                                 pass
1020                         elif face_len == 2:
1021                                 face_edges.append((vert_index, vert_index+1))
1022                         elif flt_face.props['draw type'] == 2 or flt_face.props['draw type'] == 3:
1023                                 i = 0
1024                                 while i < (face_len-1):
1025                                         face_edges.append((vert_index + i, vert_index + i + 1))
1026                                         i = i + 1
1027                                 if flt_face.props['draw type'] == 2:
1028                                         face_edges.append((vert_index + i,vert_index)) 
1029                         elif face_len == 3 or face_len == 4: # tri or quad
1030                                 #if face_len == 1:
1031                                 #       pass
1032                                 #if face_len == 2:
1033                                 #       face_edges.append((vert_index, vert_index+1))
1034                                 new_faces.append( [i+vert_index for i in xrange(face_len)] )
1035                                 new_faces_props.append((None, image, uvs, flt_face.uverts, flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,0, flt_face.subfacelevel))
1036                         
1037                         else: # fgon
1038                                 mesh_face_indicies = [i+vert_index for i in xrange(face_len)]
1039                                 tri_ngons= ngon(self.mesh, mesh_face_indicies)
1040                                 if len(tri_ngons) != 1:
1041                                         new_faces.extend([ [mesh_face_indicies[t] for t in tri] for tri in tri_ngons])
1042                                         new_faces_props.extend( [ (None, image, (uvs[tri[0]], uvs[tri[1]], uvs[tri[2]]), [flt_face.uverts[tri[0]], flt_face.uverts[tri[1]], flt_face.uverts[tri[2]]], flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,1, flt_face.subfacelevel) for tri in tri_ngons ])
1043                         
1044                         vert_index+= face_len
1045                         FLT_OrigIndex+=1
1046                 
1047                 self.mesh.faces.extend(new_faces)
1048                 self.mesh.edges.extend(face_edges)
1049                 
1050                 #add in the FLT_ORIGINDEX layer
1051                 if len(self.mesh.faces):
1052                         try:    self.mesh.faceUV= True
1053                         except: pass
1054                 
1055                         if self.mesh.faceUV == True:
1056                                 self.mesh.renameUVLayer(self.mesh.activeUVLayer, 'Layer0')
1057                 
1058                         #create name layer for faces
1059                         self.mesh.faces.addPropertyLayer("FLT_ID",Blender.Mesh.PropertyTypes["STRING"])
1060                         #create layer for face color indices
1061                         self.mesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
1062                         #create index layer for faces. This is needed by both FGONs and subfaces
1063                         self.mesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"])
1064                         #create temporary FGON flag layer. Delete after remove doubles
1065                         self.mesh.faces.addPropertyLayer("FLT_FGON",Blender.Mesh.PropertyTypes["INT"])
1066                         self.mesh.faces.addPropertyLayer("FLT_SFLEVEL", Blender.Mesh.PropertyTypes["INT"])
1067                         
1068                         for i, f in enumerate(self.mesh.faces):
1069                                 props = new_faces_props[i]
1070                                 if props[6]['template billboard'] > 0:
1071                                         f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"]
1072                                         if props[6]['template billboard'] == 2:
1073                                                 f.mode |=  Blender.Mesh.FaceModes["BILLBOARD"]
1074                                         f.mode |= Blender.Mesh.FaceModes["LIGHT"]
1075                                 if props[6]['draw type'] == 1:
1076                                         f.mode |= Blender.Mesh.FaceModes["TWOSIDE"]
1077                                 
1078                                 #f.mat = props[0]
1079                                 f.image = props[1]
1080                                 f.uv = props[2]
1081                                 #set vertex colors
1082                                 color = self.header.get_color(props[5])
1083                                 if not color:
1084                                         color = [255,255,255,255]
1085                                 for mcol in f.col:
1086                                         mcol.a = color[3]
1087                                         mcol.r = color[0]
1088                                         mcol.g = color[1]
1089                                         mcol.b = color[2]
1090                                 
1091                                 f.setProperty("FLT_SFLEVEL", props[9])
1092                                 f.setProperty("FLT_ORIGINDEX",i)
1093                                 f.setProperty("FLT_ID",props[6]['id'])
1094                                 #if props[5] > 13199:
1095                                 #       print "Warning, invalid color index read in! Using default!"
1096                                 #       f.setProperty("FLT_COL",127)
1097                                 #else:
1098                                 if(1):                  #uh oh....
1099                                         value = struct.unpack('>i',struct.pack('>I',props[5]))[0]
1100                                         f.setProperty("FLT_COL",value)
1101                                 
1102                                 #if props[8]: 
1103                                 #       f.setProperty("FLT_FGON",1)
1104                                 #else:
1105                                 #       f.setProperty("FLT_FGON",0)
1106                         
1107                         
1108                         #Create multitex layers, if present.
1109                         actuvlayer = self.mesh.activeUVLayer
1110                         if(self.hasmtex):
1111                                 #For every multi-tex layer, we have to add a new UV layer to the mesh
1112                                 for i,mask in enumerate(reversed(sorted(self.uvlayers))):
1113                                         if self.uvlayers[mask]:
1114                                                 self.blayernames[mask] = "Layer" + str(i+1)
1115                                                 self.mesh.addUVLayer(self.blayernames[mask])
1116                                 
1117                                 #Cycle through availible multi-tex layers and add face UVS
1118                                 for mask in self.uvlayers:
1119                                         if self.uvlayers[mask]:
1120                                                 self.mesh.activeUVLayer = self.blayernames[mask]
1121                                                 for j, f in enumerate(self.mesh.faces):
1122                                                         if props[6]['draw type'] == 1:
1123                                                                 f.mode |= Blender.Mesh.FaceModes["TWOSIDE"]
1124                                                         f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"]
1125                                                         f.mode |= Blender.Mesh.FaceModes["LIGHT"]
1126                                                         props = new_faces_props[j]
1127                                                         uvlayers = props[4]
1128                                                         if uvlayers.has_key(mask): #redundant
1129                                                                 uverts = props[3]
1130                                                                 for k, uv in enumerate(f.uv):
1131                                                                         uv[0] = uverts[k][mask][0]
1132                                                                         uv[1] = uverts[k][mask][1]
1133                                 
1134                                                                 uvlayer = uvlayers[mask]
1135                                                                 tex_index = uvlayer['texture index']
1136                                                                 if tex_index != -1:
1137                                                                         try:
1138                                                                                 f.image = self.header.tex_pal[tex_index][1]
1139                                                                         except KeyError:
1140                                                                                 f.image = None
1141                                                                         
1142                         if global_prefs['smoothshading'] == True and len(self.mesh.faces):
1143                                 #We need to store per-face vertex normals in the faces as UV layers and delete them later.
1144                                 self.mesh.addUVLayer("FLTNorm1")
1145                                 self.mesh.addUVLayer("FLTNorm2")
1146                                 self.mesh.activeUVLayer = "FLTNorm1"
1147                                 for f in self.mesh.faces:
1148                                         f.smooth = 1
1149                                         #grab the X and Y components of normal and store them in UV 
1150                                         for i, uv in enumerate(f.uv):
1151                                                 vert = f.v[i].index
1152                                                 vert_desc = vert_desc_lst[vert_list[vert-1]]
1153                                                 if vert_desc.cnorm:
1154                                                         uv[0] = vert_desc.nx
1155                                                         uv[1] = vert_desc.ny
1156                                                 else:
1157                                                         uv[0] = 0.0
1158                                                         uv[1] = 0.0
1159                                 
1160                                 #Now go through and populate the second UV Layer with the z component
1161                                 self.mesh.activeUVLayer = "FLTNorm2"
1162                                 for f in self.mesh.faces:
1163                                         for i, uv in enumerate(f.uv):
1164                                                 vert = f.v[i].index
1165                                                 vert_desc = vert_desc_lst[vert_list[vert-1]]
1166                                                 if vert_desc.cnorm:
1167                                                         uv[0] = vert_desc.nz
1168                                                         uv[1] = 0.0
1169                                                 else:
1170                                                         uv[0] = 0.0
1171                                                         uv[1] = 0.0
1172                         
1173                                 
1174                                 
1175                         #Finally, go through, remove dummy vertex, remove doubles and add edgesplit modifier.
1176                         Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX'])
1177                         self.mesh.sel= 1
1178                         self.header.scene.update(1) #slow!
1179                         
1180                         #self.mesh.remDoubles(0.0001)
1181                         weldmesh = self.buildWeldMesh()
1182                         welded = self.weldFuseFaces(weldmesh)
1183                         self.mesh.verts.delete(0) # remove the dummy vert
1184                         
1185                         edgeHash = dict()
1186
1187                         for edge in self.mesh.edges:
1188                                 edgeHash[edge.key] = edge.index
1189
1190
1191                         if global_prefs['smoothshading'] == True and len(self.mesh.faces):
1192                                 
1193                                 #rip out the custom vertex normals from the mesh and place them in a face aligned list. Easier to compare this way.
1194                                 facenorms = []
1195                                 self.mesh.activeUVLayer = "FLTNorm1"
1196                                 for face in self.mesh.faces:
1197                                         facenorm = []
1198                                         for uv in face.uv:
1199                                                 facenorm.append(Vector(uv[0],uv[1],0.0))
1200                                         facenorms.append(facenorm)
1201                                 self.mesh.activeUVLayer = "FLTNorm2"
1202                                 for i, face in enumerate(self.mesh.faces):
1203                                         facenorm = facenorms[i]
1204                                         for j, uv in enumerate(face.uv):
1205                                                 facenorm[j][2] = uv[0]
1206                                 self.mesh.removeUVLayer("FLTNorm1")
1207                                 self.mesh.removeUVLayer("FLTNorm2")
1208
1209                                 #find hard edges
1210                                 #store edge data for lookup by faces
1211                                 #edgeHash = dict()
1212                                 #for edge in self.mesh.edges:
1213                                 #       edgeHash[edge.key] = edge.index
1214
1215                                 edgeNormHash = dict()
1216                                 #make sure to align the edgenormals to key value!
1217                                 for i, face in enumerate(self.mesh.faces):
1218                                         
1219                                         facenorm = facenorms[i]
1220                                         faceEdges = []
1221                                         faceEdges.append((face.v[0].index,face.v[1].index,facenorm[0],facenorm[1],face.edge_keys[0]))
1222                                         faceEdges.append((face.v[1].index,face.v[2].index,facenorm[1],facenorm[2],face.edge_keys[1]))
1223                                         if len(face.v) == 3:
1224                                                 faceEdges.append((face.v[2].index,face.v[0].index,facenorm[2],facenorm[0],face.edge_keys[2]))
1225                                         elif len(face.v) == 4:
1226                                                 faceEdges.append((face.v[2].index,face.v[3].index,facenorm[2],facenorm[3],face.edge_keys[2]))
1227                                                 faceEdges.append((face.v[3].index,face.v[0].index,facenorm[3],facenorm[0],face.edge_keys[3]))
1228                                         
1229                                         #check to see if edgeNormal has been placed in the edgeNormHash yet
1230                                         #this is a redundant test, and should be optimized to not be called as often as it is.
1231                                         for j, faceEdge in enumerate(faceEdges):
1232                                                 #the value we are looking for is (faceEdge[2],faceEdge[3])
1233                                                 hashvalue = (faceEdge[2],faceEdge[3])
1234                                                 if (faceEdge[0],faceEdge[1]) != faceEdge[4]:
1235                                                         hashvalue = (hashvalue[1],hashvalue[0])
1236                                                         assert (faceEdge[1],faceEdge[0]) == faceEdge[4]
1237                                                 if edgeNormHash.has_key(faceEdge[4]):
1238                                                         #compare value in the hash, if different, mark as sharp
1239                                                         edgeNorm = edgeNormHash[faceEdge[4]]
1240                                                         if\
1241                                                         abs(hashvalue[0][0] - edgeNorm[0][0]) > FLOAT_TOLERANCE or\
1242                                                         abs(hashvalue[0][1] - edgeNorm[0][1]) > FLOAT_TOLERANCE or\
1243                                                         abs(hashvalue[0][2] - edgeNorm[0][2]) > FLOAT_TOLERANCE or\
1244                                                         abs(hashvalue[1][0] - edgeNorm[1][0]) > FLOAT_TOLERANCE or\
1245                                                         abs(hashvalue[1][1] - edgeNorm[1][1]) > FLOAT_TOLERANCE or\
1246                                                         abs(hashvalue[1][2] - edgeNorm[1][2]) > FLOAT_TOLERANCE:
1247                                                                 edge = self.mesh.edges[edgeHash[faceEdge[4]]]
1248                                                                 edge.flag |= Blender.Mesh.EdgeFlags.SHARP
1249                                                                 
1250                                                 else:
1251                                                         edgeNormHash[faceEdge[4]] = hashvalue
1252                                 
1253                                 #add in edgesplit modifier
1254                                 mod = self.object.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
1255                                 mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = True
1256                                 mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = False
1257
1258                         if(actuvlayer):
1259                                 self.mesh.activeUVLayer = actuvlayer
1260                 
1261         def blender_import(self):
1262                 if self.vis and self.parent.object:
1263                         self.vis = self.parent.vis
1264                 name = self.props['id']
1265                 
1266
1267                 if self.hasMesh:
1268                         self.mesh = Blender.Mesh.New()
1269                         self.mesh.name = 'FLT_FaceList'
1270                         self.mesh.fakeUser = True
1271                         self.mesh.verts.extend( Vector()) #DUMMYVERT
1272                         self.object = self.header.scene.objects.new(self.mesh)
1273                 else:
1274                         self.object = self.header.scene.objects.new('Empty')
1275
1276                 self.object.name = name
1277                 self.header.group.objects.link(self.object)
1278
1279                 #id props import
1280                 self.object.properties['FLT'] = dict()
1281                 for key in self.props:
1282                         try:
1283                                 self.object.properties['FLT'][key] = self.props[key]
1284                         except: #horrible...
1285                                 pass
1286                 
1287
1288                 if self.extension:
1289                         self.object.properties['FLT']['EXT'] = dict()
1290                         for key in self.extension:
1291                                 self.object.properties['FLT']['EXT'][key] = self.extension[key]
1292                 
1293                 if self.parent and self.parent.object and (self.header.scene == self.parent.header.scene):
1294                                 self.parent.object.makeParent([self.object],1)
1295
1296                 if self.matrix:
1297                         self.object.setMatrix(self.matrix)
1298                 
1299                 if self.vis == False:
1300                         self.object.restrictDisplay = True
1301                         self.object.restrictRender = True
1302                 
1303                 else: #check for LOD children and set the proper flags
1304                         lodlist = list()
1305                         for child in self.children:
1306                                 if child.props.has_key('type') and child.props['type'] == 73:
1307                                         if child.props['6d!switch out'] != 0.0:
1308                                                 child.vis = False
1309                                         #lodlist.append(child)
1310                         
1311                         #def LODmin(a,b):
1312                         #       if a.props['5d!switch in'] < b.props['5d!switch in']:
1313                         #               return a 
1314                         #       return b
1315                 
1316                         #min= None
1317                         #if len(lodlist) > 1:
1318                         #       for lod in lodlist:
1319                         #               lod.vis = False
1320                         #       min = lodlist[0]
1321                         #       for i in xrange(len(lodlist)):
1322                         #               min= LODmin(min,lodlist[i])
1323                         #       min.vis = True
1324                                 
1325                         
1326                 Node.blender_import(self) # Attach faces to self.faceLs
1327                 
1328                 if self.hasMesh:
1329                         # Add all my faces into the mesh at once
1330                         self.blender_import_my_faces()
1331                         
1332         def parse_face(self):
1333                 child = Face(self, self.subfacelevel)
1334                 child.parse()
1335                 return True
1336
1337         def parse_group(self):
1338                 child = Group(self)
1339                 child.parse()
1340                 return True
1341
1342         def move_to_next_layer(self):
1343                 global current_layer
1344                 current_layer = current_layer << 1
1345                 if current_layer > 0x80000:
1346                         current_layer = 1
1347
1348         def parse_lod(self):
1349                 child = LOD(self)
1350                 child.parse()
1351                 return True
1352
1353         def parse_unhandled(self):
1354                 child = Unhandled(self)
1355                 child.parse()
1356                 return True
1357
1358         def parse_object(self):
1359                 child = Object(self)
1360                 child.parse()
1361                 return True
1362         
1363         def parse_xref(self):
1364                 child = XRef(self)
1365                 child.parse()
1366                 return True
1367
1368         def parse_dof(self):
1369                 child = DOF(self)
1370                 child.parse()
1371                 return True
1372
1373         def parse_indexed_light_point(self):
1374                 child = IndexedLightPoint(self)
1375                 child.parse()
1376                 return True
1377                 
1378         def parse_inline_light_point(self):
1379                 child = InlineLightPoint(self)
1380                 child.parse()
1381                 return True
1382                 
1383         def parse_matrix(self):
1384                 m = list()
1385                 for i in xrange(4):
1386                         m.append([])
1387                         for j in xrange(4):
1388                                 f = self.header.fw.read_float()
1389                                 m[i].append(f)
1390                 self.matrix = Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3])
1391                 
1392         def parse_subpush(self):
1393                 self.parse_push()
1394                 self.subfacelevel+= 1
1395                 return True
1396         def  parse_subpop(self):
1397                 self.parse_pop()
1398                 self.subfacelevel -= 1
1399                 return True
1400
1401                 
1402                 
1403 class Face(Node):
1404         def __init__(self, parent,subfacelevel):
1405                 Node.__init__(self, parent, parent.header)
1406                 self.root_handler.set_handler({31: self.parse_comment,
1407                                                                            10: self.parse_push,
1408                                                                            52: self.parse_multitex})
1409                 self.root_handler.set_throw_back_lst(throw_back_opcodes)
1410                 
1411                 self.child_handler.set_handler({72: self.parse_vertex_list,
1412                                                                                 10: self.parse_push,
1413                                                                                 11: self.parse_pop,
1414                                                                                 53: self.parse_uvlist})
1415                 
1416                 if parent:
1417                         parent.hasMesh = True
1418
1419                 self.subfacelevel = subfacelevel
1420                 self.indices =  list()  # face verts here
1421                 self.uvlayers = dict()  # MultiTexture layers keyed to layer bitmask.
1422                 self.uverts = list()    # Vertex aligned list of dictionaries keyed to layer bitmask.
1423                 self.uvmask = 0                 # Bitfield read from MTex record
1424                 
1425                 self.comment = ''
1426                 self.props = dict()             
1427                 self.props['id'] = self.header.fw.read_string(8)
1428                 # Load face.
1429                 self.props['ir color'] = self.header.fw.read_int()
1430                 self.props['priority'] = self.header.fw.read_short()
1431                 self.props['draw type'] = self.header.fw.read_char()
1432                 self.props['texture white'] = self.header.fw.read_char()
1433                 self.header.fw.read_ahead(4) # color name indices
1434                 self.header.fw.read_ahead(1) # reserved
1435                 self.props['template billboard'] = self.header.fw.read_uchar()
1436                 self.detail_tex_index = self.header.fw.read_short()
1437                 self.tex_index = self.header.fw.read_short()
1438                 self.mat_index = self.header.fw.read_short()
1439                 self.props['smc'] = self.header.fw.read_short()
1440                 self.props['fid'] = self.header.fw.read_short()
1441                 self.props['ir material'] = self.header.fw.read_int()
1442                 self.alpha = 1.0 - float(self.header.fw.read_ushort()) / 65535.0
1443                 self.props['lod generation control'] = self.header.fw.read_uchar()
1444                 self.header.fw.read_ahead(1) # line style index
1445                 self.props['flags'] = self.header.fw.read_int()
1446                 self.props['light mode'] = self.header.fw.read_uchar()
1447                 self.header.fw.read_ahead(7)
1448                 a = self.header.fw.read_uchar()
1449                 b = self.header.fw.read_uchar()
1450                 g = self.header.fw.read_uchar()
1451                 r = self.header.fw.read_uchar()
1452                 self.packed_color = [r, g, b, a]
1453                 a = self.header.fw.read_uchar()
1454                 b = self.header.fw.read_uchar()
1455                 g = self.header.fw.read_uchar()
1456                 r = self.header.fw.read_uchar()
1457                 self.alt_packed_color = [r, g, b, a]
1458                 self.tex_map_index = self.header.fw.read_short()
1459                 self.header.fw.read_ahead(2)
1460                 self.color_index = self.header.fw.read_uint()
1461                 self.alt_color_index = self.header.fw.read_uint()
1462                 #self.header.fw.read_ahead(2)
1463                 #self.shader_index = self.header.fw.read_short()
1464
1465         def parse_comment(self):
1466                 self.comment = self.header.fw.read_string(self.header.fw.get_length()-4)
1467                 return True
1468                 
1469         def blender_import(self):
1470                 vert_count = len(self.indices)
1471                 if vert_count < 1:
1472                         if global_prefs['verbose'] >= 2:
1473                                 print 'Warning: Ignoring face with no vertices.'
1474                         return
1475                 
1476                 # Assign material and image
1477                 
1478                 self.parent.faceLs.append(self)
1479                 #need to store comment in mesh prop layer!
1480                 
1481                 # Store comment info in parent.
1482                 #if self.comment != '':
1483                 #       if self.parent.props['comment'] != '':
1484                 #               self.parent.props['comment'] += '\n\nFrom Face:\n' + self.comment
1485                 #       else:
1486                 #               self.parent.props['comment'] = self.comment
1487                 
1488                 if self.uvlayers:
1489                         #Make sure that the mesh knows about the layers that this face uses
1490                         self.parent.hasmtex = True
1491                         for mask in self.uvlayers.keys():
1492                                 self.parent.uvlayers[mask] = True
1493                         
1494         def parse_vertex_list(self):
1495                 length = self.header.fw.get_length()
1496                 fw = self.header.fw
1497                 vert_pal = self.header.vert_pal
1498
1499                 count = (length-4)/4
1500                 
1501                 # If this ever fails the chunk below does error checking
1502                 self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
1503                 '''
1504                 for i in xrange(count):
1505                         byte_offset = fw.read_int()
1506                         if byte_offset in vert_pal.index:
1507                                 index = vert_pal.index[byte_offset]
1508                                 self.indices.append(index)
1509                         elif global_prefs['verbose'] >= 1:
1510                                 print 'Warning: Unable to map byte offset %s' + \
1511                                           ' to vertex index.' % byte_offset
1512                 '''
1513                 return True
1514         
1515         def parse_multitex(self):
1516                 #Parse  MultiTex Record.
1517                 length = self.header.fw.get_length()
1518                 fw = self.header.fw
1519                 #num layers == (length - 8) / 4
1520                 uvmask = fw.read_uint()
1521                 mask = 2147483648
1522                 for i in xrange(7):
1523                         if mask & uvmask:
1524                                 uvlayer = dict()
1525                                 self.uvlayers[mask] = uvlayer
1526                         mask = mask / 2
1527                 
1528                 #read in record for each individual layer.
1529                 for key in reversed(sorted(self.uvlayers)):
1530                         uvlayer = self.uvlayers[key]
1531                         uvlayer['texture index'] = fw.read_ushort()
1532                         uvlayer['texture enviorment'] = fw.read_ushort()
1533                         uvlayer['texture mapping'] = fw.read_ushort()
1534                         uvlayer['texture data'] = fw.read_ushort()
1535                 
1536                         self.uvmask = uvmask
1537                 
1538         def parse_uvlist(self):
1539                 #for each uvlayer, add uv vertices
1540                 length = self.header.fw.get_length()
1541                 fw = self.header.fw
1542                 uvmask = fw.read_uint()
1543                 if uvmask != self.uvmask: #This should never happen!
1544                         fw.read_ahead(self.length -  4) #potentially unnessecary?
1545                 else:   
1546                         #need to store in uvverts dictionary for each vertex.
1547                         totverts = len(self.indices)
1548                         for i in xrange(totverts):
1549                                 uvert = dict()
1550                                 for key in reversed(sorted(self.uvlayers)):
1551                                         uv = Vector(0.0,0.0)
1552                                         uv[0] = fw.read_float()
1553                                         uv[1] = fw.read_float()
1554                                         uvert[key] = uv
1555                                 self.uverts.append(uvert)
1556                                 
1557 class Object(InterNode):
1558         def __init__(self, parent):
1559                 Node.__init__(self, parent, parent.header)
1560                 InterNode.__init__(self)
1561                 
1562                 self.root_handler.set_handler({33: self.parse_long_id,
1563                                                                         21: self.parse_push_extension,
1564                                                                         31: self.parse_comment,
1565                                                                         10: self.parse_push,
1566                                                                         49: self.parse_matrix})
1567                 self.root_handler.set_throw_back_lst(throw_back_opcodes)
1568                 
1569                 self.child_handler.set_handler({5: self.parse_face,
1570                                                                                 19: self.parse_subpush,
1571                                                                                 20: self.parse_subpop,
1572                                                                                 111: self.parse_inline_light_point,
1573                                                                                 10: self.parse_push,
1574                                                                                 11: self.parse_pop})
1575                 self.extension_handler.set_handler({22: self.parse_pop_extension,
1576                                                                 100: self.parse_extension})
1577                 
1578                 self.extension = dict()
1579                 self.props = dict()             
1580                 self.props['comment'] = ''
1581                 self.parse_record()
1582
1583 class Group(InterNode):
1584         def __init__(self, parent):
1585                 Node.__init__(self, parent, parent.header)
1586                 InterNode.__init__(self)
1587                 
1588                 self.root_handler.set_handler({33: self.parse_long_id,
1589                                                                            31: self.parse_comment,
1590                                                                            10: self.parse_push,
1591                                                                            49: self.parse_matrix,
1592                                                                            21: self.parse_push_extension})
1593                 self.root_handler.set_throw_back_lst(throw_back_opcodes)
1594                 
1595                 self.child_handler.set_handler({5: self.parse_face,
1596                                                                                 19: self.parse_subpush,
1597                                                                                 20: self.parse_subpop,
1598                                                                                 111: self.parse_inline_light_point,
1599                                                                                 2: self.parse_group,
1600                                                                                 73: self.parse_lod,
1601                                                                                 4: self.parse_object,
1602                                                                                 10: self.parse_push,
1603                                                                                 11: self.parse_pop,
1604                                                                                 96: self.parse_unhandled,
1605                                                                                 14: self.parse_dof,
1606                                                                                 91: self.parse_unhandled,
1607                                                                                 98: self.parse_unhandled,
1608                                                                                 63: self.parse_xref})
1609                                                                                 
1610                 self.extension_handler.set_handler({22: self.parse_pop_extension,
1611                                                                 100: self.parse_extension})
1612                                                                 
1613                 self.props = dict.fromkeys(['type', 'id', 'comment', 'priority', 'flags', 'special1',
1614                                                                         'special2', 'significance', 'layer code', 'loop count',
1615                                                                         'loop duration', 'last frame duration'])
1616                 
1617                 self.props['comment'] = ''
1618                 self.parse_record()
1619                 
1620                 #self.props['type'] = str(self.opcode) + ':' + opcode_name[self.opcode]
1621                 #props = records[self.opcode]
1622                 #propkeys = props.keys()
1623                 #propkeys.sort()
1624                 #for position in propkeys:
1625                 #       (type,length,name) = props[position]
1626                 #       self.props[name] = read_prop(self.header.fw,type,length)
1627                 #self.props['id'] = self.props['3t8!id']
1628
1629 class DOF(InterNode):
1630         def blender_import(self):
1631                 InterNode.blender_import(self)
1632
1633         def __init__(self, parent):
1634                 Node.__init__(self, parent, parent.header)
1635                 InterNode.__init__(self)
1636                 
1637                 self.root_handler.set_handler({33: self.parse_long_id,
1638                                                                            31: self.parse_comment,
1639                                                                            10: self.parse_push,
1640                                                                            49: self.parse_matrix,
1641                                                                            21: self.parse_push_extension})
1642                 self.root_handler.set_throw_back_lst(throw_back_opcodes)
1643                 
1644                 self.child_handler.set_handler({#130: self.parse_indexed_light_point,
1645                                                                                 111: self.parse_inline_light_point,
1646                                                                                 2: self.parse_group,
1647                                                                                 73: self.parse_lod,
1648                                                                                 4: self.parse_object,
1649                                                                                 10: self.parse_push,
1650                                                                                 11: self.parse_pop,
1651                                                                                 96: self.parse_unhandled,
1652                                                                                 14: self.parse_dof,
1653                                                                                 91: self.parse_unhandled,
1654                                                                                 98: self.parse_unhandled,
1655                                                                                 63: self.parse_xref})
1656                 self.extension_handler.set_handler({22: self.parse_pop_extension,
1657                                                                                 100: self.parse_extension})
1658                 self.props = dict()             
1659                 self.props['comment'] = ''
1660                 self.parse_record()
1661
1662
1663 class XRef(InterNode):
1664         def parse(self):
1665                 if self.xref:
1666                         self.xref.parse()
1667                 Node.parse(self)
1668
1669         def __init__(self, parent):
1670                 Node.__init__(self, parent, parent.header)
1671                 InterNode.__init__(self)
1672                 
1673                 self.root_handler.set_handler({49: self.parse_matrix})
1674                 self.root_handler.set_throw_back_lst(throw_back_opcodes)
1675                 
1676                 self.props = dict()             
1677                 self.props['comment'] = ''
1678                 self.parse_record()
1679
1680                 xref_filename = self.props['3t200!filename'] #I dont even think there is a reason to keep this around...
1681                 
1682                 if not os.path.isabs(xref_filename):
1683                         absname = os.path.join(os.path.dirname(self.header.filename), xref_filename) 
1684                 else:
1685                         absname = xref_filename 
1686                 
1687                 self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(xref_filename))[0] #this is really wrong as well....
1688                 
1689                 if global_prefs['doxrefs'] and os.path.exists(absname) and not self.header.grr.xrefs.has_key(xref_filename):
1690                         self.xref = Database(absname, self.header.grr, self)
1691                         self.header.grr.xrefs[xref_filename] = self.xref
1692                 else:
1693                         self.xref = None
1694                 
1695
1696         def blender_import(self):
1697                 #name = self.props['type'] + ': ' + self.props['id']
1698                 name = self.props['id']
1699                 self.object = self.header.scene.objects.new('Empty')
1700                 self.object.name = name
1701                 self.object.enableDupGroup = True
1702                 self.header.group.objects.link(self.object)
1703                 
1704                 #for broken links its ok to leave this empty! they purely for visual purposes anyway.....
1705                 try:
1706                         self.object.DupGroup = self.header.grr.xrefs[self.props['3t200!filename']].group
1707                 except:
1708                         pass
1709                         
1710
1711
1712
1713                 if self.parent and self.parent.object:
1714                         self.parent.object.makeParent([self.object],1)
1715
1716                 if self.matrix:
1717                         self.object.setMatrix(self.matrix)
1718
1719
1720                 #id props import
1721                 self.object.properties['FLT'] = dict()
1722                 for key in self.props:
1723                         try:
1724                                 self.object.properties['FLT'][key] = self.props[key]
1725                         except: #horrible...
1726                                 pass
1727
1728                 self.object.Layer = current_layer
1729                 self.object.sel = 1
1730
1731                 Node.blender_import(self)
1732                 
1733                 
1734 class LOD(InterNode):
1735         def blender_import(self):
1736                 #self.move_to_next_layer()
1737                 InterNode.blender_import(self)
1738                 #self.object.properties['FLT'] = self.props.copy()
1739                 
1740         def __init__(self, parent):
1741                 Node.__init__(self, parent, parent.header)
1742                 InterNode.__init__(self)
1743
1744                 self.root_handler.set_handler({33: self.parse_long_id,
1745                                                                            31: self.parse_comment,
1746                                                                            10: self.parse_push,
1747                                                                            49: self.parse_matrix,
1748                                                                            21: self.parse_push_extension})
1749                 self.root_handler.set_throw_back_lst(throw_back_opcodes)
1750                 
1751                 self.child_handler.set_handler({2: self.parse_group,
1752                                                                                 111: self.parse_inline_light_point,
1753                                                                                 73: self.parse_lod,
1754                                                                                 4: self.parse_object,
1755                                                                                 10: self.parse_push,
1756                                                                                 11: self.parse_pop,
1757                                                                                 96: self.parse_unhandled, # switch
1758                                                                                 14: self.parse_dof, # DOF
1759                                                                                 91: self.parse_unhandled, # sound
1760                                                                                 98: self.parse_unhandled, # clip
1761                                                                                 63: self.parse_xref})
1762                 self.extension_handler.set_handler({22: self.parse_pop_extension,
1763                                                                 100: self.parse_extension})
1764
1765
1766                 self.props = dict()             
1767                 self.props['comment'] = ''
1768                 self.parse_record()
1769
1770 class InlineLightPoint(InterNode):
1771         def __init__(self, parent):
1772                 Node.__init__(self, parent, parent.header)
1773                 InterNode.__init__(self)
1774                 self.root_handler.set_handler({33: self.parse_long_id,
1775                                                                            31: self.parse_comment,
1776                                                                            10: self.parse_push,
1777                                                                            21: self.parse_push_extension,
1778                                                                            49: self.parse_matrix})
1779                 self.root_handler.set_throw_back_lst(throw_back_opcodes)
1780                 
1781                 self.child_handler.set_handler({72: self.parse_vertex_list,
1782                                                                                 10: self.parse_push,
1783                                                                                 11: self.parse_pop})
1784                 self.extension_handler.set_handler({22: self.parse_pop_extension,
1785                                                                 100: self.parse_extension})
1786                 
1787                 self.indices = list()
1788                 self.props = dict()             
1789                 self.props['comment'] = ''
1790                 self.parse_record()
1791
1792                 
1793         def blender_import(self):
1794                 
1795
1796                 name = self.props['id']
1797                 self.mesh= Blender.Mesh.New()
1798                 self.mesh.name = 'FLT_LP'
1799                 self.object = self.header.scene.objects.new(self.mesh)
1800                 self.object.name = name
1801                 #self.mesh.verts.extend(Vector() ) # DUMMYVERT
1802                 self.object.Layer = current_layer
1803                 self.object.sel= 1
1804         
1805                 self.object.properties['FLT'] = dict()
1806                 for key in self.props:
1807                         try:
1808                                 self.object.properties['FLT'][key] = self.props[key]
1809                         except: #horrible...
1810                                 pass
1811
1812                 if self.extension:
1813                         self.object.properties['FLT']['EXT'] = dict()
1814                         for key in self.extension:
1815                                 self.object.properties['FLT']['EXT'][key] = self.extension[key]
1816
1817                 if self.parent and self.parent.object and self.header.scene == self.parent.header.scene:
1818                         self.parent.object.makeParent([self.object])
1819
1820                 if self.matrix:
1821                         self.object.setMatrix(self.matrix)
1822
1823                 self.mesh.verts.extend([self.header.vert_pal.blender_verts[i] for i in self.indices])
1824                 
1825                 #add color index information.
1826                 self.mesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"])
1827                 for i, vindex in enumerate(self.indices):
1828                         vdesc = self.header.vert_pal.vert_desc_lst[vindex]
1829                         v = self.mesh.verts[i]
1830                         v.setProperty("FLT_VCOL",vdesc.cindex)
1831                 #for i, v in enumerate(self.mesh.verts):
1832                 #       vdesc = self.header.vert_pal.vert_desc_lst[i]
1833                 #       v.setProperty("FLT_VCOL",vdesc.cindex)
1834                 self.mesh.update()
1835                                 
1836         def parse_vertex_list(self):
1837                 length = self.header.fw.get_length()
1838                 fw = self.header.fw
1839                 vert_pal = self.header.vert_pal
1840
1841                 count = (length-4)/4
1842                 
1843                 # If this ever fails the chunk below does error checking
1844                 self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
1845                 
1846                 '''
1847                 for i in xrange(count):
1848                         byte_offset = fw.read_int()
1849                         if byte_offset in vert_pal.index:
1850                                 index = vert_pal.index[byte_offset]
1851                                 self.indices.append(index)
1852                         elif global_prefs['verbose'] >= 1:
1853                                 print 'Warning: Unable to map byte offset %s' + \
1854                                           ' to vertex index.' % byte_offset
1855                 '''
1856                 
1857                 return True
1858                 
1859
1860
1861 class IndexedLightPoint(InterNode):
1862         # return dictionary: lp_app name => index list
1863         def group_points(self, props):
1864                 
1865                 name_to_indices = {}
1866                 
1867                 for i in self.indices:
1868                         vert_desc = self.header.vert_pal.vert_desc_lst[i]
1869                         app_desc = LightPointAppDesc()
1870                         app_desc.props.update(props)
1871                         # add vertex normal and color
1872                         app_desc.props.update({'nx': vert_desc.nx})
1873                         app_desc.props.update({'ny': vert_desc.ny})
1874                         app_desc.props.update({'nz': vert_desc.nz})
1875                         
1876                         app_desc.props.update({'r': vert_desc.r})
1877                         app_desc.props.update({'g': vert_desc.g})
1878                         app_desc.props.update({'b': vert_desc.b})
1879                         app_desc.props.update({'a': vert_desc.a})
1880                         
1881                         app_name = self.header.grr.request_lightpoint_app(app_desc, self.header.scene)
1882
1883                         if name_to_indices.get(app_name):
1884                                 name_to_indices[app_name].append(i)
1885                         else:
1886                                 name_to_indices.update({app_name: [i]})
1887                         
1888                 return name_to_indices
1889                 
1890         def blender_import(self):
1891                 name = self.props['type'] + ': ' + self.props['id']
1892                 
1893                 name_to_indices = self.group_points(self.header.lightpoint_appearance_pal[self.index])
1894                 
1895                 for app_name, indices in name_to_indices.iteritems():        
1896                         self.object = Blender.Object.New('Mesh', name)
1897                         self.mesh= Blender.Mesh.New()
1898                         self.mesh.verts.extend( Vector() ) # DUMMYVERT
1899                         self.object.link(self.mesh)
1900                         
1901                         if self.parent:
1902                                 self.parent.object.makeParent([self.object])
1903                                 
1904                         for i in indices:
1905                                 vert = self.header.vert_pal.blender_verts[i]
1906                                 self.mesh.verts.append(vert)
1907                         
1908                         self.header.scene.objects.link(self.object)
1909         
1910                         self.object.Layer = current_layer
1911                         
1912                         if self.matrix:
1913                                 self.object.setMatrix(self.matrix)
1914                                 
1915                         # Import comment.
1916                         if self.props['comment'] != '':
1917                                 name = 'COMMENT: ' + self.props['id']
1918                                 t = Blender.Text.New(name)
1919                                 t.write(self.props['comment'])
1920                                 self.props['comment'] = name
1921                                 
1922                         # Attach properties.
1923                         self.props.update({'appearance': app_name})
1924                         for name, value in self.props.iteritems():
1925                                 self.object.addProperty(name, value)
1926                         
1927                         self.mesh.update()
1928                         
1929         def parse_vertex_list(self):
1930                 length = self.header.fw.get_length()
1931                 fw = self.header.fw
1932                 vert_pal = self.header.vert_pal
1933
1934                 count = (length-4)/4
1935                 
1936                 # If this ever fails the chunk below does error checking
1937                 self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
1938                 
1939                 '''
1940                 for i in xrange(count):
1941                         byte_offset = fw.read_int()
1942                         if byte_offset in vert_pal.index:
1943                                 index = vert_pal.index[byte_offset]
1944                                 self.indices.append(index)
1945                         elif global_prefs['verbose'] >= 1:
1946                                 print 'Warning: Unable to map byte offset %s' + \
1947                                           ' to vertex index.' % byte_offset
1948                 '''
1949                 return True
1950                 
1951         def __init__(self, parent):
1952                 Node.__init__(self, parent, parent.header)
1953                 InterNode.__init__(self)
1954                 self.root_handler.set_handler({33: self.parse_long_id,
1955                                                                            31: self.parse_comment,
1956                                                                            10: self.parse_push,
1957                                                                            49: self.parse_matrix})
1958                 self.root_handler.set_throw_back_lst(throw_back_opcodes)
1959                 
1960                 self.child_handler.set_handler({72: self.parse_vertex_list,
1961                                                                                 10: self.parse_push,
1962                                                                                 11: self.parse_pop})
1963
1964                 self.indices = list()
1965                 
1966                 self.props = dict.fromkeys(['id', 'type', 'comment', 'draw order', 'appearance'])
1967                 self.props['comment'] = ''
1968                 self.props['type'] = 'Light Point'
1969                 self.props['id'] = self.header.fw.read_string(8)
1970                 self.index = self.header.fw.read_int()
1971                 self.header.fw.read_ahead(4) # animation index
1972                 self.props['draw order'] = self.header.fw.read_int()        
1973
1974 class Unhandled(InterNode):
1975         def __init__(self, parent):
1976                 Node.__init__(self, parent, parent.header)
1977                 InterNode.__init__(self)
1978                 
1979                 self.root_handler.set_handler({33: self.parse_long_id,
1980                                                                            31: self.parse_comment,
1981                                                                            10: self.parse_push,
1982                                                                            49: self.parse_matrix})
1983                 self.root_handler.set_throw_back_lst(throw_back_opcodes)
1984                 
1985                 self.child_handler.set_handler({2: self.parse_group,
1986                                                                                 73: self.parse_lod,
1987                                                                                 4: self.parse_object,
1988                                                                                 10: self.parse_push,
1989                                                                                 11: self.parse_pop,
1990                                                                                 96: self.parse_unhandled, # switch
1991                                                                                 14: self.parse_dof, # DOF
1992                                                                                 91: self.parse_unhandled, # sound
1993                                                                                 98: self.parse_unhandled, # clip
1994                                                                                 63: self.parse_xref})
1995
1996                 self.props['id'] = self.header.fw.read_string(8)
1997
1998 class Database(InterNode):
1999         def blender_import(self):
2000                 for key in self.tex_pal.keys():
2001                         path_filename= FF.find(self.tex_pal[key][0])
2002                         if path_filename != None:
2003                                 img = self.grr.request_image(path_filename)
2004                                 if img:
2005                                         self.tex_pal[key][1] = img
2006                         elif global_prefs['verbose'] >= 1:
2007                                 print 'Warning: Unable to find', self.tex_pal[key][0]
2008                 
2009                 self.scene.properties['FLT'] = dict()
2010                 for key in self.props:
2011                         try:
2012                                 self.scene.properties['FLT'][key] = self.props[key]
2013                         except: #horrible...
2014                                 pass
2015                 
2016                 self.scene.properties['FLT']['Main'] = 0
2017                 self.scene.properties['FLT']['Filename'] = self.bname
2018                 
2019                 for child in self.children:
2020                         if child.props.has_key('type') and child.props['type'] == 73:
2021                                 if child.props['6d!switch out'] != 0.0:
2022                                                 child.vis = False
2023                 
2024                 #import color palette
2025                 carray = list()
2026                 for color in self.col_pal:
2027                         carray.append(struct.unpack('>i',struct.pack('>BBBB',color[0],color[1],color[2],color[3]))[0])
2028                 self.scene.properties['FLT']['Color Palette'] = carray
2029                 Node.blender_import(self)
2030
2031         def parse_appearance_palette(self):
2032                 props = dict()
2033                 self.fw.read_ahead(4) # reserved
2034                 props.update({'id': self.fw.read_string(256)})
2035                 index = self.fw.read_int()
2036                 props.update({'smc': self.fw.read_short()})
2037                 props.update({'fid': self.fw.read_short()})
2038                 props.update({'back color: a': self.fw.read_uchar()})
2039                 props.update({'back color: b': self.fw.read_uchar()})
2040                 props.update({'back color: g': self.fw.read_uchar()})
2041                 props.update({'back color: r': self.fw.read_uchar()})
2042                 props.update({'display mode': self.fw.read_int()})
2043                 props.update({'intensity': self.fw.read_float()})
2044                 props.update({'back intensity': self.fw.read_float()})
2045                 props.update({'minimum defocus': self.fw.read_float()})
2046                 props.update({'maximum defocus': self.fw.read_float()})
2047                 props.update({'fading mode': self.fw.read_int()})
2048                 props.update({'fog punch mode': self.fw.read_int()})
2049                 props.update({'directional mode': self.fw.read_int()})
2050                 props.update({'range mode': self.fw.read_int()})
2051                 props.update({'min pixel size': self.fw.read_float()})
2052                 props.update({'max pixel size': self.fw.read_float()})
2053                 props.update({'actual size': self.fw.read_float()})
2054                 props.update({'trans falloff pixel size': self.fw.read_float()})
2055                 props.update({'trans falloff exponent': self.fw.read_float()})
2056                 props.update({'trans falloff scalar': self.fw.read_float()})
2057                 props.update({'trans falloff clamp': self.fw.read_float()})
2058                 props.update({'fog scalar': self.fw.read_float()})
2059                 props.update({'fog intensity': self.fw.read_float()})
2060                 props.update({'size threshold': self.fw.read_float()})
2061                 props.update({'directionality': self.fw.read_int()})
2062                 props.update({'horizontal lobe angle': self.fw.read_float()})
2063                 props.update({'vertical lobe angle': self.fw.read_float()})
2064                 props.update({'lobe roll angle': self.fw.read_float()})
2065                 props.update({'dir falloff exponent': self.fw.read_float()})
2066                 props.update({'dir ambient intensity': self.fw.read_float()})
2067                 props.update({'significance': self.fw.read_float()})
2068                 props.update({'flags': self.fw.read_int()})
2069                 props.update({'visibility range': self.fw.read_float()})
2070                 props.update({'fade range ratio': self.fw.read_float()})
2071                 props.update({'fade in duration': self.fw.read_float()})
2072                 props.update({'fade out duration': self.fw.read_float()})
2073                 props.update({'LOD range ratio': self.fw.read_float()})
2074                 props.update({'LOD scale': self.fw.read_float()})
2075                 
2076                 self.lightpoint_appearance_pal.update({index: props})
2077                 
2078         def parse_header(self):
2079                 self.props['type'] = 'Header'
2080                 self.props['comment'] = ''
2081                 self.props['id'] = self.fw.read_string(8)
2082                 self.props['version'] = self.fw.read_int()
2083                 self.fw.read_ahead(46)
2084                 self.props['units'] = self.fw.read_char()
2085                 self.props['set white'] = bool(self.fw.read_char())
2086                 self.props['flags'] = self.fw.read_int()
2087                 self.fw.read_ahead(24)
2088                 self.props['projection type'] = self.fw.read_int()
2089                 self.fw.read_ahead(36)
2090                 self.props['sw x'] = self.fw.read_double()
2091                 self.props['sw y'] = self.fw.read_double()
2092                 self.props['dx'] = self.fw.read_double()
2093                 self.props['dy'] = self.fw.read_double()
2094                 self.fw.read_ahead(24)
2095                 self.props['sw lat'] = self.fw.read_double()
2096                 self.props['sw lon'] = self.fw.read_double()
2097                 self.props['ne lat'] = self.fw.read_double()
2098                 self.props['ne lon'] = self.fw.read_double()
2099                 self.props['origin lat'] = self.fw.read_double()
2100                 self.props['origin lon'] = self.fw.read_double()
2101                 self.props['lambert lat1'] = self.fw.read_double()
2102                 self.props['lambert lat2'] = self.fw.read_double()
2103                 self.fw.read_ahead(16)
2104                 self.props['ellipsoid model'] = self.fw.read_int()
2105                 self.fw.read_ahead(4)
2106                 self.props['utm zone'] = self.fw.read_short()
2107                 self.fw.read_ahead(6)
2108                 self.props['dz'] = self.fw.read_double()
2109                 self.props['radius'] = self.fw.read_double()
2110                 self.fw.read_ahead(8)
2111                 self.props['major axis'] = self.fw.read_double()
2112                 self.props['minor axis'] = self.fw.read_double()
2113                 
2114                 if global_prefs['verbose'] >= 1:
2115                         print 'OpenFlight Version:', float(self.props['version']) / 100.0
2116                         print
2117                         
2118                 return True
2119
2120         def parse_mat_palette(self):
2121                 mat_desc = MaterialDesc()
2122                 index = self.fw.read_int()
2123
2124                 name = self.fw.read_string(12)
2125                 if len(mat_desc.name) > 0:
2126                         mat_desc.name = name
2127
2128                 flag = self.fw.read_int()
2129                 # skip material if not used
2130                 if not flag & 0x80000000:
2131                         return True
2132
2133                 ambient_col = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
2134                 mat_desc.diffuse = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
2135                 mat_desc.specular = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
2136                 emissive_col = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
2137
2138                 mat_desc.shininess = self.fw.read_float() / 64.0 # [0.0, 128.0] => [0.0, 2.0]
2139                 mat_desc.alpha = self.fw.read_float()
2140
2141                 # Convert ambient and emissive colors into intensitities.
2142                 mat_desc.ambient = col_to_gray(ambient_col)
2143                 mat_desc.emissive = col_to_gray(emissive_col)
2144
2145                 self.mat_desc_pal_lst.append( (index, mat_desc) )
2146                 
2147                 return True
2148         
2149         def get_color(self, color_index):
2150                 color = None
2151                 index = color_index / 128
2152                 intensity = float(color_index - 128.0 * index) / 127.0
2153                 
2154                 if index >= 0 and index <= 1023:
2155                         brightest = self.col_pal[index]
2156                         r = int(brightest[0] * intensity)
2157                         g = int(brightest[1] * intensity)
2158                         b = int(brightest[2] * intensity)
2159                         a = int(brightest[3])
2160                         
2161                         color = [r, g, b, a]
2162                 
2163                 return color
2164         
2165         def parse_color_palette(self):
2166                 self.header.fw.read_ahead(128)
2167                 for i in xrange(1024):
2168                         a = self.header.fw.read_uchar()
2169                         b = self.header.fw.read_uchar()
2170                         g = self.header.fw.read_uchar()
2171                         r = self.header.fw.read_uchar()
2172                         self.col_pal.append((r, g, b, a))
2173                 return True
2174                 
2175         def parse_vertex_palette(self):
2176                 self.vert_pal = VertexPalette(self)
2177                 self.vert_pal.parse()
2178                 return True
2179                 
2180         def parse_texture_palette(self):
2181                 name = self.fw.read_string(200)
2182                 index = self.fw.read_int()
2183                 self.tex_pal[index]= [name, None]
2184                 return True
2185         
2186         def read_attribute_files(self):
2187                 for tex in self.tex_pal.keys():
2188                         [name,image] = self.tex_pal[tex]
2189                         basename = os.path.basename(name)
2190                         if(image):
2191                                 basename = basename + ".attr"
2192                                 dirname = os.path.dirname(Blender.sys.expandpath(image.getFilename())) #can't rely on original info stored in pallette since it might be relative link
2193                                 newpath = os.path.join(dirname, basename)
2194                                 if os.path.exists(newpath) and not image.properties.has_key('FLT'):
2195                                         fw = flt_filewalker.FltIn(newpath)
2196                                         fw.read_ahead(8) #We dont care what the attribute file says about x/y dimensions
2197                                         image.properties['FLT']={}
2198                                         
2199                                         #need to steal code from parse records....
2200                                         props = records['Image']
2201                                         propkeys = props.keys()
2202                                         propkeys.sort()
2203                                         for position in propkeys:
2204                                                 (type,length,name) = props[position]
2205                                                 image.properties['FLT'][name] = read_prop(fw,type,length)
2206                                         fw.close_file()
2207                                         
2208                                         #copy clamp settings
2209                                         wrap = image.properties['FLT']['10i!Wrap']
2210                                         wrapu = image.properties['FLT']['11i!WrapU']
2211                                         wrapv = image.properties['FLT']['12i!WrapV']
2212                                         
2213                                         if wrapu == 3 or wrapv == 3:
2214                                                 wrapuv = (wrap,wrap)
2215                                         else:
2216                                                 wrapuv = (wrapu, wrapv)
2217                                         image.clampX = wrapuv[0]
2218                                         image.clampY = wrapuv[1]
2219                                         
2220                                 elif not os.path.exists(newpath):
2221                                         print "Cannot read attribute file:" + newpath
2222                                         
2223         def __init__(self, filename, grr, parent=None):
2224                 if global_prefs['verbose'] >= 1:
2225                         print 'Parsing:', filename
2226                         print
2227                 
2228                 #check to see if filename is a relative path
2229                 #filename = os.path.abspath(filename)
2230                 
2231                 self.fw = flt_filewalker.FltIn(filename)
2232                 self.filename = filename
2233                 self.bname = os.path.splitext(os.path.basename(filename))[0]
2234                 self.grr = grr
2235                 
2236                 Node.__init__(self, parent, self)
2237                 InterNode.__init__(self)
2238                 
2239                 self.root_handler.set_handler({1: self.parse_header,
2240                                                                            67: self.parse_vertex_palette,
2241                                                                            33: self.parse_long_id,
2242                                                                            31: self.parse_comment,
2243                                                                            64: self.parse_texture_palette,
2244                                                                            32: self.parse_color_palette,
2245                                                                            113: self.parse_mat_palette,
2246                                                                            128: self.parse_appearance_palette,
2247                                                                            10: self.parse_push})
2248                 if parent:
2249                         self.root_handler.set_throw_back_lst(throw_back_opcodes)
2250
2251                 self.child_handler.set_handler({#130: self.parse_indexed_light_point,
2252                                                                                 111: self.parse_inline_light_point,
2253                                                                                 2: self.parse_group,
2254                                                                                 73: self.parse_lod,
2255                                                                                 4: self.parse_object,
2256                                                                                 10: self.parse_push,
2257                                                                                 11: self.parse_pop,
2258                                                                                 96: self.parse_unhandled,
2259                                                                                 14: self.parse_dof,
2260                                                                                 91: self.parse_unhandled,
2261                                                                                 98: self.parse_unhandled,
2262                                                                                 63: self.parse_xref})
2263                 
2264                 self.scene = Blender.Scene.New(self.bname)
2265                 self.group = Blender.Group.New(self.bname)
2266
2267                 self.vert_pal = None
2268                 self.lightpoint_appearance_pal = dict()
2269                 self.tex_pal = dict()
2270                 #self.tex_pal_lst = list()
2271                 #self.bl_tex_pal = dict()
2272                 self.col_pal = list()
2273                 self.mat_desc_pal_lst = list()
2274                 self.mat_desc_pal = dict()
2275                 self.props = dict.fromkeys(['id', 'type', 'comment', 'version', 'units', 'set white',
2276                         'flags', 'projection type', 'sw x', 'sw y', 'dx', 'dy', 'dz', 'sw lat',
2277                         'sw lon', 'ne lat', 'ne lon', 'origin lat', 'origin lon', 'lambert lat1',
2278                         'lambert lat2', 'ellipsoid model', 'utm zone', 'radius', 'major axis', 'minor axis'])
2279
2280
2281 def clearparent(root,childhash):
2282         for child in childhash[root]:
2283                 clearparent(child,childhash)
2284         root.clrParent(2,0)
2285
2286 def fixscale(root,childhash):   
2287         for child in childhash[root]:
2288                 fixscale(child,childhash)
2289         location = Blender.Mathutils.Vector(root.getLocation('worldspace'))
2290         if location[0] != 0.0 or location[1] != 0.0 or location[2] != 0.0:
2291                 #direction = Blender.Mathutils.Vector(0-location[0],0-location[1],0-location[2]) #reverse vector
2292                 smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4)
2293                 root.setLocation(location * smat)
2294         #if its a mesh, we need to scale all of its vertices too
2295         if root.type == 'Mesh':
2296                 smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4)
2297                 rmesh = root.getData(mesh=True)
2298                 for v in rmesh.verts:
2299                         v.co = v.co * smat
2300         
2301 def reparent(root,childhash,sce):
2302         for child in childhash[root]:
2303                 reparent(child,childhash,sce)
2304         
2305         root.makeParent(childhash[root])
2306         sce.update(1)
2307         
2308 def update_scene(root,sdone):
2309         for object in root.objects:
2310                 if object.DupGroup:
2311                         try:
2312                                 child = Blender.Scene.Get(object.DupGroup.name)
2313                         except:
2314                                 child = None
2315                         if child and child not in sdone:
2316                                 update_scene(child,sdone)
2317         root.makeCurrent()
2318         #create a list of children for each object
2319         childhash = dict()
2320         for object in root.objects:
2321                 childhash[object] = list()
2322                 
2323         for object in root.objects:
2324                 if object.parent:
2325                         childhash[object.parent].append(object)
2326         
2327         for object in root.objects:
2328                 if not object.parent:
2329                         #recursivley go through and clear all the children of their transformation, starting at deepest level first.
2330                         clearparent(object,childhash)
2331                         #now fix the location of everything
2332                         fixscale(object,childhash)
2333                         #now fix the parenting
2334                         reparent(object,childhash,root)
2335         
2336         for object in root.objects:
2337                 object.makeDisplayList()
2338         root.update(1)
2339         sdone.append(root)
2340
2341
2342 def select_file(filename, grr):
2343         if not Blender.sys.exists(filename):
2344                 msg = 'Error: File ' + filename + ' does not exist.'
2345                 Blender.Draw.PupMenu(msg)
2346                 return
2347         
2348         if not filename.lower().endswith('.flt'):
2349                 msg = 'Error: Not a flight file.'
2350                 Blender.Draw.PupMenu(msg)
2351                 print msg
2352                 print
2353                 return
2354         
2355         global_prefs['fltfile']= filename
2356         global_prefs['verbose']= 1
2357         global_prefs['get_texture'] = True
2358         global_prefs['get_diffuse'] = True
2359         global_prefs['get_specular'] = False
2360         global_prefs['get_emissive'] = False
2361         global_prefs['get_alpha'] = True
2362         global_prefs['get_ambient'] = False
2363         global_prefs['get_shininess'] = True
2364         global_prefs['color_from_face'] = True
2365         global_prefs['log to blender'] = True
2366         
2367         
2368         
2369         Blender.Window.WaitCursor(True)
2370         Blender.Window.EditMode(0)
2371         
2372         
2373         FF.add_file_to_search_path(filename)
2374         
2375         if global_prefs['verbose'] >= 1:
2376                 print 'Pass 1: Loading.'
2377                 print
2378
2379         load_time = Blender.sys.time()    
2380         db = Database(filename,grr)
2381         db.parse()
2382         load_time = Blender.sys.time() - load_time
2383
2384         if global_prefs['verbose'] >= 1:
2385                 print
2386                 print 'Pass 2: Importing to Blender.'
2387                 print
2388
2389         import_time = Blender.sys.time()
2390         db.blender_import()
2391         
2392         if global_prefs['attrib']:
2393                 print "reading attribute files"
2394                 db.read_attribute_files()
2395         
2396         Blender.Window.ViewLayer(range(1,21))
2397         
2398         update_scene(db.scene,[])
2399         import_time = Blender.sys.time() - import_time
2400         if global_prefs['verbose'] >= 1:
2401                 print 'Done.'
2402                 print
2403                 print 'Time to parse file: %.3f seconds' % load_time
2404                 print 'Time to import to blender: %.3f seconds' % import_time
2405                 print 'Total time: %.3f seconds' % (load_time + import_time)
2406         
2407         Blender.Window.WaitCursor(False)
2408
2409 def setimportscale(ID,val):
2410         global global_prefs
2411         global_prefs['scale'] = val
2412 def setBpath(fname):
2413         global_prefs['fltfile'] = fname
2414         d = dict()
2415         for key in global_prefs:
2416                 d[key] = global_prefs[key]
2417                 Blender.Registry.SetKey('flt_import', d, 1) 
2418
2419 def event(evt,val):
2420         pass
2421
2422 from Blender.BGL import *
2423 from Blender import Draw
2424
2425 def but_event(evt):
2426         
2427         global FLTBaseLabel
2428         global FLTBaseString
2429         global FLTBaseChooser
2430
2431         global FLTExport
2432         global FLTClose
2433         
2434         global FLTDoXRef
2435         global FLTShadeImport
2436         global FLTAttrib
2437         
2438         global FLTWarn
2439         
2440         #Import DB
2441         if evt == 1:
2442                 if global_prefs['verbose'] >= 1:
2443                         print
2444                         print 'OpenFlight Importer'
2445                         print 'Version:', __version__
2446                         print 'Author: Greg MacDonald, Campbell Barton, Geoffrey Bantle'
2447                         print __url__[2]
2448                         print
2449                 
2450                 GRR = GlobalResourceRepository()
2451                 
2452                 try:
2453                         select_file(global_prefs['fltfile'], GRR)
2454                 except:
2455                         import traceback
2456                         FLTWarn = Draw.PupBlock("Ixport Error", ["See console for output!"])
2457                         traceback.print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)
2458         
2459         #choose base path for export
2460         if evt == 4:
2461                 Blender.Window.FileSelector(setBpath, "DB Root", global_prefs['fltfile'])
2462         #Import custom shading?
2463         if evt == 9:
2464                 global_prefs['smoothshading'] = FLTShadeImport.val
2465         #Import Image attribute files
2466         if evt == 10:
2467                 global_prefs['attrib'] = FLTAttrib.val
2468         #export XRefs
2469         if evt == 13:
2470                 global_prefs['doxrefs'] = FLTDoXRef.val
2471         
2472         if evt == 2:
2473                 Draw.Exit()
2474         
2475         d = dict()
2476         for key in global_prefs:
2477                 d[key] = global_prefs[key]
2478                 Blender.Registry.SetKey('flt_import', d, 1) 
2479
2480 def gui():
2481         
2482         global FLTBaseLabel
2483         global FLTBaseString
2484         global FLTBaseChooser
2485
2486         global FLTExport
2487         global FLTClose
2488         
2489         global FLTDoXRef
2490         global FLTShadeImport
2491         
2492         global FLTAttrib
2493         
2494         
2495         glClearColor(0.772,0.832,0.847,1.0)
2496         glClear(GL_COLOR_BUFFER_BIT)
2497         
2498         areas = Blender.Window.GetScreenInfo()
2499         curarea = Blender.Window.GetAreaID()
2500         curRect = None
2501         
2502         for area in areas:
2503                 if area['id'] == curarea:
2504                         curRect = area['vertices']
2505                         break
2506         
2507         width = curRect[2] - curRect[0]
2508         height = curRect[3] - curRect[1]
2509         cx = 50
2510         cy = height - 80
2511
2512         FLTBaseLabel = Draw.Label("Base file:",cx,cy,100,20)
2513         FLTBaseString = Draw.String("",3,cx+100,cy,300,20,global_prefs['fltfile'],255,"Root DB file")
2514         FLTBaseChooser = Draw.PushButton("...",4,cx+400,cy,20,20,"Choose Folder")
2515         
2516         cy = cy-40
2517         FLTScale = Draw.Number("Import Scale",14,cx,cy,220,20,global_prefs['scale'],0.0,100.0,"Export scaleing factor",setimportscale)
2518         
2519         cy = cy-40
2520         FLTDoXRef = Draw.Toggle("Import XRefs", 13,cx,cy,220,20,global_prefs['doxrefs'],"Import External references")
2521         
2522         cy = cy-40
2523         FLTShadeImport = Draw.Toggle("Import Custom Shading",9,cx,cy,220,20,global_prefs['smoothshading'],"Import custom shading via edgesplit modifiers")
2524         
2525         cy = cy-40
2526         FLTAttrib = Draw.Toggle("Import Attribute Files", 10,cx,cy,220,20,global_prefs['attrib'],"Import Image Attribute files")
2527         
2528         cy = cy - 40
2529         FLTExport = Draw.PushButton("Import",1,cx,20,100,20,"Import FLT Database")
2530         FLTClose = Draw.PushButton("Close",2,cx+120,20,100,20,"Close Window")
2531
2532         
2533         
2534 Draw.Register(gui,event,but_event)