blender/release/scripts/flt_import.py
Geoffrey Bantle 0010f33bdb -> FLT I/O: UI now undo safe
Both the FLT importer and exporter now store and retrieve
their settings from the blender python registry making
them safe for use with global undo.
2008-03-28 23:06:00 +00:00

2511 lines
75 KiB
Python

#!BPY
""" Registration info for Blender menus:
Name: 'OpenFlight (.flt)...'
Blender: 245
Group: 'Import'
Tip: 'Import OpenFlight (.flt)'
"""
__author__ = "Greg MacDonald, Campbell Barton, Geoffrey Bantle"
__version__ = "2.0 11/21/07"
__url__ = ("blender", "elysiun", "Author's homepage, http://sourceforge.net/projects/blight/")
__bpydoc__ = """\
This script imports OpenFlight files into Blender. OpenFlight is a
registered trademark of MultiGen-Paradigm, Inc.
Feature overview and more availible at:
http://wiki.blender.org/index.php/Scripts/Manual/Import/openflight_flt
Note: This file is a grab-bag of old and new code. It needs some cleanup still.
"""
# flt_import.py is an OpenFlight importer for blender.
# Copyright (C) 2005 Greg MacDonald, 2007 Blender Foundation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import Blender
import os
import BPyMesh
import BPyImage
import flt_filewalker
import flt_properties
reload(flt_properties)
from flt_properties import *
#Globals. Should Clean these up and minimize their usage.
typecodes = ['c','C','s','S','i','I','f','d','t']
records = dict()
FLTBaseLabel = None
FLTBaseString = None
FLTBaseChooser = None
FLTExport = None
FLTClose = None
FLTDoXRef = None
FLTScale = None
FLTShadeImport = None
FLTAttrib = None
Vector= Blender.Mathutils.Vector
FLOAT_TOLERANCE = 0.01
FF = flt_filewalker.FileFinder()
current_layer = 0x01
global_prefs = dict()
global_prefs['verbose']= 4
global_prefs['get_texture'] = True
global_prefs['get_diffuse'] = True
global_prefs['get_specular'] = False
global_prefs['get_emissive'] = False
global_prefs['get_alpha'] = True
global_prefs['get_ambient'] = False
global_prefs['get_shininess'] = True
global_prefs['color_from_face'] = True
global_prefs['fltfile']= ''
global_prefs['smoothshading'] = 1
global_prefs['doxrefs'] = 1
global_prefs['scale'] = 1.0
global_prefs['attrib'] = 0
msg_once = False
reg = Blender.Registry.GetKey('flt_import',1)
if reg:
for key in global_prefs:
if reg.has_key(key):
global_prefs[key] = reg[key]
throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63,111] # Opcodes that indicate its time to return control to parent.
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]
#Process FLT record definitions
for record in FLT_Records:
props = dict()
for prop in FLT_Records[record]:
position = ''
slice = 0
(format,name) = prop.split('!')
for i in format:
if i not in typecodes:
position = position + i
slice = slice + 1
else:
break
type = format[slice:]
length = type[1:]
if len(length) == 0:
length = 1
else:
type = type[0]
length = int(length)
props[int(position)] = (type,length,prop)
records[record] = props
def col_to_gray(c):
return 0.3*c[0] + 0.59*c[1] + 0.11*c[2]
class MaterialDesc:
# Was going to use int(f*1000.0) instead of round(f,3), but for some reason
# round produces better results, as in less dups.
def make_key(self):
key = list()
if global_prefs['get_texture']:
if self.tex0:
key.append(self.tex0.getName())
else:
key.append(None)
if global_prefs['get_alpha']:
key.append(round(self.alpha, 3))
else:
key.append(None)
if global_prefs['get_shininess']:
key.append(round(self.shininess, 3))
else:
key.append(None)
if global_prefs['get_emissive']:
key.append(round(self.emissive, 3))
else:
key.append(None)
if global_prefs['get_ambient']:
key.append(round(self.ambient, 3))
else:
key.append(None)
if global_prefs['get_specular']:
for n in self.specular:
key.append(round(n, 3))
else:
key.extend([None, None, None])
if global_prefs['get_diffuse']:
for n in self.diffuse:
key.append(round(n, 3))
else:
key.extend([None, None, None])
# key.extend(self.face_props.values())
return tuple(key)
def __init__(self):
self.name = 'Material'
# Colors, List of 3 floats.
self.diffuse = [1.0, 1.0, 1.0]
self.specular = [1.0, 1.0, 1.0]
# Scalars
self.ambient = 0.0 # [0.0, 1.0]
self.emissive = 0.0 # [0.0, 1.0]
self.shininess = 0.5 # Range is [0.0, 2.0]
self.alpha = 1.0 # Range is [0.0, 1.0]
self.tex0 = None
# OpenFlight Face attributes
self.face_props = dict.fromkeys(['comment', 'ir color', 'priority',
'draw type', 'texture white', 'template billboard',
'smc', 'fid', 'ir material', 'lod generation control',
'flags', 'light mode'])
class VertexDesc:
def make_key(self):
return round(self.x, 6), round(self.y, 6), round(self.z, 6)
def __init__(self):
# Assign later, save memory, all verts have a loc
self.x = 0.0
self.y = 0.0
self.z = 0.0
self.nx = 0.0
self.ny = 0.0
self.nz = 0.0
self.uv= Vector(0,0)
self.cindex = 127 #default/lowest
self.cnorm = False
class LightPointAppDesc:
def make_key(self):
d = dict(self.props)
del d['id']
del d['type']
if d['directionality'] != 0: # not omni
d['nx'] = 0.0
d['ny'] = 0.0
d['nz'] = 0.0
return tuple(d.values())
def __init__(self):
self.props = dict()
self.props.update({'type': 'LPA'})
self.props.update({'id': 'ap'})
# Attribs not found in inline lightpoint.
self.props.update({'visibility range': 0.0})
self.props.update({'fade range ratio': 0.0})
self.props.update({'fade in duration': 0.0})
self.props.update({'fade out duration': 0.0})
self.props.update({'LOD range ratio': 0.0})
self.props.update({'LOD scale': 0.0})
class GlobalResourceRepository:
def request_lightpoint_app(self, desc, scene):
match = self.light_point_app.get(desc.make_key())
if match:
return match.getName()
else:
# Create empty and fill with properties.
name = desc.props['type'] + ': ' + desc.props['id']
object = Blender.Object.New('Empty', name)
scene.objects.link(object)
object.Layers= current_layer
object.sel= 1
# Attach properties
for name, value in desc.props.iteritems():
object.addProperty(name, value)
self.light_point_app.update({desc.make_key(): object})
return object.getName()
# Dont use request_vert - faster to make it from the vector direct.
"""
def request_vert(self, desc):
match = self.vert_dict.get(desc.make_key())
if match:
return match
else:
vert = Blender.Mathutils.Vector(desc.x, desc.y, desc.z)
''' IGNORE_NORMALS
vert.no[0] = desc.nx
vert.no[1] = desc.ny
vert.no[2] = desc.nz
'''
self.vert_dict.update({desc.make_key(): vert})
return vert
"""
def request_mat(self, mat_desc):
match = self.mat_dict.get(mat_desc.make_key())
if match: return match
mat = Blender.Material.New(mat_desc.name)
if mat_desc.tex0 != None:
mat.setTexture(0, mat_desc.tex0, Blender.Texture.TexCo.UV)
mat.setAlpha(mat_desc.alpha)
mat.setSpec(mat_desc.shininess)
mat.setHardness(255)
mat.setEmit(mat_desc.emissive)
mat.setAmb(mat_desc.ambient)
mat.setSpecCol(mat_desc.specular)
mat.setRGBCol(mat_desc.diffuse)
# Create a text object to store openflight face attribs until
# user properties can be set on materials.
# t = Blender.Text.New('FACE: ' + mat.getName())
#
# for name, value in mat_desc.face_props.items():
# t.write(name + '\n' + str(value) + '\n\n')
self.mat_dict.update({mat_desc.make_key(): mat})
return mat
def request_image(self, filename_with_path):
if not global_prefs['get_texture']: return None
return BPyImage.comprehensiveImageLoad(filename_with_path, global_prefs['fltfile']) # Use join in case of spaces
def request_texture(self, image):
if not global_prefs['get_texture']:
return None
tex = self.tex_dict.get(image.filename)
if tex: return tex
tex = Blender.Texture.New(Blender.sys.basename(image.filename))
tex.setImage(image)
tex.setType('Image')
self.tex_dict.update({image.filename: tex})
return tex
def __init__(self):
#list of scenes xrefs belong to.
self.xrefs = dict()
# material
self.mat_dict = dict()
mat_lst = Blender.Material.Get()
for mat in mat_lst:
mat_desc = MaterialDesc()
mapto_lst = mat.getTextures()
if mapto_lst[0]:
mat_desc.tex0 = mapto_lst[0].tex
else:
mat_desc.tex0 = None
mat_desc.alpha = mat.getAlpha()
mat_desc.shininess = mat.getSpec()
mat_desc.emissive = mat.getEmit()
mat_desc.ambient = mat.getAmb()
mat_desc.specular = mat.getSpecCol()
mat_desc.diffuse = mat.getRGBCol()
self.mat_dict.update({mat_desc.make_key(): mat})
# texture
self.tex_dict = dict()
tex_lst = Blender.Texture.Get()
for tex in tex_lst:
img = tex.getImage()
# Only interested in textures with images.
if img:
self.tex_dict.update({img.filename: tex})
# vertex
# self.vert_dict = dict()
# light point
self.light_point_app = dict()
class Handler:
def in_throw_back_lst(self, opcode):
return opcode in self.throw_back_lst
def handle(self, opcode):
return self.handler[opcode]()
def handles(self, opcode):
return opcode in self.handler.iterkeys()
def throws_back_all_unhandled(self):
return self.throw_back_unhandled
def set_throw_back_lst(self, a):
self.throw_back_lst = a
def set_throw_back_all_unhandled(self):
self.throw_back_unhandled = True
def set_only_throw_back_specified(self):
self.throw_back_unhandled = False
def set_handler(self, d):
self.handler = d
def __init__(self):
# Dictionary of opcodes to handler methods.
self.handler = dict()
# Send all opcodes not handled to the parent node.
self.throw_back_unhandled = False
# If throw_back_unhandled is False then only throw back
# if the opcodes in throw_back are encountered.
self.throw_back_lst = list()
class Node:
def blender_import(self):
if self.opcode in opcode_name and global_prefs['verbose'] >= 2:
for i in xrange(self.get_level()):
print ' ',
print opcode_name[self.opcode],
print '-', self.props['id'],
print '-', self.props['comment'],
print
for child in self.children:
child.blender_import()
# Import comment.
# if self.props['comment'] != '':
# name = 'COMMENT: ' + self.props['id']
# t = Blender.Text.New(name)
# t.write(self.props['comment'])
# self.props['comment'] = name
# Always ignore extensions and anything in between them.
def parse_push_extension(self):
self.saved_handler = self.active_handler
self.active_handler = self.extension_handler
return True
def parse_pop_extension(self):
self.active_handler = self.saved_handler
return True
def parse_push(self):
self.header.fw.up_level()
# Ignore unknown children.
self.ignore_unhandled = True
# Don't do child records that might overwrite parent info. ex: longid
self.active_handler = self.child_handler
return True
def parse_pop(self):
self.header.fw.down_level()
if self.header.fw.get_level() == self.level:
return False
return True
def parse(self):
while self.header.fw.begin_record():
opcode = self.header.fw.get_opcode()
# Print out info on opcode and tree level.
if global_prefs['verbose'] >= 3:
p = ''
for i in xrange(self.header.fw.get_level()):
p = p + ' '
if opcode in opcode_name:
p = p + opcode_name[opcode]
else:
if global_prefs['verbose'] >= 1:
print 'undocumented opcode', opcode
continue
if self.global_handler.handles(opcode):
if global_prefs['verbose'] >= 3:
print p + ' handled globally'
if self.global_handler.handle(opcode) == False:
break
elif self.active_handler.handles(opcode):
if global_prefs['verbose'] >= 4:
print p + ' handled'
if self.active_handler.handle(opcode) == False:
break
else:
if self.active_handler.throws_back_all_unhandled():
if global_prefs['verbose'] >= 3:
print p + ' handled elsewhere'
self.header.fw.repeat_record()
break
elif self.active_handler.in_throw_back_lst(opcode):
if global_prefs['verbose'] >= 3:
print p + ' handled elsewhere'
self.header.fw.repeat_record()
break
else:
if global_prefs['verbose'] >= 3:
print p + ' ignored'
elif global_prefs['verbose'] >= 1 and not opcode in do_not_report_opcodes and opcode in opcode_name:
print 'not handled'
def get_level(self):
return self.level
def parse_long_id(self):
self.props['id'] = self.header.fw.read_string(self.header.fw.get_length()-4)
return True
def parse_comment(self):
self.props['comment'] = self.header.fw.read_string(self.header.fw.get_length()-4)
return True
def parse_extension(self):
extension = dict()
props = records[100]
propkeys = props.keys()
propkeys.sort()
for position in propkeys:
(type,length,name) = props[position]
extension[name] = read_prop(self.header.fw,type,length)
#read extension data.
dstring = list()
for i in xrange(self.header.fw.get_length()-24):
dstring.append(self.header.fw.read_char())
extension['data'] = dstring
self.extension = extension
def parse_record(self):
self.props['type'] = self.opcode
props = records[self.opcode]
propkeys = props.keys()
propkeys.sort()
for position in propkeys:
(type,length,name) = props[position]
self.props[name] = read_prop(self.header.fw,type,length)
try: #remove me!
self.props['id'] = self.props['3t8!id']
except:
pass
def __init__(self, parent, header):
self.root_handler = Handler()
self.child_handler = Handler()
self.extension_handler = Handler()
self.global_handler = Handler()
self.global_handler.set_handler({21: self.parse_push_extension})
self.active_handler = self.root_handler
# used by parse_*_extension
self.extension_handler.set_handler({22: self.parse_pop_extension})
self.saved_handler = None
self.header = header
self.children = list()
self.parent = parent
if parent:
parent.children.append(self)
self.level = self.header.fw.get_level()
self.opcode = self.header.fw.get_opcode()
self.props = {'id': 'unnamed', 'comment': '', 'type': 'untyped'}
class VertexPalette(Node):
def __init__(self, parent):
Node.__init__(self, parent, parent.header)
self.root_handler.set_handler({68: self.parse_vertex_c,
69: self.parse_vertex_cn,
70: self.parse_vertex_cnuv,
71: self.parse_vertex_cuv})
self.root_handler.set_throw_back_all_unhandled()
self.vert_desc_lst = list()
self.blender_verts = list()
self.offset = 8
# Used to create a map from byte offset to vertex index.
self.index = dict()
def blender_import(self):
self.blender_verts.extend([Vector(vert_desc.x, vert_desc.y, vert_desc.z) for vert_desc in self.vert_desc_lst ])
def parse_vertex_common(self):
# Add this vertex to an offset to index dictionary.
#self.index_lst.append( (self.offset, self.next_index) )
self.index[self.offset]= len(self.index)
# Get ready for next record.
self.offset += self.header.fw.get_length()
v = VertexDesc()
self.header.fw.read_ahead(2)
v.flags = self.header.fw.read_short()
v.x = self.header.fw.read_double()
v.y = self.header.fw.read_double()
v.z = self.header.fw.read_double()
return v
def parse_vertex_post_common(self, v):
#if not v.flags & 0x2000: # 0x2000 = no color
#if v.flags & 0x1000: # 0x1000 = packed color
# v.a = self.header.fw.read_uchar()
# v.b = self.header.fw.read_uchar()
# v.g = self.header.fw.read_uchar()
# v.r = self.header.fw.read_uchar()
#else:
self.header.fw.read_ahead(4) #skip packed color
v.cindex = self.header.fw.read_uint()
self.vert_desc_lst.append(v)
return True
def parse_vertex_c(self):
v = self.parse_vertex_common()
self.parse_vertex_post_common(v)
return True
def parse_vertex_cn(self):
v = self.parse_vertex_common()
v.cnorm = True
v.nx = self.header.fw.read_float()
v.ny = self.header.fw.read_float()
v.nz = self.header.fw.read_float()
self.parse_vertex_post_common(v)
return True
def parse_vertex_cuv(self):
v = self.parse_vertex_common()
v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
self.parse_vertex_post_common(v)
return True
def parse_vertex_cnuv(self):
v = self.parse_vertex_common()
v.cnorm = True
v.nx = self.header.fw.read_float()
v.ny = self.header.fw.read_float()
v.nz = self.header.fw.read_float()
v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
self.parse_vertex_post_common(v)
return True
def parse(self): # Run once per import
Node.parse(self)
class InterNode(Node):
def __init__(self):
self.object = None
self.mesh = None
self.swapmesh = None
self.hasMesh = False
self.faceLs= []
self.matrix = None
self.vis = True
self.hasmtex = False
self.uvlayers = dict()
self.blayernames = dict()
self.subfacelevel = 0
self.extension = None
mask = 2147483648
for i in xrange(7):
self.uvlayers[mask] = False
mask = mask / 2
#######################################################
## Begin Remove Doubles Replacement ##
#######################################################
def __xvertsort(self,__a,__b):
(__vert, __x1) = __a
(__vert2,__x2) = __b
if __x1 > __x2:
return 1
elif __x1 < __x2:
return -1
return 0
def __calcFaceNorm(self,__face):
if len(__face) == 3:
return Blender.Mathutils.TriangleNormal(__face[0].co, __face[1].co, __face[2].co)
elif len(__face) == 4:
return Blender.Mathutils.QuadNormal(__face[0].co, __face[1].co, __face[2].co, __face[3].co)
def __replaceFaceVert(self,__weldface, __oldvert, __newvert):
__index = None
for __i, __v in enumerate(__weldface):
if __v == __oldvert:
__index = __i
break
__weldface[__index] = __newvert
def __matchEdge(self,__weldmesh, __edge1, __edge2):
if __edge1[0] in __weldmesh['Vertex Disk'][__edge2[1]] and __edge1[1] in __weldmesh['Vertex Disk'][__edge2[0]]:
return True
return False
#have to compare original faces!
def __faceWinding(self, __weldmesh, __face1, __face2):
__f1edges = list()
__f2edges = list()
__f1edges.append((__face1.verts[0], __face1.verts[1]))
__f1edges.append((__face1.verts[1], __face1.verts[2]))
if len(__face1.verts) == 3:
__f1edges.append((__face1.verts[2], __face1.verts[0]))
else:
__f1edges.append((__face1.verts[2], __face1.verts[3]))
__f1edges.append((__face1.verts[3], __face1.verts[0]))
__f2edges.append((__face2.verts[0], __face2.verts[1]))
__f2edges.append((__face2.verts[1], __face2.verts[2]))
if len(__face2.verts) == 3:
__f2edges.append((__face2.verts[2], __face2.verts[0]))
else:
__f2edges.append((__face2.verts[2], __face2.verts[3]))
__f2edges.append((__face2.verts[3], __face2.verts[0]))
#find a matching edge
for __edge1 in __f1edges:
for __edge2 in __f2edges:
if self.__matchEdge(__weldmesh, __edge1, __edge2): #no more tests nessecary
return True
return False
def __floatcompare(self, __f1, __f2):
epsilon = 0.1
if ((__f1 + epsilon) > __f2) and ((__f1 - epsilon) < __f2):
return True
return False
def __testFace(self,__weldmesh,__v1face, __v2face, __v1bface, __v2bface):
limit = 0.01
__matchvert = None
#frst test (for real this time!). Are the faces the same face?
if __v1face == __v2face:
return False
#first test: Do the faces possibly geometrically share more than two vertices? we should be comparing original faces for this? - Yes.....
__match = 0
for __vert in __v1bface.verts:
for __vert2 in __v2bface.verts:
#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!
if __vert2 in __weldmesh['Vertex Disk'][__vert] or __vert == __vert2:
__match += 1
__matchvert = __vert2
#avoid faces sharing more than two verts
if __match > 2:
return False
#consistent winding for face normals
if __match == 2:
if not self.__faceWinding(__weldmesh, __v1bface, __v2bface):
return False
#second test: Compatible normals.Anything beyond almost exact opposite is 'ok'
__v1facenorm = self.__calcFaceNorm(__v1face)
__v2facenorm = self.__calcFaceNorm(__v2face)
#dont even mess with zero length faces
if __v1facenorm.length < limit:
return False
if __v2facenorm.length < limit:
return False
__v1facenorm.normalize()
__v2facenorm.normalize()
if __match == 1:
#special case, look for comparison of normals angle
__angle = Blender.Mathutils.AngleBetweenVecs(__v1facenorm, __v2facenorm)
if __angle > 70.0:
return False
__v2facenorm = __v2facenorm.negate()
if self.__floatcompare(__v1facenorm[0], __v2facenorm[0]) and self.__floatcompare(__v1facenorm[1], __v2facenorm[1]) and self.__floatcompare(__v1facenorm[2], __v2facenorm[2]):
return False
#next test: dont weld a subface to a non-subface!
if __v1bface.getProperty("FLT_SFLEVEL") != __v2bface.getProperty("FLT_SFLEVEL"):
return False
#final test: edge test - We dont want to create a non-manifold edge through our weld operation
return True
def __copyFaceData(self, __source, __target):
#copy vcolor layers.
__actColLayer = self.mesh.activeColorLayer
for __colorlayer in self.mesh.getColorLayerNames():
self.mesh.activeColorLayer = __colorlayer
for __i, __col in enumerate(__source.col):
__target.col[__i].r = __col.r
__target.col[__i].g = __col.g
__target.col[__i].b = __col.b
self.mesh.activeColorLayer = __actColLayer
#copy uv layers.
__actUVLayer = self.mesh.activeUVLayer
for __uvlayer in self.mesh.getUVLayerNames():
self.mesh.activeUVLayer = __uvlayer
__target.image = __source.image
__target.mode = __source.mode
__target.smooth = __source.smooth
__target.transp = __source.transp
for __i, __uv in enumerate(__source.uv):
__target.uv[__i][0] = __uv[0]
__target.uv[__i][1] = __uv[1]
self.mesh.activeUVLayer = __actUVLayer
#copy property layers
for __property in self.mesh.faces.properties:
__target.setProperty(__property, __source.getProperty(__property))
def findDoubles(self):
limit = 0.01
sortblock = list()
double = dict()
for vert in self.mesh.verts:
double[vert] = None
sortblock.append((vert, vert.co[0] + vert.co[1] + vert.co[2]))
sortblock.sort(self.__xvertsort)
a = 0
while a < len(self.mesh.verts):
(vert,xsort) = sortblock[a]
b = a+1
if not double[vert]:
while b < len(self.mesh.verts):
(vert2, xsort2) = sortblock[b]
if not double[vert2]:
#first test, simple distance
if (xsort2 - xsort) > limit:
break
#second test, more expensive
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):
double[vert2] = vert
b+=1
a+=1
return double
def buildWeldMesh(self):
weldmesh = dict()
weldmesh['Vertex Disk'] = dict() #this is geometric adjacency
weldmesh['Vertex Faces'] = dict() #topological adjacency
#find the doubles for this mesh
double = self.findDoubles()
for vert in self.mesh.verts:
weldmesh['Vertex Faces'][vert] = list()
#create weld faces
weldfaces = list()
originalfaces = list()
for face in self.mesh.faces:
weldface = list()
for vert in face.verts:
weldface.append(vert)
weldfaces.append(weldface)
originalfaces.append(face)
for i, weldface in enumerate(weldfaces):
for vert in weldface:
weldmesh['Vertex Faces'][vert].append(i)
weldmesh['Weld Faces'] = weldfaces
weldmesh['Original Faces'] = originalfaces
#Now we need to build the vertex disk data. first we do just the 'target' vertices
for vert in self.mesh.verts:
if not double[vert]: #its a target
weldmesh['Vertex Disk'][vert] = list()
for vert in self.mesh.verts:
if double[vert]: #its a double
weldmesh['Vertex Disk'][double[vert]].append(vert)
#Now we need to create the disk information for the remaining vertices
targets = weldmesh['Vertex Disk'].keys()
for target in targets:
for doublevert in weldmesh['Vertex Disk'][target]:
weldmesh['Vertex Disk'][doublevert] = [target]
for othervert in weldmesh['Vertex Disk'][target]:
if othervert != doublevert:
weldmesh['Vertex Disk'][doublevert].append(othervert)
return weldmesh
def weldFuseFaces(self,weldmesh):
#slight modification here: we need to walk around the mesh as many times as it takes to have no more matches
done = 0
while not done:
done = 1
for windex, weldface in enumerate(weldmesh['Weld Faces']):
for vertex in weldface:
#we walk around the faces of the doubles of this vertex and if possible, we weld them.
for doublevert in weldmesh['Vertex Disk'][vertex]:
removeFaces = list() #list of faces to remove from doubleverts face list
for doublefaceindex in weldmesh['Vertex Faces'][doublevert]:
doubleface = weldmesh['Weld Faces'][doublefaceindex]
oface1 = self.mesh.faces[windex]
oface2 = self.mesh.faces[doublefaceindex]
ok = self.__testFace(weldmesh, weldface, doubleface, oface1, oface2)
if ok:
done = 0
removeFaces.append(doublefaceindex)
self.__replaceFaceVert(doubleface, doublevert, vertex)
for doublefaceindex in removeFaces:
weldmesh['Vertex Faces'][doublevert].remove(doublefaceindex)
#old faces first
oldindices = list()
for face in self.mesh.faces:
oldindices.append(face.index)
#make our new faces.
newfaces = list()
for weldface in weldmesh['Weld Faces']:
newfaces.append(weldface)
newindices = self.mesh.faces.extend(newfaces, indexList=True, ignoreDups=True)
#copy custom data over
for i, newindex in enumerate(newindices):
try:
self.__copyFaceData(self.mesh.faces[oldindices[i]], self.mesh.faces[newindex])
except:
print "warning, could not copy face data!"
#delete the old faces
self.mesh.faces.delete(1, oldindices)
#Clean up stray vertices
vertuse = dict()
for vert in self.mesh.verts:
vertuse[vert] = 0
for face in self.mesh.faces:
for vert in face.verts:
vertuse[vert] += 1
delverts = list()
for vert in self.mesh.verts:
if not vertuse[vert] and vert.index != 0:
delverts.append(vert)
self.mesh.verts.delete(delverts)
#######################################################
## End Remove Doubles Replacement ##
#######################################################
def blender_import_my_faces(self):
# Add the verts onto the mesh
blender_verts= self.header.vert_pal.blender_verts
vert_desc_lst= self.header.vert_pal.vert_desc_lst
vert_list= [ i for flt_face in self.faceLs for i in flt_face.indices] #splitting faces apart. Is this a good thing?
face_edges= []
face_verts= []
self.mesh.verts.extend([blender_verts[i] for i in vert_list])
new_faces= []
new_faces_props= []
ngon= BPyMesh.ngon
vert_index= 1
#add vertex color layer for baked face colors.
self.mesh.addColorLayer("FLT_Fcol")
self.mesh.activeColorLayer = "FLT_Fcol"
FLT_OrigIndex = 0
for flt_face in self.faceLs:
if flt_face.tex_index != -1:
try:
image= self.header.tex_pal[flt_face.tex_index][1]
except KeyError:
image= None
else:
image= None
face_len= len(flt_face.indices)
#create dummy uvert dicts
if len(flt_face.uverts) == 0:
for i in xrange(face_len):
flt_face.uverts.append(dict())
#May need to patch up MTex info
if self.hasmtex:
#For every layer in mesh, there should be corresponding layer in the face
for mask in self.uvlayers.keys():
if self.uvlayers[mask]:
if not flt_face.uvlayers.has_key(mask): #Does the face have this layer?
#Create Layer info for this face
flt_face.uvlayers[mask] = dict()
flt_face.uvlayers[mask]['texture index'] = -1
flt_face.uvlayers[mask]['texture enviorment'] = 3
flt_face.uvlayers[mask]['texture mapping'] = 0
flt_face.uvlayers[mask]['texture data'] = 0
#now go through and create dummy uvs for this layer
for uvert in flt_face.uverts:
uv = Vector(0.0,0.0)
uvert[mask] = uv
# Get the indicies in reference to the mesh.
uvs= [vert_desc_lst[j].uv for j in flt_face.indices]
if face_len == 1:
pass
elif face_len == 2:
face_edges.append((vert_index, vert_index+1))
elif flt_face.props['draw type'] == 2 or flt_face.props['draw type'] == 3:
i = 0
while i < (face_len-1):
face_edges.append((vert_index + i, vert_index + i + 1))
i = i + 1
if flt_face.props['draw type'] == 2:
face_edges.append((vert_index + i,vert_index))
elif face_len == 3 or face_len == 4: # tri or quad
#if face_len == 1:
# pass
#if face_len == 2:
# face_edges.append((vert_index, vert_index+1))
new_faces.append( [i+vert_index for i in xrange(face_len)] )
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))
else: # fgon
mesh_face_indicies = [i+vert_index for i in xrange(face_len)]
tri_ngons= ngon(self.mesh, mesh_face_indicies)
new_faces.extend([ [mesh_face_indicies[t] for t in tri] for tri in tri_ngons])
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 ])
vert_index+= face_len
FLT_OrigIndex+=1
self.mesh.faces.extend(new_faces)
self.mesh.edges.extend(face_edges)
#add in the FLT_ORIGINDEX layer
if len(self.mesh.faces):
try: self.mesh.faceUV= True
except: pass
if self.mesh.faceUV == True:
self.mesh.renameUVLayer(self.mesh.activeUVLayer, 'Layer0')
#create name layer for faces
self.mesh.faces.addPropertyLayer("FLT_ID",Blender.Mesh.PropertyTypes["STRING"])
#create layer for face color indices
self.mesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
#create index layer for faces. This is needed by both FGONs and subfaces
self.mesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"])
#create temporary FGON flag layer. Delete after remove doubles
self.mesh.faces.addPropertyLayer("FLT_FGON",Blender.Mesh.PropertyTypes["INT"])
self.mesh.faces.addPropertyLayer("FLT_SFLEVEL", Blender.Mesh.PropertyTypes["INT"])
for i, f in enumerate(self.mesh.faces):
props = new_faces_props[i]
if props[6]['template billboard'] > 0:
f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"]
if props[6]['template billboard'] == 2:
f.mode |= Blender.Mesh.FaceModes["BILLBOARD"]
f.mode |= Blender.Mesh.FaceModes["LIGHT"]
if props[6]['draw type'] == 1:
f.mode |= Blender.Mesh.FaceModes["TWOSIDE"]
#f.mat = props[0]
f.image = props[1]
f.uv = props[2]
#set vertex colors
color = self.header.get_color(props[5])
if not color:
color = [255,255,255,255]
for mcol in f.col:
mcol.a = color[3]
mcol.r = color[0]
mcol.g = color[1]
mcol.b = color[2]
f.setProperty("FLT_SFLEVEL", props[9])
f.setProperty("FLT_ORIGINDEX",i)
f.setProperty("FLT_ID",props[6]['id'])
#if props[5] > 13199:
# print "Warning, invalid color index read in! Using default!"
# f.setProperty("FLT_COL",127)
#else:
if(1): #uh oh....
value = struct.unpack('>i',struct.pack('>I',props[5]))[0]
f.setProperty("FLT_COL",value)
#if props[8]:
# f.setProperty("FLT_FGON",1)
#else:
# f.setProperty("FLT_FGON",0)
#Create multitex layers, if present.
actuvlayer = self.mesh.activeUVLayer
if(self.hasmtex):
#For every multi-tex layer, we have to add a new UV layer to the mesh
for i,mask in enumerate(reversed(sorted(self.uvlayers))):
if self.uvlayers[mask]:
self.blayernames[mask] = "Layer" + str(i+1)
self.mesh.addUVLayer(self.blayernames[mask])
#Cycle through availible multi-tex layers and add face UVS
for mask in self.uvlayers:
if self.uvlayers[mask]:
self.mesh.activeUVLayer = self.blayernames[mask]
for j, f in enumerate(self.mesh.faces):
if props[6]['draw type'] == 1:
f.mode |= Blender.Mesh.FaceModes["TWOSIDE"]
f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"]
f.mode |= Blender.Mesh.FaceModes["LIGHT"]
props = new_faces_props[j]
uvlayers = props[4]
if uvlayers.has_key(mask): #redundant
uverts = props[3]
for k, uv in enumerate(f.uv):
uv[0] = uverts[k][mask][0]
uv[1] = uverts[k][mask][1]
uvlayer = uvlayers[mask]
tex_index = uvlayer['texture index']
if tex_index != -1:
try:
f.image = self.header.tex_pal[tex_index][1]
except KeyError:
f.image = None
if global_prefs['smoothshading'] == True and len(self.mesh.faces):
#We need to store per-face vertex normals in the faces as UV layers and delete them later.
self.mesh.addUVLayer("FLTNorm1")
self.mesh.addUVLayer("FLTNorm2")
self.mesh.activeUVLayer = "FLTNorm1"
for f in self.mesh.faces:
f.smooth = 1
#grab the X and Y components of normal and store them in UV
for i, uv in enumerate(f.uv):
vert = f.v[i].index
vert_desc = vert_desc_lst[vert_list[vert-1]]
if vert_desc.cnorm:
uv[0] = vert_desc.nx
uv[1] = vert_desc.ny
else:
uv[0] = 0.0
uv[1] = 0.0
#Now go through and populate the second UV Layer with the z component
self.mesh.activeUVLayer = "FLTNorm2"
for f in self.mesh.faces:
for i, uv in enumerate(f.uv):
vert = f.v[i].index
vert_desc = vert_desc_lst[vert_list[vert-1]]
if vert_desc.cnorm:
uv[0] = vert_desc.nz
uv[1] = 0.0
else:
uv[0] = 0.0
uv[1] = 0.0
#Finally, go through, remove dummy vertex, remove doubles and add edgesplit modifier.
Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX'])
self.mesh.sel= 1
self.header.scene.update(1) #slow!
#self.mesh.remDoubles(0.0001)
weldmesh = self.buildWeldMesh()
welded = self.weldFuseFaces(weldmesh)
self.mesh.verts.delete(0) # remove the dummy vert
edgeHash = dict()
for edge in self.mesh.edges:
edgeHash[edge.key] = edge.index
if global_prefs['smoothshading'] == True and len(self.mesh.faces):
#rip out the custom vertex normals from the mesh and place them in a face aligned list. Easier to compare this way.
facenorms = []
self.mesh.activeUVLayer = "FLTNorm1"
for face in self.mesh.faces:
facenorm = []
for uv in face.uv:
facenorm.append(Vector(uv[0],uv[1],0.0))
facenorms.append(facenorm)
self.mesh.activeUVLayer = "FLTNorm2"
for i, face in enumerate(self.mesh.faces):
facenorm = facenorms[i]
for j, uv in enumerate(face.uv):
facenorm[j][2] = uv[0]
self.mesh.removeUVLayer("FLTNorm1")
self.mesh.removeUVLayer("FLTNorm2")
#find hard edges
#store edge data for lookup by faces
#edgeHash = dict()
#for edge in self.mesh.edges:
# edgeHash[edge.key] = edge.index
edgeNormHash = dict()
#make sure to align the edgenormals to key value!
for i, face in enumerate(self.mesh.faces):
facenorm = facenorms[i]
faceEdges = []
faceEdges.append((face.v[0].index,face.v[1].index,facenorm[0],facenorm[1],face.edge_keys[0]))
faceEdges.append((face.v[1].index,face.v[2].index,facenorm[1],facenorm[2],face.edge_keys[1]))
if len(face.v) == 3:
faceEdges.append((face.v[2].index,face.v[0].index,facenorm[2],facenorm[0],face.edge_keys[2]))
elif len(face.v) == 4:
faceEdges.append((face.v[2].index,face.v[3].index,facenorm[2],facenorm[3],face.edge_keys[2]))
faceEdges.append((face.v[3].index,face.v[0].index,facenorm[3],facenorm[0],face.edge_keys[3]))
#check to see if edgeNormal has been placed in the edgeNormHash yet
#this is a redundant test, and should be optimized to not be called as often as it is.
for j, faceEdge in enumerate(faceEdges):
#the value we are looking for is (faceEdge[2],faceEdge[3])
hashvalue = (faceEdge[2],faceEdge[3])
if (faceEdge[0],faceEdge[1]) != faceEdge[4]:
hashvalue = (hashvalue[1],hashvalue[0])
assert (faceEdge[1],faceEdge[0]) == faceEdge[4]
if edgeNormHash.has_key(faceEdge[4]):
#compare value in the hash, if different, mark as sharp
edgeNorm = edgeNormHash[faceEdge[4]]
if\
abs(hashvalue[0][0] - edgeNorm[0][0]) > FLOAT_TOLERANCE or\
abs(hashvalue[0][1] - edgeNorm[0][1]) > FLOAT_TOLERANCE or\
abs(hashvalue[0][2] - edgeNorm[0][2]) > FLOAT_TOLERANCE or\
abs(hashvalue[1][0] - edgeNorm[1][0]) > FLOAT_TOLERANCE or\
abs(hashvalue[1][1] - edgeNorm[1][1]) > FLOAT_TOLERANCE or\
abs(hashvalue[1][2] - edgeNorm[1][2]) > FLOAT_TOLERANCE:
edge = self.mesh.edges[edgeHash[faceEdge[4]]]
edge.flag |= Blender.Mesh.EdgeFlags.SHARP
else:
edgeNormHash[faceEdge[4]] = hashvalue
#add in edgesplit modifier
mod = self.object.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = True
mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = False
if(actuvlayer):
self.mesh.activeUVLayer = actuvlayer
def blender_import(self):
if self.vis and self.parent.object:
self.vis = self.parent.vis
name = self.props['id']
if self.hasMesh:
self.mesh = Blender.Mesh.New()
self.mesh.name = 'FLT_FaceList'
self.mesh.fakeUser = True
self.mesh.verts.extend( Vector()) #DUMMYVERT
self.object = self.header.scene.objects.new(self.mesh)
else:
self.object = self.header.scene.objects.new('Empty')
self.object.name = name
self.header.group.objects.link(self.object)
#id props import
self.object.properties['FLT'] = dict()
for key in self.props:
try:
self.object.properties['FLT'][key] = self.props[key]
except: #horrible...
pass
if self.extension:
self.object.properties['FLT']['EXT'] = dict()
for key in self.extension:
self.object.properties['FLT']['EXT'][key] = self.extension[key]
if self.parent and self.parent.object and (self.header.scene == self.parent.header.scene):
self.parent.object.makeParent([self.object],1)
if self.matrix:
self.object.setMatrix(self.matrix)
if self.vis == False:
self.object.restrictDisplay = True
self.object.restrictRender = True
else: #check for LOD children and set the proper flags
lodlist = list()
for child in self.children:
if child.props.has_key('type') and child.props['type'] == 73:
if child.props['6d!switch out'] != 0.0:
child.vis = False
#lodlist.append(child)
#def LODmin(a,b):
# if a.props['5d!switch in'] < b.props['5d!switch in']:
# return a
# return b
#min= None
#if len(lodlist) > 1:
# for lod in lodlist:
# lod.vis = False
# min = lodlist[0]
# for i in xrange(len(lodlist)):
# min= LODmin(min,lodlist[i])
# min.vis = True
Node.blender_import(self) # Attach faces to self.faceLs
if self.hasMesh:
# Add all my faces into the mesh at once
self.blender_import_my_faces()
def parse_face(self):
child = Face(self, self.subfacelevel)
child.parse()
return True
def parse_group(self):
child = Group(self)
child.parse()
return True
def move_to_next_layer(self):
global current_layer
current_layer = current_layer << 1
if current_layer > 0x80000:
current_layer = 1
def parse_lod(self):
child = LOD(self)
child.parse()
return True
def parse_unhandled(self):
child = Unhandled(self)
child.parse()
return True
def parse_object(self):
child = Object(self)
child.parse()
return True
def parse_xref(self):
child = XRef(self)
child.parse()
return True
def parse_dof(self):
child = DOF(self)
child.parse()
return True
def parse_indexed_light_point(self):
child = IndexedLightPoint(self)
child.parse()
return True
def parse_inline_light_point(self):
child = InlineLightPoint(self)
child.parse()
return True
def parse_matrix(self):
m = list()
for i in xrange(4):
m.append([])
for j in xrange(4):
f = self.header.fw.read_float()
m[i].append(f)
self.matrix = Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3])
def parse_subpush(self):
self.parse_push()
self.subfacelevel+= 1
return True
def parse_subpop(self):
self.parse_pop()
self.subfacelevel -= 1
return True
class Face(Node):
def __init__(self, parent,subfacelevel):
Node.__init__(self, parent, parent.header)
self.root_handler.set_handler({31: self.parse_comment,
10: self.parse_push,
52: self.parse_multitex})
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({72: self.parse_vertex_list,
10: self.parse_push,
11: self.parse_pop,
53: self.parse_uvlist})
if parent:
parent.hasMesh = True
self.subfacelevel = subfacelevel
self.indices = list() # face verts here
self.uvlayers = dict() # MultiTexture layers keyed to layer bitmask.
self.uverts = list() # Vertex aligned list of dictionaries keyed to layer bitmask.
self.uvmask = 0 # Bitfield read from MTex record
self.comment = ''
self.props = dict()
self.props['id'] = self.header.fw.read_string(8)
# Load face.
self.props['ir color'] = self.header.fw.read_int()
self.props['priority'] = self.header.fw.read_short()
self.props['draw type'] = self.header.fw.read_char()
self.props['texture white'] = self.header.fw.read_char()
self.header.fw.read_ahead(4) # color name indices
self.header.fw.read_ahead(1) # reserved
self.props['template billboard'] = self.header.fw.read_uchar()
self.detail_tex_index = self.header.fw.read_short()
self.tex_index = self.header.fw.read_short()
self.mat_index = self.header.fw.read_short()
self.props['smc'] = self.header.fw.read_short()
self.props['fid'] = self.header.fw.read_short()
self.props['ir material'] = self.header.fw.read_int()
self.alpha = 1.0 - float(self.header.fw.read_ushort()) / 65535.0
self.props['lod generation control'] = self.header.fw.read_uchar()
self.header.fw.read_ahead(1) # line style index
self.props['flags'] = self.header.fw.read_int()
self.props['light mode'] = self.header.fw.read_uchar()
self.header.fw.read_ahead(7)
a = self.header.fw.read_uchar()
b = self.header.fw.read_uchar()
g = self.header.fw.read_uchar()
r = self.header.fw.read_uchar()
self.packed_color = [r, g, b, a]
a = self.header.fw.read_uchar()
b = self.header.fw.read_uchar()
g = self.header.fw.read_uchar()
r = self.header.fw.read_uchar()
self.alt_packed_color = [r, g, b, a]
self.tex_map_index = self.header.fw.read_short()
self.header.fw.read_ahead(2)
self.color_index = self.header.fw.read_uint()
self.alt_color_index = self.header.fw.read_uint()
#self.header.fw.read_ahead(2)
#self.shader_index = self.header.fw.read_short()
def parse_comment(self):
self.comment = self.header.fw.read_string(self.header.fw.get_length()-4)
return True
def blender_import(self):
vert_count = len(self.indices)
if vert_count < 1:
if global_prefs['verbose'] >= 2:
print 'Warning: Ignoring face with no vertices.'
return
# Assign material and image
self.parent.faceLs.append(self)
#need to store comment in mesh prop layer!
# Store comment info in parent.
#if self.comment != '':
# if self.parent.props['comment'] != '':
# self.parent.props['comment'] += '\n\nFrom Face:\n' + self.comment
# else:
# self.parent.props['comment'] = self.comment
if self.uvlayers:
#Make sure that the mesh knows about the layers that this face uses
self.parent.hasmtex = True
for mask in self.uvlayers.keys():
self.parent.uvlayers[mask] = True
def parse_vertex_list(self):
length = self.header.fw.get_length()
fw = self.header.fw
vert_pal = self.header.vert_pal
count = (length-4)/4
# If this ever fails the chunk below does error checking
self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
'''
for i in xrange(count):
byte_offset = fw.read_int()
if byte_offset in vert_pal.index:
index = vert_pal.index[byte_offset]
self.indices.append(index)
elif global_prefs['verbose'] >= 1:
print 'Warning: Unable to map byte offset %s' + \
' to vertex index.' % byte_offset
'''
return True
def parse_multitex(self):
#Parse MultiTex Record.
length = self.header.fw.get_length()
fw = self.header.fw
#num layers == (length - 8) / 4
uvmask = fw.read_uint()
mask = 2147483648
for i in xrange(7):
if mask & uvmask:
uvlayer = dict()
self.uvlayers[mask] = uvlayer
mask = mask / 2
#read in record for each individual layer.
for key in reversed(sorted(self.uvlayers)):
uvlayer = self.uvlayers[key]
uvlayer['texture index'] = fw.read_ushort()
uvlayer['texture enviorment'] = fw.read_ushort()
uvlayer['texture mapping'] = fw.read_ushort()
uvlayer['texture data'] = fw.read_ushort()
self.uvmask = uvmask
def parse_uvlist(self):
#for each uvlayer, add uv vertices
length = self.header.fw.get_length()
fw = self.header.fw
uvmask = fw.read_uint()
if uvmask != self.uvmask: #This should never happen!
fw.read_ahead(self.length - 4) #potentially unnessecary?
else:
#need to store in uvverts dictionary for each vertex.
totverts = len(self.indices)
for i in xrange(totverts):
uvert = dict()
for key in reversed(sorted(self.uvlayers)):
uv = Vector(0.0,0.0)
uv[0] = fw.read_float()
uv[1] = fw.read_float()
uvert[key] = uv
self.uverts.append(uvert)
class Object(InterNode):
def __init__(self, parent):
Node.__init__(self, parent, parent.header)
InterNode.__init__(self)
self.root_handler.set_handler({33: self.parse_long_id,
21: self.parse_push_extension,
31: self.parse_comment,
10: self.parse_push,
49: self.parse_matrix})
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({5: self.parse_face,
19: self.parse_subpush,
20: self.parse_subpop,
111: self.parse_inline_light_point,
10: self.parse_push,
11: self.parse_pop})
self.extension_handler.set_handler({22: self.parse_pop_extension,
100: self.parse_extension})
self.extension = dict()
self.props = dict()
self.props['comment'] = ''
self.parse_record()
class Group(InterNode):
def __init__(self, parent):
Node.__init__(self, parent, parent.header)
InterNode.__init__(self)
self.root_handler.set_handler({33: self.parse_long_id,
31: self.parse_comment,
10: self.parse_push,
49: self.parse_matrix,
21: self.parse_push_extension})
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({5: self.parse_face,
19: self.parse_subpush,
20: self.parse_subpop,
111: self.parse_inline_light_point,
2: self.parse_group,
73: self.parse_lod,
4: self.parse_object,
10: self.parse_push,
11: self.parse_pop,
96: self.parse_unhandled,
14: self.parse_dof,
91: self.parse_unhandled,
98: self.parse_unhandled,
63: self.parse_xref})
self.extension_handler.set_handler({22: self.parse_pop_extension,
100: self.parse_extension})
self.props = dict.fromkeys(['type', 'id', 'comment', 'priority', 'flags', 'special1',
'special2', 'significance', 'layer code', 'loop count',
'loop duration', 'last frame duration'])
self.props['comment'] = ''
self.parse_record()
#self.props['type'] = str(self.opcode) + ':' + opcode_name[self.opcode]
#props = records[self.opcode]
#propkeys = props.keys()
#propkeys.sort()
#for position in propkeys:
# (type,length,name) = props[position]
# self.props[name] = read_prop(self.header.fw,type,length)
#self.props['id'] = self.props['3t8!id']
class DOF(InterNode):
def blender_import(self):
InterNode.blender_import(self)
def __init__(self, parent):
Node.__init__(self, parent, parent.header)
InterNode.__init__(self)
self.root_handler.set_handler({33: self.parse_long_id,
31: self.parse_comment,
10: self.parse_push,
49: self.parse_matrix,
21: self.parse_push_extension})
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({#130: self.parse_indexed_light_point,
111: self.parse_inline_light_point,
2: self.parse_group,
73: self.parse_lod,
4: self.parse_object,
10: self.parse_push,
11: self.parse_pop,
96: self.parse_unhandled,
14: self.parse_dof,
91: self.parse_unhandled,
98: self.parse_unhandled,
63: self.parse_xref})
self.extension_handler.set_handler({22: self.parse_pop_extension,
100: self.parse_extension})
self.props = dict()
self.props['comment'] = ''
self.parse_record()
class XRef(InterNode):
def parse(self):
if self.xref:
self.xref.parse()
Node.parse(self)
def __init__(self, parent):
Node.__init__(self, parent, parent.header)
InterNode.__init__(self)
self.root_handler.set_handler({49: self.parse_matrix})
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.props = dict()
self.props['comment'] = ''
self.parse_record()
xref_filename = self.props['3t200!filename'] #I dont even think there is a reason to keep this around...
if not os.path.isabs(xref_filename):
absname = os.path.join(os.path.dirname(self.header.filename), xref_filename)
else:
absname = xref_filename
self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(xref_filename))[0] #this is really wrong as well....
if global_prefs['doxrefs'] and os.path.exists(absname) and not self.header.grr.xrefs.has_key(xref_filename):
self.xref = Database(absname, self.header.grr, self)
self.header.grr.xrefs[xref_filename] = self.xref
else:
self.xref = None
def blender_import(self):
#name = self.props['type'] + ': ' + self.props['id']
name = self.props['id']
self.object = self.header.scene.objects.new('Empty')
self.object.name = name
self.object.enableDupGroup = True
self.header.group.objects.link(self.object)
#for broken links its ok to leave this empty! they purely for visual purposes anyway.....
try:
self.object.DupGroup = self.header.grr.xrefs[self.props['3t200!filename']].group
except:
pass
if self.parent and self.parent.object:
self.parent.object.makeParent([self.object],1)
if self.matrix:
self.object.setMatrix(self.matrix)
#id props import
self.object.properties['FLT'] = dict()
for key in self.props:
try:
self.object.properties['FLT'][key] = self.props[key]
except: #horrible...
pass
self.object.Layer = current_layer
self.object.sel = 1
Node.blender_import(self)
class LOD(InterNode):
def blender_import(self):
#self.move_to_next_layer()
InterNode.blender_import(self)
#self.object.properties['FLT'] = self.props.copy()
def __init__(self, parent):
Node.__init__(self, parent, parent.header)
InterNode.__init__(self)
self.root_handler.set_handler({33: self.parse_long_id,
31: self.parse_comment,
10: self.parse_push,
49: self.parse_matrix,
21: self.parse_push_extension})
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({2: self.parse_group,
111: self.parse_inline_light_point,
73: self.parse_lod,
4: self.parse_object,
10: self.parse_push,
11: self.parse_pop,
96: self.parse_unhandled, # switch
14: self.parse_dof, # DOF
91: self.parse_unhandled, # sound
98: self.parse_unhandled, # clip
63: self.parse_xref})
self.extension_handler.set_handler({22: self.parse_pop_extension,
100: self.parse_extension})
self.props = dict()
self.props['comment'] = ''
self.parse_record()
class InlineLightPoint(InterNode):
def __init__(self, parent):
Node.__init__(self, parent, parent.header)
InterNode.__init__(self)
self.root_handler.set_handler({33: self.parse_long_id,
31: self.parse_comment,
10: self.parse_push,
21: self.parse_push_extension,
49: self.parse_matrix})
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({72: self.parse_vertex_list,
10: self.parse_push,
11: self.parse_pop})
self.extension_handler.set_handler({22: self.parse_pop_extension,
100: self.parse_extension})
self.indices = list()
self.props = dict()
self.props['comment'] = ''
self.parse_record()
def blender_import(self):
name = self.props['id']
self.mesh= Blender.Mesh.New()
self.mesh.name = 'FLT_LP'
self.object = self.header.scene.objects.new(self.mesh)
self.object.name = name
#self.mesh.verts.extend(Vector() ) # DUMMYVERT
self.object.Layer = current_layer
self.object.sel= 1
self.object.properties['FLT'] = dict()
for key in self.props:
try:
self.object.properties['FLT'][key] = self.props[key]
except: #horrible...
pass
if self.extension:
self.object.properties['FLT']['EXT'] = dict()
for key in self.extension:
self.object.properties['FLT']['EXT'][key] = self.extension[key]
if self.parent and self.parent.object and self.header.scene == self.parent.header.scene:
self.parent.object.makeParent([self.object])
if self.matrix:
self.object.setMatrix(self.matrix)
self.mesh.verts.extend([self.header.vert_pal.blender_verts[i] for i in self.indices])
#add color index information.
self.mesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"])
for i, vindex in enumerate(self.indices):
vdesc = self.header.vert_pal.vert_desc_lst[vindex]
v = self.mesh.verts[i]
v.setProperty("FLT_VCOL",vdesc.cindex)
#for i, v in enumerate(self.mesh.verts):
# vdesc = self.header.vert_pal.vert_desc_lst[i]
# v.setProperty("FLT_VCOL",vdesc.cindex)
self.mesh.update()
def parse_vertex_list(self):
length = self.header.fw.get_length()
fw = self.header.fw
vert_pal = self.header.vert_pal
count = (length-4)/4
# If this ever fails the chunk below does error checking
self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
'''
for i in xrange(count):
byte_offset = fw.read_int()
if byte_offset in vert_pal.index:
index = vert_pal.index[byte_offset]
self.indices.append(index)
elif global_prefs['verbose'] >= 1:
print 'Warning: Unable to map byte offset %s' + \
' to vertex index.' % byte_offset
'''
return True
class IndexedLightPoint(InterNode):
# return dictionary: lp_app name => index list
def group_points(self, props):
name_to_indices = {}
for i in self.indices:
vert_desc = self.header.vert_pal.vert_desc_lst[i]
app_desc = LightPointAppDesc()
app_desc.props.update(props)
# add vertex normal and color
app_desc.props.update({'nx': vert_desc.nx})
app_desc.props.update({'ny': vert_desc.ny})
app_desc.props.update({'nz': vert_desc.nz})
app_desc.props.update({'r': vert_desc.r})
app_desc.props.update({'g': vert_desc.g})
app_desc.props.update({'b': vert_desc.b})
app_desc.props.update({'a': vert_desc.a})
app_name = self.header.grr.request_lightpoint_app(app_desc, self.header.scene)
if name_to_indices.get(app_name):
name_to_indices[app_name].append(i)
else:
name_to_indices.update({app_name: [i]})
return name_to_indices
def blender_import(self):
name = self.props['type'] + ': ' + self.props['id']
name_to_indices = self.group_points(self.header.lightpoint_appearance_pal[self.index])
for app_name, indices in name_to_indices.iteritems():
self.object = Blender.Object.New('Mesh', name)
self.mesh= Blender.Mesh.New()
self.mesh.verts.extend( Vector() ) # DUMMYVERT
self.object.link(self.mesh)
if self.parent:
self.parent.object.makeParent([self.object])
for i in indices:
vert = self.header.vert_pal.blender_verts[i]
self.mesh.verts.append(vert)
self.header.scene.objects.link(self.object)
self.object.Layer = current_layer
if self.matrix:
self.object.setMatrix(self.matrix)
# Import comment.
if self.props['comment'] != '':
name = 'COMMENT: ' + self.props['id']
t = Blender.Text.New(name)
t.write(self.props['comment'])
self.props['comment'] = name
# Attach properties.
self.props.update({'appearance': app_name})
for name, value in self.props.iteritems():
self.object.addProperty(name, value)
self.mesh.update()
def parse_vertex_list(self):
length = self.header.fw.get_length()
fw = self.header.fw
vert_pal = self.header.vert_pal
count = (length-4)/4
# If this ever fails the chunk below does error checking
self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
'''
for i in xrange(count):
byte_offset = fw.read_int()
if byte_offset in vert_pal.index:
index = vert_pal.index[byte_offset]
self.indices.append(index)
elif global_prefs['verbose'] >= 1:
print 'Warning: Unable to map byte offset %s' + \
' to vertex index.' % byte_offset
'''
return True
def __init__(self, parent):
Node.__init__(self, parent, parent.header)
InterNode.__init__(self)
self.root_handler.set_handler({33: self.parse_long_id,
31: self.parse_comment,
10: self.parse_push,
49: self.parse_matrix})
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({72: self.parse_vertex_list,
10: self.parse_push,
11: self.parse_pop})
self.indices = list()
self.props = dict.fromkeys(['id', 'type', 'comment', 'draw order', 'appearance'])
self.props['comment'] = ''
self.props['type'] = 'Light Point'
self.props['id'] = self.header.fw.read_string(8)
self.index = self.header.fw.read_int()
self.header.fw.read_ahead(4) # animation index
self.props['draw order'] = self.header.fw.read_int()
class Unhandled(InterNode):
def __init__(self, parent):
Node.__init__(self, parent, parent.header)
InterNode.__init__(self)
self.root_handler.set_handler({33: self.parse_long_id,
31: self.parse_comment,
10: self.parse_push,
49: self.parse_matrix})
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({2: self.parse_group,
73: self.parse_lod,
4: self.parse_object,
10: self.parse_push,
11: self.parse_pop,
96: self.parse_unhandled, # switch
14: self.parse_dof, # DOF
91: self.parse_unhandled, # sound
98: self.parse_unhandled, # clip
63: self.parse_xref})
self.props['id'] = self.header.fw.read_string(8)
class Database(InterNode):
def blender_import(self):
for key in self.tex_pal.keys():
path_filename= FF.find(self.tex_pal[key][0])
if path_filename != None:
img = self.grr.request_image(path_filename)
if img:
self.tex_pal[key][1] = img
elif global_prefs['verbose'] >= 1:
print 'Warning: Unable to find', self.tex_pal[key][0]
self.scene.properties['FLT'] = dict()
for key in self.props:
try:
self.scene.properties['FLT'][key] = self.props[key]
except: #horrible...
pass
self.scene.properties['FLT']['Main'] = 0
self.scene.properties['FLT']['Filename'] = self.bname
for child in self.children:
if child.props.has_key('type') and child.props['type'] == 73:
if child.props['6d!switch out'] != 0.0:
child.vis = False
#import color palette
carray = list()
for color in self.col_pal:
carray.append(struct.unpack('>i',struct.pack('>BBBB',color[0],color[1],color[2],color[3]))[0])
self.scene.properties['FLT']['Color Palette'] = carray
Node.blender_import(self)
def parse_appearance_palette(self):
props = dict()
self.fw.read_ahead(4) # reserved
props.update({'id': self.fw.read_string(256)})
index = self.fw.read_int()
props.update({'smc': self.fw.read_short()})
props.update({'fid': self.fw.read_short()})
props.update({'back color: a': self.fw.read_uchar()})
props.update({'back color: b': self.fw.read_uchar()})
props.update({'back color: g': self.fw.read_uchar()})
props.update({'back color: r': self.fw.read_uchar()})
props.update({'display mode': self.fw.read_int()})
props.update({'intensity': self.fw.read_float()})
props.update({'back intensity': self.fw.read_float()})
props.update({'minimum defocus': self.fw.read_float()})
props.update({'maximum defocus': self.fw.read_float()})
props.update({'fading mode': self.fw.read_int()})
props.update({'fog punch mode': self.fw.read_int()})
props.update({'directional mode': self.fw.read_int()})
props.update({'range mode': self.fw.read_int()})
props.update({'min pixel size': self.fw.read_float()})
props.update({'max pixel size': self.fw.read_float()})
props.update({'actual size': self.fw.read_float()})
props.update({'trans falloff pixel size': self.fw.read_float()})
props.update({'trans falloff exponent': self.fw.read_float()})
props.update({'trans falloff scalar': self.fw.read_float()})
props.update({'trans falloff clamp': self.fw.read_float()})
props.update({'fog scalar': self.fw.read_float()})
props.update({'fog intensity': self.fw.read_float()})
props.update({'size threshold': self.fw.read_float()})
props.update({'directionality': self.fw.read_int()})
props.update({'horizontal lobe angle': self.fw.read_float()})
props.update({'vertical lobe angle': self.fw.read_float()})
props.update({'lobe roll angle': self.fw.read_float()})
props.update({'dir falloff exponent': self.fw.read_float()})
props.update({'dir ambient intensity': self.fw.read_float()})
props.update({'significance': self.fw.read_float()})
props.update({'flags': self.fw.read_int()})
props.update({'visibility range': self.fw.read_float()})
props.update({'fade range ratio': self.fw.read_float()})
props.update({'fade in duration': self.fw.read_float()})
props.update({'fade out duration': self.fw.read_float()})
props.update({'LOD range ratio': self.fw.read_float()})
props.update({'LOD scale': self.fw.read_float()})
self.lightpoint_appearance_pal.update({index: props})
def parse_header(self):
self.props['type'] = 'Header'
self.props['comment'] = ''
self.props['id'] = self.fw.read_string(8)
self.props['version'] = self.fw.read_int()
self.fw.read_ahead(46)
self.props['units'] = self.fw.read_char()
self.props['set white'] = bool(self.fw.read_char())
self.props['flags'] = self.fw.read_int()
self.fw.read_ahead(24)
self.props['projection type'] = self.fw.read_int()
self.fw.read_ahead(36)
self.props['sw x'] = self.fw.read_double()
self.props['sw y'] = self.fw.read_double()
self.props['dx'] = self.fw.read_double()
self.props['dy'] = self.fw.read_double()
self.fw.read_ahead(24)
self.props['sw lat'] = self.fw.read_double()
self.props['sw lon'] = self.fw.read_double()
self.props['ne lat'] = self.fw.read_double()
self.props['ne lon'] = self.fw.read_double()
self.props['origin lat'] = self.fw.read_double()
self.props['origin lon'] = self.fw.read_double()
self.props['lambert lat1'] = self.fw.read_double()
self.props['lambert lat2'] = self.fw.read_double()
self.fw.read_ahead(16)
self.props['ellipsoid model'] = self.fw.read_int()
self.fw.read_ahead(4)
self.props['utm zone'] = self.fw.read_short()
self.fw.read_ahead(6)
self.props['dz'] = self.fw.read_double()
self.props['radius'] = self.fw.read_double()
self.fw.read_ahead(8)
self.props['major axis'] = self.fw.read_double()
self.props['minor axis'] = self.fw.read_double()
if global_prefs['verbose'] >= 1:
print 'OpenFlight Version:', float(self.props['version']) / 100.0
print
return True
def parse_mat_palette(self):
mat_desc = MaterialDesc()
index = self.fw.read_int()
name = self.fw.read_string(12)
if len(mat_desc.name) > 0:
mat_desc.name = name
flag = self.fw.read_int()
# skip material if not used
if not flag & 0x80000000:
return True
ambient_col = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
mat_desc.diffuse = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
mat_desc.specular = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
emissive_col = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
mat_desc.shininess = self.fw.read_float() / 64.0 # [0.0, 128.0] => [0.0, 2.0]
mat_desc.alpha = self.fw.read_float()
# Convert ambient and emissive colors into intensitities.
mat_desc.ambient = col_to_gray(ambient_col)
mat_desc.emissive = col_to_gray(emissive_col)
self.mat_desc_pal_lst.append( (index, mat_desc) )
return True
def get_color(self, color_index):
color = None
index = color_index / 128
intensity = float(color_index - 128.0 * index) / 127.0
if index >= 0 and index <= 1023:
brightest = self.col_pal[index]
r = int(brightest[0] * intensity)
g = int(brightest[1] * intensity)
b = int(brightest[2] * intensity)
a = int(brightest[3])
color = [r, g, b, a]
return color
def parse_color_palette(self):
self.header.fw.read_ahead(128)
for i in xrange(1024):
a = self.header.fw.read_uchar()
b = self.header.fw.read_uchar()
g = self.header.fw.read_uchar()
r = self.header.fw.read_uchar()
self.col_pal.append((r, g, b, a))
return True
def parse_vertex_palette(self):
self.vert_pal = VertexPalette(self)
self.vert_pal.parse()
return True
def parse_texture_palette(self):
name = self.fw.read_string(200)
index = self.fw.read_int()
self.tex_pal[index]= [name, None]
return True
def read_attribute_files(self):
for tex in self.tex_pal.keys():
[name,image] = self.tex_pal[tex]
basename = os.path.basename(name)
if(image):
basename = basename + ".attr"
dirname = os.path.dirname(Blender.sys.expandpath(image.getFilename())) #can't rely on original info stored in pallette since it might be relative link
newpath = os.path.join(dirname, basename)
if os.path.exists(newpath) and not image.properties.has_key('FLT'):
fw = flt_filewalker.FltIn(newpath)
fw.read_ahead(8) #We dont care what the attribute file says about x/y dimensions
image.properties['FLT']={}
#need to steal code from parse records....
props = records['Image']
propkeys = props.keys()
propkeys.sort()
for position in propkeys:
(type,length,name) = props[position]
image.properties['FLT'][name] = read_prop(fw,type,length)
fw.close_file()
#copy clamp settings
wrap = image.properties['FLT']['10i!Wrap']
wrapu = image.properties['FLT']['11i!WrapU']
wrapv = image.properties['FLT']['12i!WrapV']
if wrapu == 3 or wrapv == 3:
wrapuv = (wrap,wrap)
else:
wrapuv = (wrapu, wrapv)
image.clampX = wrapuv[0]
image.clampY = wrapuv[1]
elif not os.path.exists(newpath):
print "Cannot read attribute file:" + newpath
def __init__(self, filename, grr, parent=None):
if global_prefs['verbose'] >= 1:
print 'Parsing:', filename
print
#check to see if filename is a relative path
#filename = os.path.abspath(filename)
self.fw = flt_filewalker.FltIn(filename)
self.filename = filename
self.bname = os.path.splitext(os.path.basename(filename))[0]
self.grr = grr
Node.__init__(self, parent, self)
InterNode.__init__(self)
self.root_handler.set_handler({1: self.parse_header,
67: self.parse_vertex_palette,
33: self.parse_long_id,
31: self.parse_comment,
64: self.parse_texture_palette,
32: self.parse_color_palette,
113: self.parse_mat_palette,
128: self.parse_appearance_palette,
10: self.parse_push})
if parent:
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({#130: self.parse_indexed_light_point,
111: self.parse_inline_light_point,
2: self.parse_group,
73: self.parse_lod,
4: self.parse_object,
10: self.parse_push,
11: self.parse_pop,
96: self.parse_unhandled,
14: self.parse_dof,
91: self.parse_unhandled,
98: self.parse_unhandled,
63: self.parse_xref})
self.scene = Blender.Scene.New(self.bname)
self.group = Blender.Group.New(self.bname)
self.vert_pal = None
self.lightpoint_appearance_pal = dict()
self.tex_pal = dict()
#self.tex_pal_lst = list()
#self.bl_tex_pal = dict()
self.col_pal = list()
self.mat_desc_pal_lst = list()
self.mat_desc_pal = dict()
self.props = dict.fromkeys(['id', 'type', 'comment', 'version', 'units', 'set white',
'flags', 'projection type', 'sw x', 'sw y', 'dx', 'dy', 'dz', 'sw lat',
'sw lon', 'ne lat', 'ne lon', 'origin lat', 'origin lon', 'lambert lat1',
'lambert lat2', 'ellipsoid model', 'utm zone', 'radius', 'major axis', 'minor axis'])
def clearparent(root,childhash):
for child in childhash[root]:
clearparent(child,childhash)
root.clrParent(2,0)
def fixscale(root,childhash):
for child in childhash[root]:
fixscale(child,childhash)
location = Blender.Mathutils.Vector(root.getLocation('worldspace'))
if location[0] != 0.0 or location[1] != 0.0 or location[2] != 0.0:
#direction = Blender.Mathutils.Vector(0-location[0],0-location[1],0-location[2]) #reverse vector
smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4)
root.setLocation(location * smat)
#if its a mesh, we need to scale all of its vertices too
if root.type == 'Mesh':
smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4)
rmesh = root.getData(mesh=True)
for v in rmesh.verts:
v.co = v.co * smat
def reparent(root,childhash,sce):
for child in childhash[root]:
reparent(child,childhash,sce)
root.makeParent(childhash[root])
sce.update(1)
def update_scene(root,sdone):
for object in root.objects:
if object.DupGroup:
try:
child = Blender.Scene.Get(object.DupGroup.name)
except:
child = None
if child and child not in sdone:
update_scene(child,sdone)
root.makeCurrent()
#create a list of children for each object
childhash = dict()
for object in root.objects:
childhash[object] = list()
for object in root.objects:
if object.parent:
childhash[object.parent].append(object)
for object in root.objects:
if not object.parent:
#recursivley go through and clear all the children of their transformation, starting at deepest level first.
clearparent(object,childhash)
#now fix the location of everything
fixscale(object,childhash)
#now fix the parenting
reparent(object,childhash,root)
for object in root.objects:
object.makeDisplayList()
root.update(1)
sdone.append(root)
def select_file(filename, grr):
if not Blender.sys.exists(filename):
msg = 'Error: File ' + filename + ' does not exist.'
Blender.Draw.PupMenu(msg)
return
if not filename.lower().endswith('.flt'):
msg = 'Error: Not a flight file.'
Blender.Draw.PupMenu(msg)
print msg
print
return
global_prefs['fltfile']= filename
global_prefs['verbose']= 1
global_prefs['get_texture'] = True
global_prefs['get_diffuse'] = True
global_prefs['get_specular'] = False
global_prefs['get_emissive'] = False
global_prefs['get_alpha'] = True
global_prefs['get_ambient'] = False
global_prefs['get_shininess'] = True
global_prefs['color_from_face'] = True
global_prefs['log to blender'] = True
Blender.Window.WaitCursor(True)
Blender.Window.EditMode(0)
FF.add_file_to_search_path(filename)
if global_prefs['verbose'] >= 1:
print 'Pass 1: Loading.'
print
load_time = Blender.sys.time()
db = Database(filename,grr)
db.parse()
load_time = Blender.sys.time() - load_time
if global_prefs['verbose'] >= 1:
print
print 'Pass 2: Importing to Blender.'
print
import_time = Blender.sys.time()
db.blender_import()
if global_prefs['attrib']:
print "reading attribute files"
db.read_attribute_files()
Blender.Window.ViewLayer(range(1,21))
update_scene(db.scene,[])
import_time = Blender.sys.time() - import_time
if global_prefs['verbose'] >= 1:
print 'Done.'
print
print 'Time to parse file: %.3f seconds' % load_time
print 'Time to import to blender: %.3f seconds' % import_time
print 'Total time: %.3f seconds' % (load_time + import_time)
Blender.Window.WaitCursor(False)
def setimportscale(ID,val):
global global_prefs
global_prefs['scale'] = val
def setBpath(fname):
global_prefs['fltfile'] = fname
d = dict()
for key in global_prefs:
d[key] = global_prefs[key]
Blender.Registry.SetKey('flt_import', d, 1)
def event(evt,val):
pass
def but_event(evt):
global FLTBaseLabel
global FLTBaseString
global FLTBaseChooser
global FLTExport
global FLTClose
global FLTDoXRef
global FLTShadeImport
global FLTAttrib
#Import DB
if evt == 1:
if global_prefs['verbose'] >= 1:
print
print 'OpenFlight Importer'
print 'Version:', __version__
print 'Author: Greg MacDonald, Campbell Barton, Geoffrey Bantle'
print __url__[2]
print
GRR = GlobalResourceRepository()
select_file(global_prefs['fltfile'], GRR)
#choose base path for export
if evt == 4:
Blender.Window.FileSelector(setBpath, "DB Root", global_prefs['fltfile'])
#Import custom shading?
if evt == 9:
global_prefs['smoothshading'] = FLTShadeImport.val
#Import Image attribute files
if evt == 10:
global_prefs['attrib'] = FLTAttrib.val
#export XRefs
if evt == 13:
global_prefs['doxrefs'] = FLTDoXRef.val
if evt == 2:
Draw.Exit()
d = dict()
for key in global_prefs:
d[key] = global_prefs[key]
Blender.Registry.SetKey('flt_import', d, 1)
from Blender.BGL import *
from Blender import Draw
def gui():
global FLTBaseLabel
global FLTBaseString
global FLTBaseChooser
global FLTExport
global FLTClose
global FLTDoXRef
global FLTShadeImport
global FLTAttrib
glClearColor(0.772,0.832,0.847,1.0)
glClear(GL_COLOR_BUFFER_BIT)
areas = Blender.Window.GetScreenInfo()
curarea = Blender.Window.GetAreaID()
curRect = None
for area in areas:
if area['id'] == curarea:
curRect = area['vertices']
break
width = curRect[2] - curRect[0]
height = curRect[3] - curRect[1]
cx = 50
cy = height - 80
FLTBaseLabel = Draw.Label("Base file:",cx,cy,100,20)
FLTBaseString = Draw.String("",3,cx+100,cy,300,20,global_prefs['fltfile'],255,"Root DB file")
FLTBaseChooser = Draw.PushButton("...",4,cx+400,cy,20,20,"Choose Folder")
cy = cy-40
FLTScale = Draw.Number("Import Scale",14,cx,cy,220,20,global_prefs['scale'],0.0,100.0,"Export scaleing factor",setimportscale)
cy = cy-40
FLTDoXRef = Draw.Toggle("Import XRefs", 13,cx,cy,220,20,global_prefs['doxrefs'],"Import External references")
cy = cy-40
FLTShadeImport = Draw.Toggle("Import Custom Shading",9,cx,cy,220,20,global_prefs['smoothshading'],"Import custom shading via edgesplit modifiers")
cy = cy-40
FLTAttrib = Draw.Toggle("Import Attribute Files", 10,cx,cy,220,20,global_prefs['attrib'],"Import Image Attribute files")
cy = cy - 40
FLTExport = Draw.PushButton("Import",1,cx,20,100,20,"Import FLT Database")
FLTClose = Draw.PushButton("Close",2,cx+120,20,100,20,"Close Window")
Draw.Register(gui,event,but_event)