Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoffrey Bantle <hairbat@yahoo.com>2007-11-22 04:43:24 +0300
committerGeoffrey Bantle <hairbat@yahoo.com>2007-11-22 04:43:24 +0300
commit78ea4f35646927a65c9a703d09f6e766bdd3b4ca (patch)
tree9d299663cd8d1bbcd3b92a6b06812ec1b6c02bc6 /release
parent313553b1edb02660361ebc281516fe8b6c122b7f (diff)
-> Updated FLT scripts
Blender FLT I/O scripts have been updated to have more features.In addition several utility scripts/applets have been added to aid in working with FLT databases within Blender. Documentation can be found here: http://wiki.blender.org/index.php/Scripts/Manual/Import/openflight_flt http://wiki.blender.org/index.php/Scripts/Manual/Export/openflight_flt http://wiki.blender.org/index.php/Scripts/Manual/FLTools
Diffstat (limited to 'release')
-rw-r--r--release/scripts/flt_defaultp.py1
-rw-r--r--release/scripts/flt_export.py1485
-rw-r--r--release/scripts/flt_filewalker.py9
-rw-r--r--release/scripts/flt_import.py1581
-rw-r--r--release/scripts/flt_palettemanager.py388
-rw-r--r--release/scripts/flt_properties.py619
-rw-r--r--release/scripts/flt_toolbar.py594
7 files changed, 3710 insertions, 967 deletions
diff --git a/release/scripts/flt_defaultp.py b/release/scripts/flt_defaultp.py
new file mode 100644
index 00000000000..5dca8ba63d7
--- /dev/null
+++ b/release/scripts/flt_defaultp.py
@@ -0,0 +1 @@
+pal = [-256,0,16711680,-16777216,-19529984,-19726592,-19923200,-20119808,-20316416,-20578560,-20840704,-21102848,-21364992,-21692672,-22020352,-22413568,-22806784,-23200000,-23658752,-24117504,-24641792,-25166080,-25755904,-26411264,-27066624,-27787520,-28573952,-29425920,-30343424,-31326464,-32375040,-33489152,-354550016,-371458304,-388366592,-405274880,-422183168,-439156992,-456130816,-473104640,-506855680,-540672256,-574488832,-608305408,-642121984,-676004096,-709886208,-760611072,-811335936,-862060800,-912851200,-980418816,-1048051968,-1115685120,-1183383808,-1267925248,-1352466688,-1453850880,-1555300608,-1656815872,-1775173888,-1893597440,-2028863744,2130771712,-1010376448,-1043996416,-1077681920,-1111367424,-1145052928,-1178738432,-1229201152,-1279663872,-1330126592,-1380654848,-1431183104,-1498488576,-1565794048,-1633165056,-1700536064,-1784684288,-1868832512,-1969823488,-2070814464,2123096320,2005262592,1887428864,1752752384,1601298688,1449779456,1281417472,1096278272,911073536,709026048,490201344,254533888,2023680,-1380857856,-1397700608,-1431320576,-1464940544,-1498560512,-1532180480,-1565865984,-1599551488,-1650014208,-1700476928,-1750939648,-1801402368,-1851865088,-1919170560,-1986476032,-2053781504,-2121086976,2089797632,2005649408,1904723968,1803798528,1686030336,1568262144,1450493952,1315883008,1164494848,1013041152,844810240,659736576,457885696,239192064,3655680,-1767919872,-1784762624,-1801605376,-1818448128,-1852068096,-1885688064,-1919308032,-1952928000,-1986547968,-2020167936,-2070565120,-2120962304,2123542272,2073079552,2022616832,1955376896,1888136960,1820897024,1736879872,1652797184,1568714496,1467854592,1366994688,1249357568,1131654912,997175040,862695168,711372544,560049920,391950080,207007488,5287680,2139657728,2122880512,2106103296,2089326080,2072548864,2055771648,2022217216,1988662784,1955108352,1921553920,1887933952,1854313984,1803916800,1753519616,1703122432,1652725248,1602328064,1535153664,1467979264,1400804864,1316853248,1232901632,1148950016,1048221184,947426816,846632448,729060864,611489280,477140480,326014464,174888448,6919680,1837268224,1820491008,1803713792,1786936576,1770159360,1753382144,1736604928,1719827712,1686273280,1652718848,1619164416,1585609984,1552055552,1518501120,1468169472,1417837824,1367506176,1317174528,1266842880,1199734016,1132625152,1065516288,998407424,914521344,830635264,729971968,629308672,528645376,411204864,293764352,159546624,8551680,-2086957824,-2103735040,-2120512256,-2137289472,2140900608,2107346176,2073791744,2040237056,2006682368,1973127680,1939572992,1906018304,1855686400,1805354496,1755022592,1704690688,1654358784,1587249664,1520140544,1453031424,1369145088,1285258496,1201371904,1100708096,1000044288,882603264,765162240,630943744,496725248,345729536,177956608,10183680,-1699438080,-1716215552,-1732993024,-1766547712,-1800102400,-1833657088,-1867211776,-1900766464,-1934321152,-1967875840,-2018207744,-2068539904,-2118872064,2125763072,2058653696,1991544320,1924434944,1857325568,1773438720,1689551872,1588887808,1488223744,1387559424,1270117888,1152676352,1018457600,884238592,733242368,565468672,397694976,213144064,11815680,-1311918848,-1345473536,-1379028224,-1412582912,-1446137600,-1479692544,-1513247488,-1546802432,-1597134592,-1647466752,-1697798912,-1748131072,-1798463488,-1865573120,-1932682752,-1999792384,-2083679232,2127400960,2043513856,1942849536,1842184960,1724743168,1607301376,1473082112,1338862848,1187866112,1020092160,852317952,667766528,466437632,248331264,13447680,-924399104,-957954048,-991508992,-1025063936,-1058618880,-1092173824,-1142505984,-1192838144,-1243170560,-1293502976,-1343835392,-1410945024,-1478054656,-1545164544,-1629051648,-1712938752,-1796826112,-1897490688,-1998155264,-2098820096,2078705152,1961262848,1827043328,1676046336,1525049344,1357274880,1172722944,971393792,753287168,518403072,283518720,15079680,-570434304,-603989248,-637544192,-671099136,-704654080,-754986496,-805318912,-855651328,-905983744,-973093632,-1040203520,-1107313408,-1174423296,-1258310656,-1342198016,-1442862848,-1543527680,-1644192512,-1761634816,-1879077120,-2013296896,2147450624,1996453376,1828678656,1660903936,1476351744,1275022080,1056914944,822030336,570368256,301928704,16711680,-503325440,-536880384,-570435328,-603990272,-637545216,-671100416,-721432832,-771765248,-822097664,-872430336,-922763008,-989872896,-1056982784,-1124092928,-1191203072,-1275090688,-1358978304,-1459643136,-1560308224,-1660973312,-1778415872,-1895858432,-2030078464,2113891328,1962893824,1795118848,1610566400,1426013696,1224683520,1006575872,771690752,520028160,-452993792,-469771520,-503326464,-536881408,-570436352,-603991552,-637546752,-671101952,-721434368,-771767040,-822099712,-872432384,-922765056,-989875200,-1056985344,-1124095744,-1191206144,-1275093760,-1358981632,-1459646720,-1560312064,-1677754624,-1795197440,-1912640512,-2046860800,2097108736,1946110720,1778335232,1593782272,1392451840,1174343936,939458560,-419439360,-436217088,-452994816,-469772544,-503327488,-536882688,-570437888,-603993088,-637548288,-671103744,-721436416,-771769088,-822101760,-872434688,-922767616,-989878016,-1056988416,-1124098816,-1207986688,-1291874560,-1375762688,-1476428032,-1577093632,-1694536704,-1811979776,-1946200320,-2080421120,2063547904,1912549376,1744773376,1560219904,1358888960,-385884928,-402662656,-419440384,-436218112,-452995840,-469773824,-503329024,-536884224,-570439424,-603994880,-637550336,-671105792,-721438464,-771771392,-822104320,-872437504,-922770688,-989881088,-1056991744,-1124102400,-1191213312,-1275101440,-1358989824,-1459655680,-1560321536,-1677764864,-1795208448,-1912652288,-2046873600,2097094912,1946095872,1778319360,-335553280,-352331008,-369108736,-385886464,-402664192,-419442176,-436220160,-452998144,-486553344,-520108800,-553664256,-587219712,-620775168,-654330880,-687886592,-738219776,-788552960,-838886144,-889219584,-939553024,-1006663936,-1073774848,-1140886016,-1224774656,-1308663296,-1392552192,-1493218560,-1593885184,-1711329280,-1828773632,-1962995456,-2097217536,-285221632,-301999360,-318777088,-335554816,-352332544,-369110528,-385888512,-402666496,-419444480,-436222720,-453000960,-469779200,-503334656,-536890368,-570446080,-604002048,-637558016,-671113984,-721447424,-771780864,-822114560,-872448256,-922782208,-989893632,-1057005056,-1124116736,-1191228672,-1275118080,-1359007744,-1459674880,-1560342272,-1677787136,-234889984,-234890496,-251668224,-268445952,-285223680,-302001664,-318779648,-335557632,-352335616,-369113856,-385892096,-402670336,-419448576,-436227072,-453005568,-469784320,-503340288,-536896256,-570452480,-604008704,-637565184,-671121664,-704678400,-755012608,-805346816,-855681280,-906016000,-973128192,-1040240640,-1107353344,-1174466304,-1258356736,-234889984,-234890496,-234891008,-234891520,-234892032,-234892800,-234893568,-234894336,-234895104,-251673344,-268451584,-285229824,-302008064,-318786560,-335565056,-352343808,-369122560,-385901312,-402680320,-419459328,-436238592,-453017856,-486574592,-520131584,-553688576,-587245824,-620803328,-654361088,-687919104,-738254592,-788590336,-838926336,-234889984,-234890496,-234891008,-234891520,-234892032,-234892800,-234893568,-234894336,-234895104,-234896128,-234897152,-234898176,-234899200,-234900480,-234901760,-234903296,-234904832,-234906368,-234908160,-234909952,-234912000,-251691264,-268470784,-285250560,-302030336,-318810368,-335590656,-352371200,-369152000,-385933056,-402714368,-419495936,-8960,-9472,-9984,-10496,-11008,-11776,-12544,-13312,-14080,-15104,-16128,-17152,-18176,-19456,-20736,-22272,-23808,-25344,-27136,-28928,-30976,-33024,-35328,-37888,-40448,-43264,-46336,-49664,-53248,-57088,-61184,-65536,-926464,-926976,-927488,-928000,-928512,-929280,-930048,-930816,-931584,-932608,-933632,-934656,-935680,-936960,-938240,-939776,-941312,-1008384,-1075712,-1143040,-1210624,-1278208,-1346048,-1414144,-1482240,-1550592,-1619200,-1688064,-1757184,-1826560,-1896192,-2031616,-926464,-926976,-927488,-928000,-928512,-929280,-930048,-996352,-1062656,-1129216,-1195776,-1262336,-1328896,-1395712,-1462528,-1529600,-1596672,-1663744,-1731072,-1798400,-1865984,-1999104,-2132480,-2266112,-2399744,-2533632,-2667776,-2867712,-3067904,-3268352,-3469056,-3670016,-926464,-992512,-1058560,-1124608,-1190656,-1256960,-1323264,-1389568,-1455872,-1522432,-1588992,-1655552,-1722112,-1788928,-1855744,-1988352,-2120960,-2253568,-2386432,-2519296,-2652416,-2785536,-2984448,-3183616,-3382784,-3582208,-3847424,-4112896,-4378624,-4644608,-4976384,-5308416,-1188608,-1254656,-1320704,-1386752,-1452800,-1519104,-1585408,-1651712,-1718016,-1784576,-1851136,-1983232,-2115328,-2247680,-2380032,-2512640,-2645248,-2777856,-2976256,-3174656,-3373312,-3571968,-3836416,-4101120,-4365824,-4630784,-4961536,-5292544,-5689344,-6086400,-6483712,-6946816,-1385216,-1451264,-1517312,-1583360,-1649408,-1715712,-1782016,-1848320,-1980160,-2112256,-2244352,-2376448,-2508544,-2640896,-2838784,-3036928,-3235072,-3433216,-3631616,-3895552,-4159744,-4423936,-4688384,-5018624,-5348864,-5744896,-6141184,-6537728,-7000064,-7462656,-7991040,-8585216,-1581824,-1647872,-1713920,-1779968,-1846016,-1977856,-2109696,-2241536,-2373376,-2505472,-2637568,-2769664,-2967296,-3165184,-3363072,-3561216,-3759360,-4023040,-4286976,-4550912,-4880640,-5210368,-5540352,-5936128,-6331904,-6793472,-7255296,-7782912,-8310784,-8904448,-9563904,-10223616,-1712896,-1778944,-1844992,-1976576,-2108160,-2240000,-2371840,-2503680,-2635520,-2767616,-2965248,-3162880,-3360512,-3558400,-3821824,-4085504,-4349184,-4612864,-4942336,-5271808,-5667072,-6062336,-6457856,-6919168,-7380480,-7907584,-8434944,-9028096,-9687040,-10346240,-11071232,-11862016,-1843968,-1975552,-2107136,-2238720,-2370304,-2502144,-2633984,-2765824,-2963200,-3160832,-3358464,-3556096,-3753728,-4017152,-4280576,-4544256,-4873472,-5202688,-5532160,-5927168,-6322432,-6783232,-7244288,-7771136,-8297984,-8890624,-9549056,-10207744,-10932224,-11722496,-12578560,-13500416,-1975040,-2106624,-2238208,-2369792,-2501376,-2633216,-2830592,-3027968,-3225344,-3422976,-3620608,-3883776,-4146944,-4410368,-4673792,-5003008,-5332224,-5726976,-6121984,-6582528,-7043328,-7504128,-8030720,-8623104,-9215488,-9873664,-10597632,-11387392,-12242944,-13164288,-14085888,-15138816,-2237184,-2368768,-2500352,-2631936,-2763520,-2960896,-3158272,-3355648,-3553024,-3816192,-4079360,-4342528,-4605696,-4934656,-5263616,-5658368,-6053120,-6447872,-6908416,-7368960,-7895296,-8421632,-9013760,-9671680,-10329600,-11053312,-11842816,-12698112,-13619200,-14606080,-15658752,-16777216] \ No newline at end of file
diff --git a/release/scripts/flt_export.py b/release/scripts/flt_export.py
index 283c24a3ad0..d2e90bc27b8 100644
--- a/release/scripts/flt_export.py
+++ b/release/scripts/flt_export.py
@@ -1,45 +1,25 @@
#!BPY
""" Registration info for Blender menus:
Name: 'OpenFlight (.flt)...'
-Blender: 237
+Blender: 245
Group: 'Export'
Tip: 'Export to OpenFlight v16.0 (.flt)'
"""
-__author__ = "Greg MacDonald"
-__version__ = "1.2 10/20/05"
+__author__ = "Greg MacDonald, Geoffrey Bantle"
+__version__ = "2.0 11/21/07"
__url__ = ("blender", "elysiun", "Author's homepage, http://sourceforge.net/projects/blight/")
__bpydoc__ = """\
This script exports v16.0 OpenFlight files. OpenFlight is a
registered trademark of MultiGen-Paradigm, Inc.
-Run from "File->Export" menu.
-
-Options are available from Blender's "Scripts Config Editor," accessible through
-the "Scripts->System" menu from the scripts window.
-
-Features:<br>
-* Heirarchy retained.<br>
-* Normals retained.<br>
-* First texture exported.<br>
-* Diffuse material color is exported as the face color, material color, or both
-depending on the option settings.<br>
-* Double sided faces are exported as two faces.<br>
-* Object transforms exported.
-
-Things To Be Aware Of:<br>
-* Object names are exported, not mesh or data names.
-* Material indices that don't have a material associated with them will confuse the
-exporter. If a warning appears about this, correct it by deleting the offending
-material indices in Blender.
-
-What's Not Handled:<br>
-* Animations.<br>
-* Vetex colors.<br>
+Feature overview and more availible at:
+http://wiki.blender.org/index.php/Scripts/Manual/Export/openflight_flt
"""
# flt_export.py is an OpenFlight exporter for blender.
-# Copyright (C) 2005 Greg MacDonald
+#
+# 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
@@ -56,29 +36,87 @@ What's Not Handled:<br>
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import Blender
+from Blender import Modifier
+import os.path
+import flt_properties
+import flt_defaultp as defaultp
from flt_filewalker import FltOut
+from flt_filewalker import FileFinder
+from flt_properties import *
+import shutil
+
+FF = FileFinder()
+records = process_recordDefs()
class ExporterOptions:
def __init__(self):
- self.defaults = { 'Diffuse Color To OpenFlight Material': False,
- 'Diffuse Color To OpenFlight Face': True}
+ self.verbose = 1
+ self.tolerance = 0.001
+ self.writevcol = True
- d = Blender.Registry.GetKey('flt_export', True)
+ #new stuff
+ self.export_shading = 0
+ self.shading_default = 45.0
+ self.basepath = os.path.dirname(Blender.Get('filename'))
+ self.scale = 1.0
- if d == None or d.keys() != self.defaults.keys():
- d = self.defaults
- Blender.Registry.SetKey('flt_export', d, True)
+ #set externals path
+ if(os.path.exists(os.path.join(self.basepath,'externals'))):
+ self.externalspath = os.path.join(self.basepath,'externals')
+ else:
+ self.externalspath = self.basepath
- self.verbose = 1
- self.tolerance = 0.001
- self.use_mat_color = d['Diffuse Color To OpenFlight Material']
- self.use_face_color = d['Diffuse Color To OpenFlight Face']
+ self.doxrefs = 1
+
+ #texture options
+ if(os.path.exists(os.path.join(self.basepath,'textures'))):
+ self.texturespath = os.path.join(self.basepath,'textures')
+ else:
+ self.texturespath = self.basepath
+
+ #misc
+ self.write_attrib_files = 0
+ self.copy_textures = 0
+ self.export_transform = 0
+ self.flattenmesh = False
+ self.xapp = 1
+ reg = Blender.Registry.GetKey('flt_export',1)
+ if(reg and 'xappath' in reg.keys()):
+ self.xappath = reg['xappath']
+ else:
+ self.xappath = ''
options = ExporterOptions()
+tex_files = dict() #a list of (possibly) modified texture path names
+
+tex_layers = ['Layer0', 'Layer1', 'Layer2', 'Layer3', 'Layer4', 'Layer5', 'Layer6', 'Layer7']
+mask = 2147483648
+mtexmasks = []
+for i in xrange(7):
+ mtexmasks.append(mask)
+ mask = mask / 2
FLOAT_TOLERANCE = options.tolerance
+#need to move all this stuff to flt_properties.py.
identity_matrix = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
+alltypes = [2,4,11,73,63,111]
+childtypes = {
+ 2 : [111,2,73,4,14,63],
+ 4 : [111],
+ 73 : [111,2,73,4,14,63],
+ 63 : [],
+ 14 : [111,2,73,4,14,63],
+ 111 : []
+}
+recordlen = {
+ 2: 44,
+ 4: 28,
+ 73: 80,
+ 63: 216,
+ 14: 384,
+ 111: 156
+}
def is_identity(m):
for i in xrange(4):
@@ -102,13 +140,47 @@ class MaterialDesc:
self.alpha = 1.0 # Range is [0.0, 1.0]
class VertexDesc:
- def __init__(self, co=None, no=None, uv=None):
+ def __init__(self, co=None, no=None, uv=None, fltindex=None,cindex=None):
if co: self.x, self.y, self.z = tuple(co)
else: self.x = self.y = self.z = 0.0
if no: self.nx, self.ny, self.nz = tuple(no)
else: self.nx = self.ny = self.nz = 0.0
if uv: self.u, self.v = tuple(uv)
else: self.u = self.v = 0.0
+ if cindex: self.cindex = cindex
+ else: self.cindex = 127
+ self.fltindex = fltindex
+ self.accum = 0
+
+class shadowVert:
+ def __init__(self,bvert,object,world,normal):
+ global options
+
+ self.co = Blender.Mathutils.Vector(bvert.co[0],bvert.co[1],bvert.co[2])
+ #if world:
+ # vec = self.co
+ # vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale
+ # self.co = Blender.Mathutils.TranslationMatrix(vec) * (self.co * object.getMatrix('worldspace'))
+
+ if normal:
+ #if world:
+ # self.no = Blender.Mathutils.Vector(normal * object.getMatrix('worldspace')).normalize()
+ #else:
+ self.no = Blender.Mathutils.Vector(normal[0],normal[1],normal[2])
+
+ else:
+ #if world:
+ #self.no = Blender.Mathutils.Vector(bvert.no * object.getMatrix('worldspace')).normalize()
+ #else:
+ self.no = Blender.Mathutils.Vector(bvert.no[0],bvert.no[1],bvert.no[2])
+
+ #do scaling factor
+ #if options.scale != 1.0:
+ #self.co[0] = self.co[0] * options.scale
+ #self.co[1] = self.co[1] * options.scale
+ #self.co[2] = self.co[2] * options.scale
+
+ self.index = bvert.index
class GlobalResourceRepository:
def new_face_name(self):
@@ -121,44 +193,98 @@ class GlobalResourceRepository:
def request_vertex_desc(self, i):
return self.vertex_lst[i]
- def request_vertex_index(self, desc):
- match = None
- for i, v in enumerate(self.vertex_lst):
- if\
- abs(v.x - desc.x) > FLOAT_TOLERANCE or\
- abs(v.y - desc.y) > FLOAT_TOLERANCE or\
- abs(v.z - desc.z) > FLOAT_TOLERANCE or\
- abs(v.nx - desc.nx) > FLOAT_TOLERANCE or\
- abs(v.ny - desc.ny) > FLOAT_TOLERANCE or\
- abs(v.nz - desc.nz) > FLOAT_TOLERANCE or\
- abs(v.u - desc.u) > FLOAT_TOLERANCE or\
- abs(v.v - desc.v) > FLOAT_TOLERANCE:
- pass
- else:
- match = i
- break
+ def request_vertex_index(self, object, mesh, face, vfindex, uvok,cindex):
- if match != None:
- return match
+ flatShadeNorm = None
+
+ if type(face) is list:
+ vertex = face[vfindex]
+ elif str(type(face)) == "<type " + "'Blender MVert'>":
+ vertex = face
+ elif str(type(face)) == "<type " + "'Blender MEdge'>":
+ if vfindex == 1:
+ vertex = face.v1
+ elif vfindex == 2:
+ vertex = face.v2
+ elif str(type(face)) == "<type " + "'Blender MFace'>":
+ if not face.smooth:
+ flatShadeNorm = face.no
+ vertex = face.v[vfindex]
+ else:
+ return None
+
+ if not self.namehash.has_key(object.name):
+ self.namehash[object.name] = dict()
+ indexhash = self.namehash[object.name]
+
+ #export in global space? THIS HAS BEEN MADE REDUNDANT... REMOVE ME
+ if not options.export_transform:
+ vertex = shadowVert(vertex,object,True,flatShadeNorm)
else:
- self.vertex_lst.append(desc)
- return len(self.vertex_lst) - 1
-
- def request_texture_index(self, filename):
+ vertex = shadowVert(vertex,object,False,flatShadeNorm)
+
+
+ #Check to see if this vertex has been visited before. If not, add
+ if not indexhash.has_key(vertex.index):
+ if uvok:
+ newvdesc = VertexDesc(vertex.co, vertex.no, face.uv[vfindex], self.nextvindex,cindex=cindex)
+ else:
+ newvdesc = VertexDesc(co=vertex.co, no=vertex.no,fltindex=self.nextvindex,cindex=cindex)
+
+ indexhash[vertex.index] = [newvdesc]
+ self.vertex_lst.append(newvdesc)
+ self.nextvindex = self.nextvindex + 1
+ return newvdesc.fltindex
+
+ else:
+ desclist = indexhash[vertex.index]
+ if uvok:
+ faceu = face.uv[vfindex][0]
+ facev = face.uv[vfindex][1]
+ else:
+ faceu = 0.0
+ facev = 0.0
+ for vdesc in desclist:
+ if\
+ abs(vdesc.x - vertex.co[0]) > FLOAT_TOLERANCE or\
+ abs(vdesc.y - vertex.co[1]) > FLOAT_TOLERANCE or\
+ abs(vdesc.z - vertex.co[2]) > FLOAT_TOLERANCE or\
+ abs(vdesc.nx - vertex.no[0]) > FLOAT_TOLERANCE or\
+ abs(vdesc.ny - vertex.no[1]) > FLOAT_TOLERANCE or\
+ abs(vdesc.nz - vertex.no[2]) > FLOAT_TOLERANCE or\
+ vdesc.cindex != cindex or\
+ abs(vdesc.u - faceu) > FLOAT_TOLERANCE or\
+ abs(vdesc.v - facev) > FLOAT_TOLERANCE:
+ pass
+ else:
+ return vdesc.fltindex
+
+ #if we get this far, we didnt find a match. Add a new one and return
+ if uvok:
+ newvdesc = VertexDesc(vertex.co, vertex.no, face.uv[vfindex], self.nextvindex,cindex=cindex)
+ else:
+ newvdesc = VertexDesc(co=vertex.co, no=vertex.no,fltindex=self.nextvindex,cindex=cindex)
+ indexhash[vertex.index].append(newvdesc)
+ self.vertex_lst.append(newvdesc)
+ self.nextvindex = self.nextvindex + 1
+ return newvdesc.fltindex
+
+
+ def request_texture_index(self, image):
match = None
for i in xrange(len(self.texture_lst)):
- if self.texture_lst[i] != filename:
+ if self.texture_lst[i] != image:
continue
match = i
break
if match != None:
return match
else:
- self.texture_lst.append(filename)
+ self.texture_lst.append(image)
return len(self.texture_lst) - 1
def request_texture_filename(self, index):
- return self.texture_lst[index]
+ return Blender.sys.expandpath(self.texture_lst[index].getFilename())
def texture_count(self):
return len(self.texture_lst)
@@ -239,7 +365,11 @@ class GlobalResourceRepository:
return len(self.color_lst)
def __init__(self):
+ #Vertex handling
self.vertex_lst = []
+ self.nextvindex = 0
+ self.namehash = dict()
+
self.texture_lst = []
self.material_lst = []
self.color_lst = [[255, 255, 255]]
@@ -253,7 +383,6 @@ class Node:
if self.object:
if options.verbose >= 2:
print '\t' * level[0], self.name, self.object.type
-
level[0] += 1
for child in self.children:
@@ -288,183 +417,530 @@ class Node:
self.header.fw.write_ushort(length+5) # Length of record
self.header.fw.write_string(name, length+1) # name + zero terminator
+ def write_comment(self,comment):
+ length = len(comment)
+ if length >= 65535:
+ comment = comment[:65530]
+ length = len(comment)
+
+ pad = (length % 4) - 1
+ if pad < 0:
+ pad = None
+ reclength = length + 5
+ else:
+ reclength = length + 5 + pad
+
+ self.header.fw.write_short(31) # Comment Opcode
+ self.header.fw.write_ushort(reclength) # Length of record is 4 + comment length + null terminator + pad
+ self.header.fw.write_string(comment,length+1) # comment + zero terminator
+ if pad:
+ self.header.fw.pad(pad) # pad to multiple of 4 bytes
+
# Initialization sets up basic tree structure.
- def __init__(self, parent, header, object, object_lst):
+ def __init__(self, parent, header, object,props):
+ global options
+
self.header = header
self.object = object
if object:
self.name = self.object.name
- self.matrix = self.object.getMatrix('localspace')
+ if not options.export_transform:
+ oloc = Blender.Mathutils.Vector(object.getLocation('worldspace'))
+ vec = Blender.Mathutils.Vector(oloc[0] * options.scale, oloc[1] * options.scale, oloc[2] * options.scale) #scale
+ self.matrix = self.object.getMatrix('worldspace') * Blender.Mathutils.TranslationMatrix(vec - oloc)
+ else:
+ self.matrix = self.object.getMatrix('localspace') #do matrix mult here.
+ self.props = props
+ self.child_objects = self.header.parenthash[object.name]
else:
self.name = 'no name'
self.matrix = None
-
+ self.props = None
+ self.child_objects = self.header.child_objects
+
self.children = []
self.parent = parent
if parent:
parent.children.append(self)
-
- left_over = object_lst[:]
- self.child_objects = []
-
- # Add children to child list and remove from left_over list.
- # Pop is faster then remove
- i = len(object_lst)
- while i:
- i-=1
- if object_lst[i].parent == object:
- self.child_objects.append(left_over.pop(i))
-
# Spawn children.
- self.has_object_child = False # For Database class.
for child in self.child_objects:
- if child.type == 'Mesh':
- BlenderMesh(self, header, child, left_over)
- self.has_object_child = True
- else: # Treat all non meshes as emptys
- BlenderEmpty(self, header, child, left_over)
-
+ if(not child.restrictDisplay):
+ childprops = None
+ type = None
+ if not child.properties.has_key('FLT'):
+ if child.type == 'Empty':
+ if child.DupGroup:
+ childprops = FLTXRef.copy()
+ type = 63
+ else:
+ childprops = FLTGroup.copy()
+ type = 2
+ elif child.type == 'Mesh':
+ if self.header.childhash[child.name] or not child.parent:
+ childprops = FLTGroup.copy()
+ type = 2
+ else:
+ childprops = FLTObject.copy()
+ type = 4
+
+ else:
+ childprops = dict()
+ for prop in child.properties['FLT']:
+ childprops[prop] = child.properties['FLT'][prop]
+ type = child.properties['FLT']['type']
+
+ if type in self.childtypes and type in alltypes:
+ Newnode = FLTNode(self,header,child,childprops,type)
+ if child.type == 'Mesh':
+ self.header.mnodes.append(Newnode)
class FaceDesc:
def __init__(self):
self.vertex_index_lst = []
+ self.mface = None
self.texture_index = -1
self.material_index = -1
self.color_index = 127
-
-class BlenderMesh(Node):
- def blender_export(self):
- Node.blender_export(self)
-
- mesh = self.object.getData()
- mesh_hasuv = mesh.hasFaceUV()
- # Gather materials and textures.
- tex_index_lst = []
- mat_index_lst = []
- color_index_lst = []
- materials = mesh.getMaterials()
-
- if not materials:
- materials = [Blender.Material.New()]
-
- for mat in materials:
- # Gather Color.
- if options.use_face_color:
- color_index_lst.append(self.header.GRR.request_color_index(mat.getRGBCol()))
+ self.renderstyle = 0
+ self.twoside = 0
+ self.name = None #uses next FLT name if not set... fix resolution of conflicts!
+
+ #Multi-Tex info. Dosn't include first UV Layer!
+ self.uvlayer = list() #list of list of tuples for UV coordinates.
+ self.images = list() #list of texture indices for seperate UV layers
+ self.mtex = list()
+ self.subface = None #can either be 'Push' or 'Pop'
+
+def edge_get_othervert(vert, edge):
+ if edge.v1 == vert:
+ return edge.v2
+ elif edge.v2 == vert:
+ return edge.v1
+ return None
+
+class FLTNode(Node):
+ def walkLoop(self, targetvert, startvert, startedge, edgelist, visited, vedges, closeloop):
+ loop = [targetvert]
+
+ curvert = startvert
+ curedge = startedge
+ visited[curedge] = True
+ found = False
+
+ while not found:
+ loop.append(curvert)
+ disk = vedges[curvert.index]
+ if not closeloop:
+ if len(disk) == 1:
+ visited[curedge] = True
+ break
else:
- color_index_lst.append(127) # white
- # Gather Texture.
- mtex_lst = mat.getTextures()
-
- index = -1
- mtex = mtex_lst[0] # Not doing multi-texturing at the moment.
- if mtex != None:
- tex = mtex_lst[0].tex
- if tex != None:
- image = tex.getImage()
- if image != None:
- filename = image.getFilename()
- index = self.header.GRR.request_texture_index(filename)
-
- tex_index_lst.append(index)
-
- # Gather Material
- mat_desc = MaterialDesc()
- mat_desc.name = mat.name
- mat_desc.alpha = mat.getAlpha()
- mat_desc.shininess = mat.getSpec() * 64.0 # 2.0 => 128.0
- if options.use_mat_color:
- mat_desc.diffuse = mat.getRGBCol()
+ if len(disk) < 2: #what?
+ visited[curedge] = True
+ return None
+
+ if disk[0] == curedge:
+ curedge = disk[1]
else:
- mat_desc.diffuse = [1.0, 1.0, 1.0]
+ curedge = disk[0]
+ if curedge.v1.index == curvert.index:
+ curvert = curedge.v2
+ else:
+ curvert = curedge.v1
- mat_desc.specular = mat.getSpecCol()
- amb = mat.getAmb()
- mat_desc.ambient = [amb, amb, amb]
- emit = mat.getEmit()
- mat_desc.emissive = [emit, emit, emit]
+ visited[curedge] = True
+
+ if(curvert == targetvert):
+ found = True
+
+ return loop
+
+ def buildVertFaces(self,vertuse):
+ for vert in self.exportmesh.verts:
+ if vertuse[vert.index][0] == False and vertuse[vert.index][1] == 0:
+ face_desc = FaceDesc()
+ face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, vert, 0,0,0))
+ face_desc.renderstyle = 3
+ face_desc.color_index = 227
+ self.face_lst.append(face_desc)
- mat_index_lst.append(self.header.GRR.request_material_index(mat_desc))
+ def buildEdgeFaces(self,vertuse):
+ for edge in self.exportmesh.edges:
+ v1 = vertuse[edge.v1.index]
+ v2 = vertuse[edge.v2.index]
+ if v1[0] == False and v2[0] == False:
+ if v1[1] == 1 and v2[1] == 1:
+ face_desc = FaceDesc()
+ face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, edge, 1, 0,0))
+ face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, edge, 2, 0,0))
+ face_desc.renderstyle = 3
+ face_desc.color_index = 227
+ self.face_lst.append(face_desc)
+
+
+ def vertwalk(self, startvert, loop, disk, visited):
+ visited[startvert] = True
+ for edge in disk[startvert]:
+ othervert = edge_get_othervert(startvert, edge)
+ if not visited[othervert]:
+ loop.append(othervert)
+ self.vertwalk(othervert,loop,disk,visited)
+
+ def buildOpenFacesNew(self, vertuse):
+ wireverts = list()
+ wiredges = list()
+ visited = dict()
+ disk = dict()
+ loops = list()
+
+ for edge in self.exportmesh.edges:
+ v1 = vertuse[edge.v1.index]
+ v2 = vertuse[edge.v2.index]
+ if v1[0] == False and v2[0] == False:
+ if v1[1] < 3 and v2[1] < 3:
+ wireverts.append(edge.v1)
+ wireverts.append(edge.v2)
+ wiredges.append(edge)
+
+ #build disk data
+ for vert in wireverts:
+ visited[vert] = False
+ disk[vert] = list()
+ for edge in wiredges:
+ disk[edge.v1].append(edge)
+ disk[edge.v2].append(edge)
+
+ #first pass: do open faces
+ for vert in wireverts:
+ if not visited[vert] and vertuse[vert.index][1] == 1:
+ visited[vert] = True
+ loop = [vert]
+ othervert = edge_get_othervert(vert, disk[vert][0])
+ self.vertwalk(othervert, loop, disk, visited)
+ if len(loop) > 2: loops.append( ('Open', loop) )
+
+ for vert in wireverts:
+ if not visited[vert]:
+ visited[vert] = True
+ loop = [vert]
+ othervert = edge_get_othervert(vert,disk[vert][0])
+ self.vertwalk(othervert, loop, disk, visited)
+ if len(loop) > 2: loops.append( ('closed', loop) )
+
+ #now go through the loops and append.
+ for l in loops:
+ (type, loop) = l
+ face_desc = FaceDesc()
+ for i,vert in enumerate(loop):
+ face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,loop,i,0,0))
+ if type == 'closed':
+ face_desc.renderstyle = 2
+ else:
+ face_desc.renderstyle = 3
+ face_desc.color_index = 227
+ self.face_lst.append(face_desc)
- # Faces described as lists of indices into the GRR's vertex_lst.
- for face in mesh.faces:
-
- face_v = face.v # Faster access
-
- # Create vertex description list for each face.
- if mesh_hasuv:
- vertex_lst = [VertexDesc(v.co, v.no, face.uv[i]) for i, v in enumerate(face_v)]
- else:
- vertex_lst = [VertexDesc(v.co, v.no) for i, v in enumerate(face_v)]
+ def sortFLTFaces(self,a,b):
+ aindex = a.getProperty("FLT_ORIGINDEX")
+ bindex = b.getProperty("FLT_ORIGINDEX")
+
+ if aindex > bindex:
+ return 1
+ elif aindex < bindex:
+ return -1
+ return 0
+
+ def buildNormFaces(self):
+
+ global options
+ meshlayers = self.exportmesh.getUVLayerNames()
+ oldlayer = self.exportmesh.activeUVLayer
+ uvok = 0
+ subfaceok = 0
+ subfacelevel = 0
+
+ #special case
+ if self.exportmesh.faceUV and len(meshlayers) == 1:
+ uvok = 1
+ elif self.exportmesh.faceUV and tex_layers[0] in meshlayers:
+ self.exportmesh.activeUVLayer = tex_layers[0]
+ uvok = 1
+
+ #Sort faces according to the subfaces/FLT indices
+ if "FLT_ORIGINDEX" in self.exportmesh.faces.properties and "FLT_SFLEVEL" in self.exportmesh.faces.properties:
+ exportfaces = list()
+ for face in self.exportmesh.faces:
+ exportfaces.append(face)
+ exportfaces.sort(self.sortFLTFaces)
+ subfaceok = 1
+ else:
+ exportfaces = self.exportmesh.faces
+ # Faces described as lists of indices into the GRR's vertex_lst.
+ for face in exportfaces:
+ descs = list()
+ #first we export the face as normal
index_lst = []
- for vert_desc in vertex_lst:
- index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
-
+ face_v = face.verts
+ for i, v in enumerate(face_v):
+ index_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,face,i,uvok,0))
face_desc = FaceDesc()
face_desc.vertex_index_lst = index_lst
+ face_desc.mface = face
+ descs.append(face_desc)
- if face.materialIndex < len(materials):
- face_desc.color_index = color_index_lst[face.materialIndex]
- face_desc.texture_index = tex_index_lst[face.materialIndex]
- face_desc.material_index = mat_index_lst[face.materialIndex]
- else:
- if options.verbose >=1:
- print 'Warning: Missing material for material index. Materials will not be imported correctly. Fix by deleting abandoned material indices in Blender.'
+ #deal with subfaces
+ if subfaceok:
+ fsflevel = face.getProperty("FLT_SFLEVEL")
+ for face_desc in descs:
+ if fsflevel > subfacelevel:
+ face_desc.subface = 'Push'
+ subfacelevel = fsflevel
+ elif fsflevel < subfacelevel:
+ face_desc.subface = 'Pop'
+ subfacelevel = fsflevel
+
+
+ if uvok and (face.mode & Blender.Mesh.FaceModes.TWOSIDE):
+ face_desc.renderstyle = 1
+ for face_desc in descs:
+ if "FLT_COL" in self.exportmesh.faces.properties:
+ color_index = face.getProperty("FLT_COL")
+# if(color_index < 127):
+# color_index = 127 #sanity check for face color indices
+ if(color_index == 0):
+ color_index = 127
+ face_desc.color_index = color_index
+ else:
+ face_desc.color_index = 127
+ if "FLT_ID" in self.exportmesh.faces.properties:
+ face_desc.name = face.getProperty("FLT_ID") #need better solution than this.
+
+ self.face_lst.append(face_desc)
+ if uvok:
+ self.exportmesh.activeUVLayer = oldlayer
- self.face_lst.append(face_desc)
+ def buildTexData(self):
+
+ meshlayers = self.exportmesh.getUVLayerNames()
+ oldlayer = self.exportmesh.activeUVLayer
+ uvok = 0
+
+ if self.exportmesh.faceUV and len(meshlayers) == 1:
+ uvok = 1
+ if self.exportmesh.faceUV and tex_layers[0] in meshlayers:
+ self.exportmesh.activeUVLayer = tex_layers[0]
+ uvok = 1
+
+ if uvok:
+ #do base layer. UVs have been stored on vertices directly already.
+ for i, face in enumerate(self.face_lst):
+ if face.mface:
+ mface = face.mface
+ image = mface.image
+ if image != None and mface.mode & Blender.Mesh.FaceModes["TEX"]:
+ index = self.header.GRR.request_texture_index(image)
+ else:
+ index = -1
+ face.texture_index = index
+
+ for i, face in enumerate(self.face_lst):
+ if face.mface:
+ mface_v = face.mface.v
+ for v in mface_v:
+ face.uvlayer.append([])
- # Export double sided face as 2 faces with opposite orientations.
- if mesh_hasuv and face.mode & Blender.NMesh.FaceModes['TWOSIDE']:
- # Create vertex description list for each face. they have a face mode, so we know they have a UV too.
- vertex_lst = [VertexDesc(v.co, -v.no, face.uv[i]) for i, v in enumerate(face_v)]
- vertex_lst.reverse() # Reversing flips the face.
+ for layername in tex_layers[1:]:
+ if layername in meshlayers:
+ self.exportmesh.activeUVLayer=layername
+ for i, face in enumerate(self.face_lst):
+ if face.mface:
+
+ face.mtex.append(layername)
+ mface = face.mface
+ mface_v = mface.v
+ image = mface.image
+
+ if image != None and mface.mode & Blender.Mesh.FaceModes["TEX"]:
+ index = self.header.GRR.request_texture_index(image)
+ face.images.append(index)
+ else:
+ face.images.append(-1)
+
+ for j, v in enumerate(mface_v):
+ face.uvlayer[j].append(tuple(mface.uv[j]))
+ if uvok:
+ self.exportmesh.activeUVLayer = oldlayer
+ def blender_export(self):
+ global options
+ Node.blender_export(self)
+ if self.opcode == 111:
+ self.exportmesh = Blender.Mesh.New()
+ self.exportmesh.getFromObject(self.object.name)
+
+ for vert in self.exportmesh.verts:
+ if not options.export_transform:
+ vec = vert.co
+ vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale
+ vert.co = Blender.Mathutils.TranslationMatrix(vec) * (vert.co * self.object.getMatrix('worldspace'))
- index_lst = []
- for vert_desc in vertex_lst:
- index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
+ if options.scale != 1.0:
+ vert.co = vert.co * options.scale
+
+ if("FLT_VCOL") in self.mesh.verts.properties:
+ for v in self.exportmesh.verts:
+ self.vert_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,v,0,0,v.getProperty("FLT_VCOL")))
+ else:
+ for v in self.mesh.verts:
+ self.vert_lst.append(self.header.GRR.request_vertex_index(self.object,self.mesh,v,0,0,127))
+
+
+
+ elif self.mesh:
+ orig_mesh = self.object.getData(mesh=True)
+ self.exportmesh = Blender.Mesh.New()
+ default = None
+
+
+ if options.export_shading:
+ mods = self.object.modifiers
+ hasedsplit = False
+ for mod in mods:
+ if mod.type == Blender.Modifier.Types.EDGESPLIT:
+ hasedsplit = True
+ break
+ if not hasedsplit:
+ default = mods.append(Modifier.Types.EDGESPLIT)
+ default[Modifier.Settings.EDGESPLIT_ANGLE] = options.shading_default
+ default[Modifier.Settings.EDGESPLIT_FROM_ANGLE] = True
+ default[Modifier.Settings.EDGESPLIT_FROM_SHARP] = False
+ self.object.makeDisplayList()
+
+ self.exportmesh.getFromObject(self.object.name)
+
+ #recalculate vertex positions
+ for vert in self.exportmesh.verts:
+ if not options.export_transform:
+ vec = vert.co
+ vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale
+ vert.co = Blender.Mathutils.TranslationMatrix(vec) * (vert.co * self.object.getMatrix('worldspace'))
- face_desc = FaceDesc()
- face_desc.vertex_index_lst = index_lst
- if face.materialIndex < len(materials):
- face_desc.color_index = color_index_lst[face.materialIndex]
- face_desc.texture_index = tex_index_lst[face.materialIndex]
- face_desc.material_index = mat_index_lst[face.materialIndex]
- else:
- if options.verbose >=1:
- print 'Error: No material for material index. Delete abandoned material indices in Blender.'
-
- self.face_lst.append(face_desc)
+ if options.scale != 1.0:
+ vert.co = vert.co * options.scale
+
+ flipped = self.object.getMatrix('worldspace').determinant()
+
+ if not options.export_transform:
+ self.exportmesh.calcNormals()
+
+
+ if default:
+ #remove modifier from list
+ mods.remove(default)
+ self.object.makeDisplayList()
+
+ #build some adjacency data
+ vertuse = list()
+ wiredges = list()
+ openends = list()
+ for v in self.exportmesh.verts:
+ vertuse.append([False,0])
+
+ #build face incidence data
+ for face in self.exportmesh.faces:
+ for i, v in enumerate(face.verts):
+ vertuse[v.index][0] = True
+
+ for edge in self.exportmesh.edges: #count valance
+ vertuse[edge.v1.index][1] = vertuse[edge.v1.index][1] + 1
+ vertuse[edge.v2.index][1] = vertuse[edge.v2.index][1] + 1
+
+ #create all face types
+ self.buildVertFaces(vertuse)
+ self.buildEdgeFaces(vertuse)
+ self.buildOpenFacesNew(vertuse)
+ self.buildNormFaces()
+ self.buildTexData()
+
+ if not options.export_transform:
+ if flipped < 0:
+ for vdesc in self.header.GRR.vertex_lst:
+ vdesc.accum = 0
+ for face in self.face_lst:
+ face.vertex_index_lst.reverse()
+ for vert in face.vertex_index_lst:
+ self.header.GRR.vertex_lst[vert].accum = 1
+
+ for vdesc in self.header.GRR.vertex_lst:
+ if vdesc.accum:
+ vdesc.nx = vdesc.nx * -1
+ vdesc.ny = vdesc.ny * -1
+ vdesc.nz = vdesc.nz * -1
+
def write_faces(self):
+ sublevel = 0
for face_desc in self.face_lst:
- face_name = self.header.GRR.new_face_name()
+ if face_desc.name:
+ face_name = face_desc.name
+ else:
+ face_name = self.header.GRR.new_face_name()
+ #grab the alpha value.
+ alpha = 0
+ if face_desc.texture_index > -1:
+ try:
+ typestring = os.path.splitext(self.header.GRR.texture_lst[face_desc.texture_index].getFilename())[1]
+ if typestring == '.inta' or typestring == '.rgba':
+ alpha = 1
+ except:
+ pass
+
+ if not alpha:
+ for index in face_desc.images:
+ try:
+ typestring = os.path.splitext(self.header.GRR.texture_lst[index].getFilename())[1]
+ if typestring == '.inta' or typestring == '.rgba':
+ alpha = 1
+ except:
+ pass
+
+ if face_desc.subface:
+ if face_desc.subface == 'Push':
+ self.header.fw.write_short(19)
+ self.header.fw.write_ushort(4)
+ sublevel += 1
+ else:
+ self.header.fw.write_short(20)
+ self.header.fw.write_ushort(4)
+ sublevel -= 1
self.header.fw.write_short(5) # Face opcode
self.header.fw.write_ushort(80) # Length of record
self.header.fw.write_string(face_name, 8) # ASCII ID
self.header.fw.write_int(-1) # IR color code
- self.header.fw.write_short(0) # Relative priority
- self.header.fw.write_char(0) # Draw type
+ self.header.fw.write_short(0) # Relative priority
+ self.header.fw.write_char(face_desc.renderstyle) # Draw type
self.header.fw.write_char(0) # Draw textured white.
self.header.fw.write_ushort(0) # Color name index
self.header.fw.write_ushort(0) # Alt color name index
self.header.fw.write_char(0) # Reserved
- self.header.fw.write_char(1) # Template
+ self.header.fw.write_char(alpha) # Template
self.header.fw.write_short(-1) # Detail tex pat index
self.header.fw.write_short(face_desc.texture_index) # Tex pattern index
self.header.fw.write_short(face_desc.material_index) # material index
self.header.fw.write_short(0) # SMC code
- self.header.fw.write_short(0) # Feature code
+ self.header.fw.write_short(0) # Feature code
self.header.fw.write_int(0) # IR material code
self.header.fw.write_ushort(0) # transparency 0 = opaque
self.header.fw.write_uchar(0) # LOD generation control
self.header.fw.write_uchar(0) # line style index
- self.header.fw.write_int(0x00000000) # Flags
+ self.header.fw.write_int(0) # Flags
self.header.fw.write_uchar(2) # Light mode
+ #self.header.fw.write_uchar(3) # Light mode
+
self.header.fw.pad(7) # Reserved
- self.header.fw.write_uint(-1) # Packed color
- self.header.fw.write_uint(-1) # Packed alt color
+ self.header.fw.write_uint(0) # Packed color
+ self.header.fw.write_uint(0) # Packed alt color
self.header.fw.write_short(-1) # Tex map index
self.header.fw.write_short(0) # Reserved
self.header.fw.write_uint(face_desc.color_index) # Color index
@@ -473,7 +949,24 @@ class BlenderMesh(Node):
self.header.fw.write_short(-1) # Shader index
self.write_longid(face_name)
-
+
+
+ #Write Multitexture field if appropriate
+ mtex = len(face_desc.mtex)
+ if mtex:
+ uvmask = 0
+ for layername in face_desc.mtex:
+ mask = mtexmasks[tex_layers.index(layername)-1]
+ uvmask |= mask
+ self.header.fw.write_ushort(52) # MultiTexture Opcode
+ self.header.fw.write_ushort(8 + (mtex * 8)) # Length
+ self.header.fw.write_uint(uvmask) # UV mask
+ for i in xrange(mtex):
+ self.header.fw.write_ushort(face_desc.images[i]) # Tex pattern index
+ self.header.fw.write_ushort(0) # Tex effect
+ self.header.fw.write_ushort(0) # Tex Mapping index
+ self.header.fw.write_ushort(0) # Tex data. User defined
+
self.write_push()
# Vertex list record
@@ -484,72 +977,95 @@ class BlenderMesh(Node):
for vert_index in face_desc.vertex_index_lst:
# Offset into vertex palette
self.header.fw.write_int(vert_index*64+8)
-
+
+ #UV list record
+ if mtex:
+ #length = 8 + (numverts * multitex * 8)
+ self.header.fw.write_ushort(53) # UV List Ocode
+ self.header.fw.write_ushort(8 + (num_verts*mtex*8)) # Record Length
+ self.header.fw.write_uint(uvmask) # UV mask
+ for i, vert_index in enumerate(face_desc.vertex_index_lst):
+ for uv in face_desc.uvlayer[i]:
+ self.header.fw.write_float(uv[0]) #U coordinate
+ self.header.fw.write_float(uv[1]) #V coordinate
self.write_pop()
+ #clean up faces at the end of meshes....
+ if sublevel:
+ self.header.fw.write_short(20)
+ self.header.fw.write_ushort(4)
+
+ def write_lps(self):
+ # Vertex list record
+ self.write_push()
+ self.header.fw.write_short(72) # Vertex list opcode
+ num_verts = len(self.vert_lst)
+ self.header.fw.write_ushort(4*num_verts+4) # Length of record
+ for vert_index in self.vert_lst:
+ # Offset into vertex palette
+ self.header.fw.write_int(vert_index*64+8)
+ self.write_pop()
def write(self):
- if self.open_flight_type == 'Object':
- self.header.fw.write_short(4) # Object opcode
- self.header.fw.write_ushort(28) # Length of record
- self.header.fw.write_string(self.name, 8) # ASCII ID
- self.header.fw.pad(16)
-
- self.write_longid(self.name)
+ self.header.fw.write_short(self.opcode)
+ self.header.fw.write_ushort(recordlen[self.opcode])
+ exportdict = FLT_Records[self.opcode].copy()
+ for key in exportdict.keys():
+ if self.props.has_key(key):
+ exportdict[key] = self.props[key]
+
+ if self.opcode == 63 and options.externalspath:
+ try:
+ exportdict['3t200!filename'] = os.path.join(options.externalspath,self.object.DupGroup.name+'.flt')
+ self.header.xrefnames.append(self.object.DupGroup.name)
+ except:
+ pass
+
+ for key in records[self.opcode]:
+ (type,length,propname) = records[self.opcode][key]
+ write_prop(self.header.fw,type,exportdict[propname],length)
+
+ if self.props.has_key('comment'):
+ self.write_comment(self.props['comment'])
+ self.write_longid(self.name) #fix this!
+
+ if options.export_transform or self.opcode == 63:
+ #writing transform matrix....
self.write_matrix()
-
+
+ if self.opcode == 111:
+ self.write_lps()
+ elif self.face_lst != [] or self.children:
+ self.write_push()
if self.face_lst != []:
- self.write_push()
-
+ #self.write_push()
self.write_faces()
+ #self.write_pop()
- self.write_pop()
- else:
- self.header.fw.write_short(2) # Group opcode
- self.header.fw.write_ushort(44) # Length of record
- self.header.fw.write_string(self.name, 8) # ASCII ID
- self.header.fw.pad(32)
-
- self.write_longid(self.name)
-
- # Because a group can contain faces as well as children.
- self.write_push()
-
- self.write_faces()
-
- for child in self.children:
- child.write()
-
+ if self.children:
+ #self.write_push()
+ for child in self.children:
+ child.write()
+ #self.write_pop()
self.write_pop()
-
- def __init__(self, parent, header, object, object_lst):
- Node.__init__(self, parent, header, object, object_lst)
- self.face_lst = []
-
- if self.children:
- self.open_flight_type= 'Group'
- else: # Empty list.
- self.open_flight_type = 'Object'
-
-class BlenderEmpty(Node):
- def write(self):
- self.header.fw.write_short(2) # Group opcode
- self.header.fw.write_ushort(44) # Length of record
- self.header.fw.write_string(self.name, 8) # ASCII ID
- self.header.fw.pad(32)
-
- self.write_longid(self.name)
-
- self.write_matrix()
+ def __init__(self, parent, header, object,props,type):
+ self.opcode = type #both these next two lines need to be in the node class....
+ self.childtypes = childtypes[self.opcode]
+ Node.__init__(self, parent, header, object,props)
+ self.face_lst = []
+ self.vert_lst = [] #for light points.
+ self.mesh = None
+ self.uvlayer = 0
+ self.flipx = False
+ self.flipy = False
+ self.flipz = False
- if self.children: # != []
- self.write_push()
-
- for child in self.children:
- child.write()
- self.write_pop()
+ if self.object.type == 'Mesh':
+ self.mesh = self.object.getData(mesh=True)
+ if(self.mesh.faceUV):
+ self.uvLayer = len(self.mesh.getUVLayerNames())
class Database(Node):
def write_header(self):
@@ -568,8 +1084,19 @@ class Database(Node):
self.fw.write_int(0) # projection type, 0 = flat earth
self.fw.pad(30)
self.fw.write_short(1) # double precision
- self.fw.pad(140)
+ self.fw.write_int(100) # database origin type
+ self.fw.pad(88)
+ try:
+ self.fw.write_double(self.header.scene.properties['FLT']['origin lat']) #database origin lattitude
+ except:
+ self.fw.write_double(0)
+ try:
+ self.fw.write_double(self.header.scene.properties['FLT']['origin lon']) #database origin longitude
+ except:
+ self.fw.write_double(0)
+ self.fw.pad(32)
self.fw.write_int(0) # ellipsoid model, 0 = WSG 1984
+
self.fw.pad(52)
def write_vert_pal(self):
@@ -579,14 +1106,13 @@ class Database(Node):
self.fw.write_short(67) # Vertex palette opcode.
self.fw.write_short(8) # Length of record
self.fw.write_int(self.GRR.vertex_count() * 64 + 8) # Length of everything.
-
# Write records for individual vertices.
for i in xrange(self.GRR.vertex_count()):
desc = self.GRR.request_vertex_desc(i)
self.fw.write_short(70) # Vertex with color normal and uv opcode.
self.fw.write_ushort(64) # Length of record
- self.fw.write_ushort(0) # Color name index
- self.fw.write_short(0x2000) # Flags set to no color
+ self.fw.write_ushort(0) # Color name index
+ self.fw.write_short(0x20000000) # Flags
self.fw.write_double(desc.x)
self.fw.write_double(desc.y)
self.fw.write_double(desc.z)
@@ -595,16 +1121,19 @@ class Database(Node):
self.fw.write_float(desc.nz)
self.fw.write_float(desc.u)
self.fw.write_float(desc.v)
- self.fw.pad(12)
+ self.fw.pad(4)
+ self.fw.write_uint(desc.cindex)
+ self.fw.pad(4)
def write_tex_pal(self):
if options.verbose >= 2:
print 'Writing texture palette.'
# Write record for texture palette
- for i in xrange(self.GRR.texture_count()):
+ for i, img in enumerate(self.GRR.texture_lst):
+ filename = tex_files[img.name]
self.fw.write_short(64) # Texture palette opcode.
self.fw.write_short(216) # Length of record
- self.fw.write_string(self.GRR.request_texture_filename(i), 200) # Filename
+ self.fw.write_string(filename, 200) # Filename
self.fw.write_int(i) # Texture index
self.fw.write_int(0) # X
self.fw.write_int(0) # Y
@@ -641,13 +1170,17 @@ class Database(Node):
self.fw.write_short(32) # Color palette opcode.
self.fw.write_short(4228) # Length of record
self.fw.pad(128)
- count = self.GRR.color_count()
+ try:
+ cpalette = self.scene.properties['FLT']['Color Palette']
+ except:
+ cpalette = defaultp.pal
+ count = len(cpalette)
for i in xrange(count):
- col = self.GRR.request_max_color(i)
- self.fw.write_uchar(255) # alpha
- self.fw.write_uchar(col[2]) # b
- self.fw.write_uchar(col[1]) # g
- self.fw.write_uchar(col[0]) # r
+ color = struct.unpack('>BBBB',struct.pack('>I',cpalette[i]))
+ self.fw.write_uchar(color[3]) # alpha
+ self.fw.write_uchar(color[2]) # b
+ self.fw.write_uchar(color[1]) # g
+ self.fw.write_uchar(color[0]) # r
self.fw.pad(max(4096-count*4, 0))
def write(self):
@@ -657,66 +1190,428 @@ class Database(Node):
self.write_mat_pal()
self.write_col_pal()
- # Wrap everything in a group if it has an object child.
- if self.has_object_child:
- self.header.fw.write_short(2) # Group opcode
- self.header.fw.write_ushort(44) # Length of record
- self.header.fw.write_string('g1', 8) # ASCII ID
- self.header.fw.pad(32)
-
self.write_push()
-
- for child in self.children:
- child.write()
-
+
+ if options.flattenmesh:
+ self.mnodes.reverse()
+ for mnode in self.mnodes:
+ mnode.write_faces()
+ else:
+ for child in self.children:
+ child.write()
self.write_pop()
+
+ def export_textures(self,texturepath):
+ for i in xrange(self.GRR.texture_count()):
+ texture = self.GRR.texture_lst[i]
+
+ if options.copy_textures:
+ filename = os.path.normpath(os.path.join(options.texturespath, os.path.basename(self.GRR.request_texture_filename(i))))
+ else:
+ filename = os.path.normpath(self.GRR.request_texture_filename(i))
+
+ tex_files[texture.name] = filename
+ def blender_export(self):
+ Node.blender_export(self)
+ self.export_textures(self)
+ return self.xrefnames
def __init__(self, scene, fw):
self.fw = fw
+ self.opcode = 1
+ self.childtypes = [73,14,2,63]
self.scene = scene
- self.all_objects = list(scene.objects)
- self.GRR = GlobalResourceRepository()
+ self.childhash = dict()
+ self.parenthash = dict()
+ self.child_objects = list()
+ self.mnodes = list()
+ self.xrefnames = list()
+ for i in self.scene.objects:
+ self.parenthash[i.name] = list()
+ self.childhash[i.name] = False
+ for i in self.scene.objects:
+ if i.parent:
+ self.childhash[i.parent.name] = True
+ self.parenthash[i.parent.name].append(i)
+ else:
+ self.child_objects.append(i)
- Node.__init__(self, None, self, None, self.all_objects)
+ self.GRR = GlobalResourceRepository()
+ Node.__init__(self, None, self, None,None)
-def fs_callback(filename):
- Blender.Window.WaitCursor(True)
-
- if Blender.sys.exists(filename):
- r = Blender.Draw.PupMenu('Overwrite ' + filename + '?%t|Yes|No')
- if r != 1:
- if options.verbose >= 1:
- print 'Export cancelled.'
- return
-
- time1 = Blender.sys.time() # Start timing
+def write_attribute_files():
+ for imgname in tex_files:
+ blentex = Blender.Image.Get(imgname)
+ exportdict = FLT_Records['Image'].copy()
+
+ if blentex.properties.has_key('FLT'):
+ for key in exportdict.keys():
+ if blentex.properties.has_key(key):
+ exportdict[key] = blentex.properties['FLT'][key]
+
+ # ClampX/Y override
+ if blentex.clampX:
+ exportdict['11i!WrapU'] = 1
+ if blentex.clampY:
+ exportdict['12i!WrapV'] = 1
+
+ exportdict['16i!Enviorment'] = 0
+
+ # File type
+ typecode = 0
+ try:
+ typestring = os.path.splitext(blentex.getFilename())[1]
+
+ if typestring == '.rgba':
+ typecode = 5
+ elif typestring == '.rgb':
+ typecode = 4
+ elif typestring == '.inta':
+ typecode = 3
+ elif typestring == '.int':
+ typecode = 2
+ except:
+ pass
+
+ exportdict['7i!File Format'] = typecode
+
+ fw = FltOut(tex_files[imgname] + '.attr')
+ size = blentex.getSize()
+ fw.write_int(size[0])
+ fw.write_int(size[1])
+ for key in records['Image']:
+ (type,length,propname) = records['Image'][key]
+ write_prop(fw,type,exportdict[propname],length)
+ fw.close_file()
+
+#globals used by the scene export function
+exportlevel = None
+xrefsdone = None
+
+def dbexport_internal(scene):
+ global exportlevel
+ global xrefsdone
+ global options
+
+ if exportlevel == 0 or not options.externalspath:
+ fname = os.path.join(options.basepath,scene.name + '.flt')
+ else:
+ fname = os.path.join(options.externalspath,scene.name + '.flt')
- fw = FltOut(filename)
-
- db = Database(Blender.Scene.GetCurrent(), fw)
+ fw = FltOut(fname)
+ db = Database(scene,fw)
if options.verbose >= 1:
- print 'Pass 1: Exporting from Blender.\n'
-
- db.blender_export()
+ print 'Pass 1: Exporting ', scene.name,'.flt from Blender.\n'
+ xreflist = db.blender_export()
if options.verbose >= 1:
- print 'Pass 2: Writing %s\n' % filename
-
+ print 'Pass 2: Writing %s\n' % fname
db.write()
-
fw.close_file()
+
+ if options.doxrefs:
+ for xname in xreflist:
+ try:
+ xrefscene = Blender.Scene.Get(xname)
+ except:
+ xrefscene = None
+ if xrefscene and xname not in xrefsdone:
+ xrefsdone.append(xname)
+ exportlevel+=1
+ dbexport_internal(xrefscene)
+ exportlevel-=1
+ return fname
+#main database export function
+def dbexport():
+ global exportlevel
+ global xrefsdone
+ exportlevel = 0
+ xrefsdone = list()
+
+ Blender.Window.WaitCursor(True)
+ time1 = Blender.sys.time() # Start timing
+
if options.verbose >= 1:
+ print '\nOpenFlight Exporter'
+ print 'Version:', __version__
+ print 'Author: Greg MacDonald, Geoffrey Bantle'
+ print __url__[2]
+ print
+
+ fname = dbexport_internal(Blender.Scene.GetCurrent())
+ if options.verbose >=1:
print 'Done in %.4f sec.\n' % (Blender.sys.time() - time1)
-
Blender.Window.WaitCursor(False)
+
+ #optional: Copy textures
+ if options.copy_textures:
+ for imgname in tex_files:
+ #Check to see if texture exists in target directory
+ if not os.path.exists(tex_files[imgname]):
+ #Get original Blender file name
+ origpath = Blender.sys.expandpath(Blender.Image.Get(imgname).getFilename())
+ #copy original to new
+ shutil.copyfile(origpath,tex_files[imgname])
+
+ #optional: Write attribute files
+ if options.write_attrib_files:
+ write_attribute_files()
+
+ if options.xapp:
+ cmd= options.xappath + " " + fname
+ status = os.system(cmd)
+
+
+#Begin UI code
+FLTExport = None
+FLTClose = None
+FLTLabel = None
+
+FLTBaseLabel = None
+FLTTextureLabel = None
+FLTXRefLabel = None
+
+FLTBaseString = None
+FLTTextureString = None
+FLTXRefString = None
+
+FLTBasePath = None
+FLTTexturePath = None
+FLTXRefPath = None
+
+FLTShadeExport = None
+FLTShadeDefault = None
+
+FLTCopyTex = None
+FLTDoXRef = None
+FLTGlobal = None
+
+FLTScale = None
+
+FLTXAPP = None
+FLTXAPPath = None
+FLTXAPPString = None
+FLTXAPPLabel = None
+FLTXAPPChooser = None
+
+FLTAttrib = None
+
+def setshadingangle(ID,val):
+ global options
+ options.shading_default = val
+def setBpath(fname):
+ global options
+ options.basepath = os.path.dirname(fname)
+ #update xref and textures path too....
+ if(os.path.exists(os.path.join(options.basepath,'externals'))):
+ options.externalspath = os.path.join(options.basepath,'externals')
+ if(os.path.exists(os.path.join(options.texturespath,'textures'))):
+ options.texturespath = os.path.join(options.basepath,'textures')
+def setexportscale(ID,val):
+ global options
+ options.scale = val
+
+def setTpath(fname):
+ global options
+ options.texturespath = os.path.dirname(fname)
+def setXpath(fname):
+ global options
+ options.externalspath = os.path.dirname(fname)
+def setXApath(fname):
+ global options
+ options.xappath = fname
+ d = dict()
+ d['xappath'] = options.xappath
+ Blender.Registry.SetKey('flt_export', d, 1)
+def event(evt, val):
+ x = 1
+def but_event(evt):
+ global options
+
+ global FLTExport
+ global FLTClose
+ global FLTLabel
+
+ global FLTBaseLabel
+ global FLTTextureLabel
+ global FLTXRefLabel
+
+ global FLTBaseString
+ global FLTTextureString
+ global FLTXRefString
+
+ global FLTBasePath
+ global FLTTexturePath
+ global FLTXRefPath
+
+ global FLTShadeExport
+ global FLTShadeDefault
+
+ global FLTCopyTex
+ global FLTDoXRef
+ global FLTGlobal
+
+ global FLTScale
+
+
+ global FLTXAPP
+ global FLTXAPPath
+ global FLTXAPPString
+ global FLTXAPPLabel
+ global FLTXAPPChooser
+
+ global FLTAttrib
+
+
+
+ #choose base path for export
+ if evt == 4:
+ Blender.Window.FileSelector(setBpath, "DB Root", options.basepath)
+
+ #choose XREF path
+ if evt == 6:
+ Blender.Window.FileSelector(setXpath,"DB Externals",options.externalspath)
+
+ #choose texture path
+ if evt == 8:
+ Blender.Window.FileSelector(setTpath,"DB Textures",options.texturespath)
+
+ #export shading toggle
+ if evt == 9:
+ options.export_shading = FLTShadeExport.val
+ #export Textures
+ if evt == 11:
+ options.copy_textures = FLTCopyTex.val
+ #export XRefs
+ if evt == 13:
+ options.doxrefs = FLTDoXRef.val
+ #export Transforms
+ if evt == 12:
+ options.export_transform = FLTGlobal.val
+
+ if evt == 14:
+ options.xapp = FLTXAPP.val
+ if evt == 16:
+ Blender.Window.FileSelector(setXApath,"External Application",options.xappath)
+ if evt == 20:
+ options.write_attrib_files = FLTAttrib.val
+
+ #Export DB
+ if evt == 1:
+ dbexport()
+
+ #exit
+ if evt == 2:
+ Draw.Exit()
+
+from Blender.BGL import *
+from Blender import Draw
+def gui():
+
+ global options
+
+ global FLTExport
+ global FLTClose
+ global FLTLabel
+
+ global FLTBaseLabel
+ global FLTTextureLabel
+ global FLTXRefLabel
+
+ global FLTBaseString
+ global FLTTextureString
+ global FLTXRefString
+
+ global FLTBasePath
+ global FLTTexturePath
+ global FLTXRefPath
+
+ global FLTShadeExport
+ global FLTShadeDefault
+
+ global FLTCopyTex
+ global FLTDoXRef
+ global FLTGlobal
+
+ global FLTScale
+
+ global FLTXAPP
+ global FLTXAPPath
+ global FLTXAPPString
+ global FLTXAPPLabel
+ global FLTXAPPChooser
+
+ global FLTAttrib
+
+ glClearColor(0.880,0.890,0.730,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]
+ #draw from top to bottom....
+ cx = 50
+ #Draw Title Bar...
+ #glRasterPos2d(cx, curRect[3]-100)
+ #FLTLabel = Draw.Text("FLT Exporter V2.0",'large')
+ cy = height - 80
+
+ #base path
+ FLTBaseLabel = Draw.Label("Base Path:",cx,cy,100,20)
+ FLTBaseString = Draw.String("",3,cx+100,cy,300,20,options.basepath,255,"Folder to export to")
+ FLTBaseChooser = Draw.PushButton("...",4,cx+400,cy,20,20,"Choose Folder")
+
+ cy = cy-40
+
+ #externals path
+ FLTXRefLabel = Draw.Label("XRefs:",cx,cy,100,20)
+ FLTXRefString = Draw.String("",5,cx+100,cy,300,20,options.externalspath,255,"Folder for external references")
+ FLTXRefChooser = Draw.PushButton("...",6,cx+400,cy,20,20,"Choose Folder")
+ cy = cy-40
+ #Textures path
+ FLTTextureLabel = Draw.Label("Textures:",cx,cy,100,20)
+ FLTTextureString = Draw.String("",7,cx+100,cy,300,20,options.texturespath,255,"Folder for texture files")
+ FLTTextureChooser = Draw.PushButton("...",8,cx+400,cy,20,20,"Choose Folder")
+ cy=cy-40
+ #External application path
+ FLTXAPPLabel = Draw.Label("XApp:",cx,cy,100,20)
+ FLTXAPPString = Draw.String("",15,cx+100,cy,300,20,options.xappath,255,"External application to launch when done")
+ FLTXAPPChooser = Draw.PushButton("...",16,cx+400, cy,20,20,"Choose Folder")
+
+ cy = cy-60
+ #Shading Options
+ FLTShadeExport = Draw.Toggle("Default Shading",9,cx,cy,100,20,options.export_shading,"Turn on export of custom shading")
+ FLTShadDefault = Draw.Number("",10,cx + 120,cy,100,20,options.shading_default,0.0,180.0,"Default shading angle for objects with no custom shading assigned",setshadingangle)
+
+ cy = cy-40
+ FLTScale = Draw.Number("Export Scale",14,cx,cy,220,20,options.scale,0.0,100.0,"Export scaling factor",setexportscale)
+
+ cy = cy-40
+ #misc Options
+ FLTCopyTex = Draw.Toggle("Copy Textures",11,cx,cy,220,20,options.copy_textures,"Copy textures to folder indicated above")
+ cy = cy-40
+ FLTGlobal = Draw.Toggle("Export Transforms",12,cx,cy,220,20,options.export_transform,"If unchecked, Global coordinates are used (recommended)")
+ cy = cy-40
+ FLTDoXRef = Draw.Toggle("Export XRefs", 13,cx,cy,220,20,options.doxrefs,"Export External references (only those below current scene!)")
+ cy = cy-40
+ FLTXAPP = Draw.Toggle("Launch External App", 14, cx,cy,220,20,options.xapp,"Launch External Application on export")
+ cy = cy-40
+ FLTAttrib = Draw.Toggle("Write Attribute Files", 20, cx, cy, 220,20,options.write_attrib_files, "Write Texture Attribute files")
+ #FLTXAPPATH = Draw.String("",15,cx,cy,300,20,options.xappath,255,"External application path")
+
-if options.verbose >= 1:
- print '\nOpenFlight Exporter'
- print 'Version:', __version__
- print 'Author: Greg MacDonald'
- print __url__[2]
- print
+ #Draw export/close buttons
+ FLTExport = Draw.PushButton("Export",1,cx,20,100,20,"Export to FLT")
+ FLTClose = Draw.PushButton("Close", 2, cx+120,20,100,20,"Close window")
-fname = Blender.sys.makename(ext=".flt")
-Blender.Window.FileSelector(fs_callback, "Export OpenFlight v16.0", fname)
+
+Draw.Register(gui,event,but_event) \ No newline at end of file
diff --git a/release/scripts/flt_filewalker.py b/release/scripts/flt_filewalker.py
index 442c9728e91..4a9b86c45d2 100644
--- a/release/scripts/flt_filewalker.py
+++ b/release/scripts/flt_filewalker.py
@@ -17,6 +17,11 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+__bpydoc__ ="""\
+File read/write module used by OpenFlight I/O and tool scripts. OpenFlight is a
+registered trademark of MultiGen-Paradigm, Inc.
+"""
+
import Blender
from struct import *
import re
@@ -199,7 +204,9 @@ class FltOut:
self.file.close()
def __init__(self, filename):
- self.file = open(filename, 'wb')
+ self.file = open(filename, 'wb')
+ self.filename = filename
+
class FileFinder:
def add_file_to_search_path(self, filename):
diff --git a/release/scripts/flt_import.py b/release/scripts/flt_import.py
index ca0db650447..220fc9f355c 100644
--- a/release/scripts/flt_import.py
+++ b/release/scripts/flt_import.py
@@ -1,72 +1,26 @@
#!BPY
""" Registration info for Blender menus:
Name: 'OpenFlight (.flt)...'
-Blender: 238
+Blender: 245
Group: 'Import'
Tip: 'Import OpenFlight (.flt)'
"""
-__author__ = "Greg MacDonald, Campbell Barton"
-__version__ = "1.2 10/20/05"
+__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.
-Run from "File->Import" menu.
-
-Options are available from Blender's "Scripts Config Editor," accessible through
-the "Scripts->System" menu from the scripts window.
-
-All global_prefs are toggle switches that let the user choose what is imported. Most
-are straight-forward, but one option could be a source of confusion. The
-"Diffuse Color From Face" option when set pulls the diffuse color from the face
-colors. Otherwise the diffuse color comes from the material. What may be
-confusing is that this global_prefs only works if the "Diffuse Color" option is set.
-
-New Features:<br>
-* Importer is 14 times faster.<br>
-* External triangle module is no longer required, but make sure the importer
-has a 3d View screen open while its running or triangulation won't work.<br>
-* Should be able to import all versions of flight files.
-
-Features:<br>
-* Heirarchy retained.<br>
-* First texture imported.<br>
-* Colors imported from face or material.<br>
-* LOD seperated out into different layers.<br>
-* Asks for location of unfound textures or external references.<br>
-* Searches Blender's texture directory in the user preferences panel.<br>
-* Triangles with more than 4 verts are triangulated if the Triangle python
-module is installed.<br>
-* Matrix transforms imported.<br>
-* External references to whole files are imported.
-
-Things To Be Aware Of:<br>
-* Each new color and face attribute creates a new material and there are only a maximum of 16
-materials per object.<br>
-* For triangulated faces, normals must be recomputed outward manually by typing
-CTRL+N in edit mode.<br>
-* You can change global_prefs only after an initial import.<br>
-* External references are imported as geometry and will be exported that way.<br>
-* A work around for not using the Triangle python module is to simply to
-triangulate in Creator before importing. This is only necessary if your
-model contains 5 or more vertices.<br>
-* You have to manually blend the material color with the texture color.
-
-What's Not Handled:<br>
-* Special texture repeating modes.<br>
-* Replications and instancing.<br>
-* Comment and attribute fields.<br>
-* Light points.<br>
-* Animations.<br>
-* External references to a node within a file.<br>
-* Multitexturing.<br>
-* Vetex colors.<br>
+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
+# 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
@@ -87,15 +41,33 @@ import os
import BPyMesh
import BPyImage
import flt_filewalker
+import flt_properties
+reload(flt_properties)
+from flt_properties import *
-Vector= Blender.Mathutils.Vector
+#Globals. Should Clean these up and minimize their usage.
-def col_to_gray(c):
- return 0.3*c[0] + 0.59*c[1] + 0.11*c[2]
+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']= 1
+global_prefs['verbose']= 4
global_prefs['get_texture'] = True
global_prefs['get_diffuse'] = True
global_prefs['get_specular'] = False
@@ -105,8 +77,41 @@ 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
+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, 100, 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.
@@ -185,16 +190,14 @@ class VertexDesc:
self.y = 0.0
self.z = 0.0
- ''' # IGNORE_NORMALS
+
self.nx = 0.0
- self.ny = 1.0
+ self.ny = 0.0
self.nz = 0.0
- '''
+
self.uv= Vector(0,0)
- self.r = 1.0
- self.g = 1.0
- self.b = 1.0
- self.a = 1.0
+ self.cindex = 127 #default/lowest
+ self.cnorm = False
class LightPointAppDesc:
def make_key(self):
@@ -222,7 +225,7 @@ class LightPointAppDesc:
self.props.update({'LOD scale': 0.0})
class GlobalResourceRepository:
- def request_lightpoint_app(self, desc):
+ def request_lightpoint_app(self, desc, scene):
match = self.light_point_app.get(desc.make_key())
if match:
@@ -231,7 +234,7 @@ class GlobalResourceRepository:
# Create empty and fill with properties.
name = desc.props['type'] + ': ' + desc.props['id']
object = Blender.Object.New('Empty', name)
- scene.link(object)
+ scene.objects.link(object)
object.Layers= current_layer
object.sel= 1
@@ -306,6 +309,9 @@ class GlobalResourceRepository:
return tex
def __init__(self):
+
+ #list of scenes xrefs belong to.
+ self.xrefs = dict()
# material
self.mat_dict = dict()
mat_lst = Blender.Material.Get()
@@ -341,108 +347,6 @@ class GlobalResourceRepository:
# light point
self.light_point_app = dict()
-# Globals
-GRR = GlobalResourceRepository()
-FF = flt_filewalker.FileFinder()
-scene = Blender.Scene.GetCurrent() # just hope they dont chenge scenes once the file selector pops up.
-current_layer = 0x01
-
-
-# Opcodes that indicate its time to return control to parent.
-throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63]
-do_not_report_opcodes = [76, 78, 79, 80, 81, 82, 94, 83, 33, 112, 100, 101, 102, 97, 31, 103, 104, 117, 118, 120, 121, 124, 125]
-
-opcode_name = { 0: 'db',
- 1: 'head',
- 2: 'grp',
- 4: 'obj',
- 5: 'face',
- 10: 'push',
- 11: 'pop',
- 14: 'dof',
- 19: 'push sub',
- 20: 'pop sub',
- 21: 'push ext',
- 22: 'pop ext',
- 23: 'cont',
- 31: 'comment',
- 32: 'color pal',
- 33: 'long id',
- 49: 'matrix',
- 50: 'vector',
- 52: 'multi-tex',
- 53: 'uv lst',
- 55: 'bsp',
- 60: 'rep',
- 61: 'inst ref',
- 62: 'inst def',
- 63: 'ext ref',
- 64: 'tex pal',
- 67: 'vert pal',
- 68: 'vert w col',
- 69: 'vert w col & norm',
- 70: 'vert w col, norm & uv',
- 71: 'vert w col & uv',
- 72: 'vert lst',
- 73: 'lod',
- 74: 'bndin box',
- 76: 'rot edge',
- 78: 'trans',
- 79: 'scl',
- 80: 'rot pnt',
- 81: 'rot and/or scale pnt',
- 82: 'put',
- 83: 'eyepoint & trackplane pal',
- 84: 'mesh',
- 85: 'local vert pool',
- 86: 'mesh prim',
- 87: 'road seg',
- 88: 'road zone',
- 89: 'morph vert lst',
- 90: 'link pal',
- 91: 'snd',
- 92: 'rd path',
- 93: 'snd pal',
- 94: 'gen matrix',
- 95: 'txt',
- 96: 'sw',
- 97: 'line styl pal',
- 98: 'clip reg',
- 100: 'ext',
- 101: 'light src',
- 102: 'light src pal',
- 103: 'reserved',
- 104: 'reserved',
- 105: 'bndin sph',
- 106: 'bndin cyl',
- 107: 'bndin hull',
- 108: 'bndin vol cntr',
- 109: 'bndin vol orient',
- 110: 'rsrvd',
- 111: 'light pnt',
- 112: 'tex map pal',
- 113: 'mat pal',
- 114: 'name tab',
- 115: 'cat',
- 116: 'cat dat',
- 117: 'rsrvd',
- 118: 'rsrvd',
- 119: 'bounding hist',
- 120: 'rsrvd',
- 121: 'rsrvd',
- 122: 'push attrib',
- 123: 'pop attrib',
- 124: 'rsrvd',
- 125: 'rsrvd',
- 126: 'curv',
- 127: 'road const',
- 128: 'light pnt appear pal',
- 129: 'light pnt anim pal',
- 130: 'indexed lp',
- 131: 'lp sys',
- 132: 'indx str',
- 133: 'shdr pal'}
-
class Handler:
def in_throw_back_lst(self, opcode):
return opcode in self.throw_back_lst
@@ -487,11 +391,11 @@ class Node:
print '-', self.props['comment'],
print
-
+
for child in self.children:
child.blender_import()
-
- # Import comment.
+
+# Import comment.
# if self.props['comment'] != '':
# name = 'COMMENT: ' + self.props['id']
# t = Blender.Text.New(name)
@@ -568,8 +472,8 @@ class Node:
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 opcode_name[opcode], 'not handled'
+ 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
@@ -581,7 +485,19 @@ class Node:
def parse_comment(self):
self.props['comment'] = self.header.fw.read_string(self.header.fw.get_length()-4)
return True
-
+
+ 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()
@@ -647,20 +563,16 @@ class VertexPalette(Node):
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)
-
- color_index = self.header.fw.read_uint()
- v.r, v.g, v.b, v.a= self.header.get_color(color_index)
-
+ #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):
@@ -672,16 +584,10 @@ class VertexPalette(Node):
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()
- '''
- # Just to advance
- self.header.fw.read_float()
- self.header.fw.read_float()
- self.header.fw.read_float()
self.parse_vertex_post_common(v)
@@ -698,15 +604,10 @@ class VertexPalette(Node):
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()
- '''
- # Just to advance
- self.header.fw.read_float()
- self.header.fw.read_float()
- self.header.fw.read_float()
v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
@@ -721,89 +622,370 @@ class InterNode(Node):
def __init__(self):
self.object = None
self.mesh = None
- self.isMesh = False
+ self.hasMesh = False
self.faceLs= []
self.matrix = None
-
- def blender_import_my_faces(self):
+ self.vis = True
+ self.hasmtex = False
+ self.uvlayers = dict()
+ self.blayernames = dict()
+ self.subfacelevel = 0
+
+ mask = 2147483648
+ for i in xrange(7):
+ self.uvlayers[mask] = False
+ mask = mask / 2
+
+ def blender_import_my_faces(self):
+
# Add the verts onto the mesh
- mesh = self.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]
-
- mesh.verts.extend([blender_verts[i] for i in vert_list])
-
+ 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:
- material_index= flt_face.blen_mat_idx
- image= flt_face.blen_image
-
+ 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 <=4: # tri or quad
+ 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((material_index, image, uvs))
+ 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(mesh, mesh_face_indicies)
+ 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( [ (material_index, image, (uvs[tri[0]], uvs[tri[1]], uvs[tri[2]]) ) 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
-
- mesh.faces.extend(new_faces)
-
- try: mesh.faceUV= True
- except: pass
-
- for i, f in enumerate(mesh.faces):
- f.mat, f.image, f.uv= new_faces_props[i]
-
+ 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):
+ f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"] #fix this!
+ f.mode |= Blender.Mesh.FaceModes["LIGHT"]
+ props = new_faces_props[i]
+ #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):
+ 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.verts.delete(0) # remove the dummy vert
+ self.mesh.sel= 1
+ self.header.scene.update(1) #slow!
+ self.mesh.remDoubles(0.0001)
+
+ 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):
-# name = self.props['type'] + ': ' + self.props['id']
+ if self.vis and self.parent:
+ self.vis = self.parent.vis
name = self.props['id']
- if self.isMesh:
- self.object = Blender.Object.New('Mesh', name)
- #self.mesh = self.object.getData()
+
+ if self.hasMesh:
self.mesh = Blender.Mesh.New()
- self.mesh.verts.extend( Vector() ) # DUMMYVERT
- self.object.link(self.mesh)
+ 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 = Blender.Object.New('Empty', name)
+ self.object = self.header.scene.objects.new('Empty')
- if self.parent:
- self.parent.object.makeParent([self.object])
+ self.object.name = name
+ self.header.group.objects.link(self.object)
- scene.link(self.object)
- self.object.Layer = current_layer
- self.object.sel = 1
+ #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.parent and self.parent.object and (self.header.scene == self.parent.header.scene):
+ self.parent.object.makeParent([self.object])
+
+ 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:
+ 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
+
+ if self.matrix:
+ self.object.setMatrix(self.matrix)
+
Node.blender_import(self) # Attach faces to self.faceLs
- if self.isMesh:
+ if self.hasMesh:
# Add all my faces into the mesh at once
self.blender_import_my_faces()
-
- if self.matrix:
- self.object.setMatrix(self.matrix)
-
- # Attach properties
- #for name, value in self.props.items():
- # self.object.addProperty(name, value)
-
+
def parse_face(self):
- child = Face(self)
+ child = Face(self, self.subfacelevel)
child.parse()
return True
@@ -838,6 +1020,11 @@ class InterNode(Node):
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()
@@ -857,32 +1044,42 @@ class InterNode(Node):
m[i].append(f)
self.matrix = Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3])
-EDGE_FGON= Blender.Mesh.EdgeFlags['FGON']
-FACE_TEX= Blender.Mesh.FaceModes['TEX']
+ 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):
+ def __init__(self, parent,subfacelevel):
Node.__init__(self, parent, parent.header)
self.root_handler.set_handler({31: self.parse_comment,
- 10: self.parse_push})
+ 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})
+ 11: self.parse_pop,
+ 53: self.parse_uvlist})
if parent:
- parent.isMesh = True
+ parent.hasMesh = True
- self.indices = list() # face verts here
+ 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.fromkeys(['ir color', 'priority',
- 'draw type', 'texture white', 'template billboard',
- 'smc', 'fid', 'ir material', 'lod generation control',
- 'flags', 'light mode'])
-
- self.header.fw.read_ahead(8) # face id
+ 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()
@@ -919,186 +1116,14 @@ class Face(Node):
self.alt_color_index = self.header.fw.read_uint()
#self.header.fw.read_ahead(2)
#self.shader_index = self.header.fw.read_short()
-
-
- """
- def blender_import_face(self, material_index, image):
-
-
- mesh = self.parent.mesh
- face_len= len(self.indices)
-
- mesh_vert_len_orig= len(mesh.verts)
- mesh.verts.extend([ self.header.vert_pal.blender_verts[i] for i in self.indices])
-
- # Exception for an edge
- if face_len==2:
- mesh.edges.extend((mesh.verts[-1], mesh.verts[-2]))
- return
-
-
- mesh_face_indicies = range(mesh_vert_len_orig, mesh_vert_len_orig+face_len)
-
- #print mesh_face_indicies , 'mesh_face_indicies '
-
- # First we need to triangulate NGONS
- if face_len>4:
- tri_indicies = [[i+mesh_vert_len_orig for i in t] for t in BPyMesh.ngon(mesh, mesh_face_indicies) ] # use range because the verts are in order.
- else:
- tri_indicies= [mesh_face_indicies] # can be a quad but thats ok
-
- # Extend face or ngon
-
- mesh.faces.extend(tri_indicies)
- #print mesh.faces, 'mesh.faces'
- mesh.faceUV= True
-
- # Now set UVs
- for i in xrange(len(mesh.faces)-len(tri_indicies), len(mesh.faces)):
- f= mesh.faces[i]
- f_v= f.v
- for j, uv in enumerate(f.uv):
- vertex_index_flt= self.indices[f_v[j].index - mesh_vert_len_orig]
-
- vert_desc = self.header.vert_pal.vert_desc_lst[vertex_index_flt]
- uv.x, uv.y= vert_desc.u, vert_desc.v
-
- # Only a bug in 2.42, fixed in cvs
- for c in f.col:
- c.r=c.g=c.b= 255
-
- f.mat = material_index
- if image:
- f.image = image
- else:
- f.mode &= ~FACE_TEX
-
- # FGon
-
- if face_len>4:
- # Add edges we know are not fgon
- end_index= len(mesh.verts)
- start_index= end_index - len(self.indices)
- edge_dict= dict([ ((i, i+1), None) for i in xrange(start_index, end_index-1)])
- edge_dict[(start_index, end_index)]= None # wish this was a set
-
- fgon_edges= {}
- for tri in tri_indicies:
- for i in (0,1,2):
- i1= tri[i]
- i2= tri[i-1]
-
- # Sort
- if i1>i2:
- i1,i2= i2,i1
-
- if not edge_dict.has_key( (i1,i2) ): # if this works its an edge vert
- fgon_edges[i1,i2]= None
-
-
- # Now set fgon flags
- for ed in mesh.edges:
- i1= ed.v1.index
- i2= ed.v2.index
- if i1>i2:
- i1,i2= i2,i1
-
- if fgon_edges.has_key( (i1,i2) ):
- # This is an edge tagged for fgonning?
- fgon_edges[i1, i2]
- ed.flag |= EDGE_FGON
- del fgon_edges[i1, i2] # make later searches faster?
-
- if not fgon_edges:
- break
- """
-
+
def parse_comment(self):
self.comment = self.header.fw.read_string(self.header.fw.get_length()-4)
return True
- # returns a tuple (material, image) where material is the blender material and
- # image is the blender image or None.
- def create_blender_material(self):
- # Create face material.
- mat_desc = MaterialDesc()
-
- if self.mat_index != -1:
- if not self.mat_index in self.header.mat_desc_pal:
- if global_prefs['verbose'] >= 1:
- #print 'Warning: Material index', self.mat_index, 'not in material palette.'
- pass
- else:
- mat_pal_desc = self.header.mat_desc_pal[self.mat_index]
- mat_desc.alpha = mat_pal_desc.alpha * self.alpha # combine face and mat alphas
- mat_desc.ambient = mat_pal_desc.ambient
- mat_desc.diffuse = mat_pal_desc.diffuse
- mat_desc.specular = mat_pal_desc.specular
- mat_desc.emissive = mat_pal_desc.emissive
- mat_desc.shininess = mat_pal_desc.shininess
- else:
- # if no material get alpha from just face.
- mat_desc.alpha = self.alpha
-
- # Color.
- if global_prefs['color_from_face']:
- color = None
- if not self.props['flags'] & 0x40000000:
- if self.props['flags'] & 0x10000000: # packed color
- color = self.packed_color
- else:
- color = self.header.get_color(self.color_index)
-
- if color:
- r = float(color[0])/255.0
- g = float(color[1])/255.0
- b = float(color[2])/255.0
- mat_desc.diffuse = [r, g, b]
-
- # Texture
- image = None
- if self.tex_index != -1 and self.tex_index in self.header.bl_tex_pal:
- mat_desc.tex0 = self.header.bl_tex_pal[self.tex_index]
- if mat_desc.tex0:
- mat_desc.name = FF.strip_path(self.header.tex_pal[self.tex_index])
- image = mat_desc.tex0.image
-
- # OpenFlight Face Attributes
- mat_desc.face_props = self.props
-
- # Get material.
- mat = GRR.request_mat(mat_desc)
-
- # Add material to mesh.
- mesh = self.parent.mesh
-
- # Return where it is in the mesh for faces.
- mesh_materials= mesh.materials
-
- material_index= -1
- for i,m in enumerate(mesh_materials):
- if m.name==mat.name:
- material_index= i
- break
-
- if material_index==-1:
- material_index= len(mesh_materials)
- if material_index==16:
- material_index= 15
- if global_prefs['verbose'] >= 1:
- print 'Warning: Too many materials per mesh object. Only a maximum of 16 ' + \
- 'allowed. Using 16th material instead.'
-
- else:
- mesh_materials.append(mat)
- mesh.materials= mesh_materials
-
- return (material_index, image)
-
-
def blender_import(self):
vert_count = len(self.indices)
- if vert_count < 3:
+ if vert_count < 1:
if global_prefs['verbose'] >= 2:
print 'Warning: Ignoring face with no vertices.'
return
@@ -1106,18 +1131,21 @@ class Face(Node):
# Assign material and image
self.parent.faceLs.append(self)
- self.blen_mat_idx, self.blen_image= self.create_blender_material()
-
-
-
+ #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.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
@@ -1138,8 +1166,49 @@ class Face(Node):
' 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)
@@ -1152,15 +1221,15 @@ class Object(InterNode):
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({5: self.parse_face,
- #130: self.parse_indexed_light_point,
- #111: self.parse_inline_light_point,
+ 19: self.parse_subpush,
+ 20: self.parse_subpop,
+ 111: self.parse_inline_light_point,
10: self.parse_push,
11: self.parse_pop})
- self.props['type'] = 'Object'
- self.props['id'] = self.header.fw.read_string(8)
-
-
+ self.props = dict()
+ self.props['comment'] = ''
+ self.parse_record()
class Group(InterNode):
def __init__(self, parent):
@@ -1174,15 +1243,16 @@ class Group(InterNode):
self.root_handler.set_throw_back_lst(throw_back_opcodes)
self.child_handler.set_handler({5: self.parse_face,
- #130: self.parse_indexed_light_point,
- #111: self.parse_inline_light_point,
+ 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_unhandled,
+ 14: self.parse_dof,
91: self.parse_unhandled,
98: self.parse_unhandled,
63: self.parse_xref})
@@ -1190,20 +1260,48 @@ class Group(InterNode):
'special2', 'significance', 'layer code', 'loop count',
'loop duration', 'last frame duration'])
- self.props['type'] = 'Group'
self.props['comment'] = ''
- self.props['id'] = self.header.fw.read_string(8)
- self.props['priority'] = self.header.fw.read_short()
- self.header.fw.read_ahead(2)
- self.props['flags'] = self.header.fw.read_int()
- self.props['special1'] = self.header.fw.read_short()
- self.props['special2'] = self.header.fw.read_short()
- self.props['significance'] = self.header.fw.read_short()
- self.props['layer code'] = self.header.fw.read_char()
- self.header.fw.read_ahead(5)
- self.props['loop count'] = self.header.fw.read_int()
- self.props['loop duration'] = self.header.fw.read_float()
- self.props['last frame duration'] = self.header.fw.read_float()
+ 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})
+ 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.props = dict()
+ self.props['comment'] = ''
+ self.parse_record()
+
class XRef(InterNode):
def parse(self):
@@ -1214,31 +1312,66 @@ class XRef(InterNode):
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)
- xref_filename = self.header.fw.read_string(200)
- filename = FF.find(xref_filename)
+ self.props = dict()
+ self.props['comment'] = ''
+ self.parse_record()
- self.props['type'] = 'XRef'
+ xref_filename = self.props['3t200!filename']
+ self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(xref_filename))[0] #this is really wrong as well....
- if filename != None:
- self.xref = Database(filename, self)
- self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(filename))[0]
+ if global_prefs['doxrefs'] and os.path.exists(xref_filename) and not self.header.grr.xrefs.has_key(xref_filename):
+ self.xref = Database(xref_filename, self.header.grr, self)
+ self.header.grr.xrefs[xref_filename] = self.xref
else:
self.xref = None
- self.props['id'] = 'X: broken'
+
+
+ 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])
+ #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
+ if self.matrix:
+ self.object.setMatrix(self.matrix)
+ Node.blender_import(self)
+
+
class LOD(InterNode):
def blender_import(self):
- self.move_to_next_layer()
+ #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,
@@ -1246,18 +1379,20 @@ class LOD(InterNode):
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_unhandled, # DOF
+ 14: self.parse_dof, # DOF
91: self.parse_unhandled, # sound
98: self.parse_unhandled, # clip
63: self.parse_xref})
- self.props['type'] = 'LOD'
- self.props['id'] = self.header.fw.read_string(8)
+ self.props = dict()
+ self.props['comment'] = ''
+ self.parse_record()
class InlineLightPoint(InterNode):
def __init__(self, parent):
@@ -1274,119 +1409,49 @@ class InlineLightPoint(InterNode):
11: self.parse_pop})
self.indices = list()
-
- self.props = dict.fromkeys(['id', 'type', 'comment', 'draw order', 'appearance'])
- self.app_props = dict()
-
+ self.props = dict()
self.props['comment'] = ''
- self.props['type'] = 'Light Point'
- self.props['id'] = self.header.fw.read_string(8)
-
- self.app_props.update({'smc': self.header.fw.read_short()})
- self.app_props.update({'fid': self.header.fw.read_short()})
- self.app_props.update({'back color: a': self.header.fw.read_uchar()})
- self.app_props.update({'back color: b': self.header.fw.read_uchar()})
- self.app_props.update({'back color: g': self.header.fw.read_uchar()})
- self.app_props.update({'back color: r': self.header.fw.read_uchar()})
- self.app_props.update({'display mode': self.header.fw.read_int()})
- self.app_props.update({'intensity': self.header.fw.read_float()})
- self.app_props.update({'back intensity': self.header.fw.read_float()})
- self.app_props.update({'minimum defocus': self.header.fw.read_float()})
- self.app_props.update({'maximum defocus': self.header.fw.read_float()})
- self.app_props.update({'fading mode': self.header.fw.read_int()})
- self.app_props.update({'fog punch mode': self.header.fw.read_int()})
- self.app_props.update({'directional mode': self.header.fw.read_int()})
- self.app_props.update({'range mode': self.header.fw.read_int()})
- self.app_props.update({'min pixel size': self.header.fw.read_float()})
- self.app_props.update({'max pixel size': self.header.fw.read_float()})
- self.app_props.update({'actual size': self.header.fw.read_float()})
- self.app_props.update({'trans falloff pixel size': self.header.fw.read_float()})
- self.app_props.update({'trans falloff exponent': self.header.fw.read_float()})
- self.app_props.update({'trans falloff scalar': self.header.fw.read_float()})
- self.app_props.update({'trans falloff clamp': self.header.fw.read_float()})
- self.app_props.update({'fog scalar': self.header.fw.read_float()})
- self.app_props.update({'fog intensity': self.header.fw.read_float()})
- self.app_props.update({'size threshold': self.header.fw.read_float()})
- self.app_props.update({'directionality': self.header.fw.read_int()})
- self.app_props.update({'horizontal lobe angle': self.header.fw.read_float()})
- self.app_props.update({'vertical lobe angle': self.header.fw.read_float()})
- self.app_props.update({'lobe roll angle': self.header.fw.read_float()})
- self.app_props.update({'dir falloff exponent': self.header.fw.read_float()})
- self.app_props.update({'dir ambient intensity': self.header.fw.read_float()})
- self.header.fw.read_ahead(12) # Animation settings.
- self.app_props.update({'significance': self.header.fw.read_float()})
- self.props['draw order'] = self.header.fw.read_int()
- self.app_props.update({'flags': self.header.fw.read_int()})
- #self.fw.read_ahead(12) # More animation settings.
-
- # 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 = GRR.request_lightpoint_app(app_desc)
+ self.parse_record()
- 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 = '%s: %s' % (self.props['type'], self.props['id'])
+
- name_to_indices = self.group_points(self.app_props)
+ 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.parent and self.parent.object and self.header.scene == self.parent.header.scene:
+ self.parent.object.makeParent([self.object])
- for app_name, indices in name_to_indices.iteritems():
- self.object = Blender.Object.New('Mesh', name)
- #self.mesh = self.object.getData()
- self.mesh= Blender.Mesh.New()
- self.mesh.verts.extend( Vector() ) # DUMMYVERT
- self.object.link(self.mesh)
+ if self.matrix:
+ self.object.setMatrix(self.matrix)
- 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)
-
- scene.link(self.object)
- self.object.Layer = current_layer
- self.object.sel= 1
-
- 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()
- # 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
@@ -1432,7 +1497,7 @@ class IndexedLightPoint(InterNode):
app_desc.props.update({'b': vert_desc.b})
app_desc.props.update({'a': vert_desc.a})
- app_name = GRR.request_lightpoint_app(app_desc)
+ 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)
@@ -1448,7 +1513,6 @@ class IndexedLightPoint(InterNode):
for app_name, indices in name_to_indices.iteritems():
self.object = Blender.Object.New('Mesh', name)
- #self.mesh = self.object.getData()
self.mesh= Blender.Mesh.New()
self.mesh.verts.extend( Vector() ) # DUMMYVERT
self.object.link(self.mesh)
@@ -1460,7 +1524,7 @@ class IndexedLightPoint(InterNode):
vert = self.header.vert_pal.blender_verts[i]
self.mesh.verts.append(vert)
- scene.link(self.object)
+ self.header.scene.objects.link(self.object)
self.object.Layer = current_layer
@@ -1543,7 +1607,7 @@ class Unhandled(InterNode):
10: self.parse_push,
11: self.parse_pop,
96: self.parse_unhandled, # switch
- 14: self.parse_unhandled, # DOF
+ 14: self.parse_dof, # DOF
91: self.parse_unhandled, # sound
98: self.parse_unhandled, # clip
63: self.parse_xref})
@@ -1552,30 +1616,31 @@ class Unhandled(InterNode):
class Database(InterNode):
def blender_import(self):
- self.tex_pal = dict(self.tex_pal_lst)
- del self.tex_pal_lst
-
- # Setup Textures
- bl_tex_pal_lst = list()
- for i in self.tex_pal.iterkeys():
- path_filename = FF.find(self.tex_pal[i])
+ for key in self.tex_pal.keys():
+ path_filename= FF.find(self.tex_pal[key][0])
if path_filename != None:
- img = GRR.request_image(path_filename)
+ img = self.grr.request_image(path_filename)
if img:
- tex = GRR.request_texture(img)
- tex.setName(FF.strip_path(self.tex_pal[i]))
- bl_tex_pal_lst.append( (i, tex) )
- else:
- bl_tex_pal_lst.append( (i, None) )
+ self.tex_pal[key][1] = img
elif global_prefs['verbose'] >= 1:
- print 'Warning: Unable to find', self.tex_pal[i]
-
- self.bl_tex_pal = dict(bl_tex_pal_lst)
-
- # Setup Materials
- self.mat_desc_pal = dict(self.mat_desc_pal_lst)
-
- InterNode.blender_import(self)
+ 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
+
+ #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()
@@ -1696,9 +1761,10 @@ class Database(InterNode):
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)
@@ -1707,7 +1773,7 @@ class Database(InterNode):
a = int(brightest[3])
color = [r, g, b, a]
-
+
return color
def parse_color_palette(self):
@@ -1728,15 +1794,56 @@ class Database(InterNode):
def parse_texture_palette(self):
name = self.fw.read_string(200)
index = self.fw.read_int()
- self.tex_pal_lst.append( (index, name) )
+ self.tex_pal[index]= [name, None]
return True
-
- def __init__(self, filename, parent=None):
+
+ 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
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)
@@ -1753,23 +1860,26 @@ class Database(InterNode):
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,
+ 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_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.tex_pal_lst = list()
+ #self.bl_tex_pal = dict()
self.col_pal = list()
self.mat_desc_pal_lst = list()
self.mat_desc_pal = dict()
@@ -1778,7 +1888,70 @@ class Database(InterNode):
'sw lon', 'ne lat', 'ne lon', 'origin lat', 'origin lon', 'lambert lat1',
'lambert lat2', 'ellipsoid model', 'utm zone', 'radius', 'major axis', 'minor axis'])
-def select_file(filename):
+
+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 and location[1] != 0.0 and 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)
@@ -1801,13 +1974,12 @@ def select_file(filename):
global_prefs['get_ambient'] = False
global_prefs['get_shininess'] = True
global_prefs['color_from_face'] = True
+ global_prefs['log to blender'] = True
+
+
- # Start loading the file,
- # first set the context
Blender.Window.WaitCursor(True)
Blender.Window.EditMode(0)
- for ob in scene.objects:
- ob.sel=0
FF.add_file_to_search_path(filename)
@@ -1817,7 +1989,7 @@ def select_file(filename):
print
load_time = Blender.sys.time()
- db = Database(filename)
+ db = Database(filename,grr)
db.parse()
load_time = Blender.sys.time() - load_time
@@ -1828,23 +2000,15 @@ def select_file(filename):
import_time = Blender.sys.time()
db.blender_import()
- import_time = Blender.sys.time() - import_time
-
- Blender.Window.ViewLayer(range(1,21))
-
- # FIX UP AFTER DUMMY VERT AND REMOVE DOUBLES
- Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX'])
- for ob in scene.objects.context:
- if ob.type=='Mesh':
- me=ob.getData(mesh=1)
- me.verts.delete(0) # remove the dummy vert
- me.sel= 1
- me.remDoubles(0.0001)
+ if global_prefs['attrib']:
+ print "reading attribute files"
+ db.read_attribute_files()
+ Blender.Window.ViewLayer(range(1,21))
- Blender.Window.RedrawAll()
-
+ update_scene(db.scene,[])
+ import_time = Blender.sys.time() - import_time
if global_prefs['verbose'] >= 1:
print 'Done.'
print
@@ -1854,37 +2018,112 @@ def select_file(filename):
Blender.Window.WaitCursor(False)
+def setimportscale(ID,val):
+ global global_prefs
+ global_prefs['scale'] = val
+def setBpath(fname):
+ global_prefs['fltfile'] = fname
-if global_prefs['verbose'] >= 1:
- print
- print 'OpenFlight Importer'
- print 'Version:', __version__
- print 'Author: Greg MacDonald'
- print __url__[2]
- print
+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()
+
-if __name__ == '__main__':
- Blender.Window.FileSelector(select_file, "Import OpenFlight", "*.flt")
- #select_file('/fe/flt/helnwsflt/helnws.flt')
- #select_file('/fe/flt/Container_006.flt')
- #select_file('/fe/flt/NaplesORIGINALmesh.flt')
- #select_file('/Anti_tank_D30.flt')
- #select_file('/metavr/file_examples/flt/cherrypoint/CherryPoint_liter_runway.flt')
+
+from Blender.BGL import *
+from Blender import Draw
+def gui():
+
+ global FLTBaseLabel
+ global FLTBaseString
+ global FLTBaseChooser
-"""
-TIME= Blender.sys.time()
-import os
-PATH= 'c:\\flt_test'
-for FNAME in os.listdir(PATH):
- if FNAME.lower().endswith('.flt'):
- FPATH= os.path.join(PATH, FNAME)
- newScn= Blender.Scene.New(FNAME)
- newScn.makeCurrent()
- scene= newScn
- select_file(FPATH)
-
-print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME)
-"""
- \ No newline at end of file
+ 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) \ No newline at end of file
diff --git a/release/scripts/flt_palettemanager.py b/release/scripts/flt_palettemanager.py
new file mode 100644
index 00000000000..c641a0a4f08
--- /dev/null
+++ b/release/scripts/flt_palettemanager.py
@@ -0,0 +1,388 @@
+#!BPY
+
+"""
+Name: 'FLT Palette Manager'
+Blender: 240
+Group: 'Misc'
+Tooltip: 'Manage FLT colors'
+"""
+
+__author__ = "Geoffrey Bantle"
+__version__ = "1.0 11/21/2007"
+__email__ = ('scripts', 'Author, ')
+__url__ = ('blender', 'elysiun')
+
+__bpydoc__ ="""\
+
+This script manages colors in OpenFlight databases. OpenFlight is a
+registered trademark of MultiGen-Paradigm, Inc.
+
+Todo:
+-Figure out whats causing the PC speaker to beep when initializing...
+
+Feature overview and more availible at:
+http://wiki.blender.org/index.php/Scripts/Manual/FLTools
+"""
+
+# --------------------------------------------------------------------------
+# flt_palettemanager.py version 0.1 2005/04/08
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
+import Blender.Draw as Draw
+from Blender.BGL import *
+import Blender
+import flt_properties
+import flt_defaultp as defaultp
+from flt_properties import *
+
+
+palette_size = 12
+palette_x = 0
+palette_y = 0
+
+colors = list()
+curint = 1.0
+curswatch = 0
+#make a default palette, not very useful.
+cinc = 1.0 / 1024.0
+cstep = 0.0
+picker = None
+ptt = ""
+for i in xrange(1024):
+ colors.append([cstep,cstep,cstep])
+ cstep = cstep + cinc
+def update_state():
+ state = dict()
+ state["activeScene"] = Blender.Scene.getCurrent()
+ state["activeObject"] = state["activeScene"].getActiveObject()
+ state["activeMesh"] = None
+ if state["activeObject"] and state["activeObject"].type == 'Mesh':
+ state["activeMesh"] = state["activeObject"].getData(mesh=True)
+
+ state["activeFace"] = None
+ if state["activeMesh"]:
+ if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
+ state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
+
+ return state
+
+def pack_face_index(index, intensity):
+ return ((127*intensity)+(128*index))
+def unpack_face_index(face_index):
+ index = face_index / 128
+ intensity = float(face_index - 128.0 * index) / 127.0
+ return(index,intensity)
+
+def event(evt,val):
+ global palette_size
+ global palette_x
+ global palette_y
+ global colors
+ global curint
+ global curswatch
+
+ areas = Blender.Window.GetScreenInfo()
+ curarea = Blender.Window.GetAreaID()
+ curRect = None
+ editmode = 0
+
+ for area in areas:
+ if area['id'] == curarea:
+ curRect = area['vertices']
+ break
+
+ if evt == Draw.LEFTMOUSE:
+ mval = Blender.Window.GetMouseCoords()
+ rastx = mval[0] - curRect[0]
+ rasty = mval[1] - curRect[1]
+
+ swatchx = (rastx -palette_x) / palette_size #+state["palette_x"]
+ swatchy = (rasty -palette_y) / palette_size #+state["palette_y"]
+ if rastx > palette_x and rastx < (palette_x + palette_size * 32) and rasty > palette_y and rasty < (palette_y+ palette_size* 32):
+ if swatchx < 32 and swatchy < 32:
+ curswatch = (swatchx * 32) + swatchy
+ Draw.Redraw(1)
+
+ elif swatchy < 34 and swatchx < 32:
+ curint = 1.0 - (float(rastx-palette_x)/(palette_size*32.0))
+ Draw.Redraw(1)
+
+ #copy current color and intensity to selected faces.
+ elif evt == Draw.CKEY:
+
+ if Blender.Window.EditMode():
+ Blender.Window.EditMode(0)
+ editmode = 1
+ state = update_state()
+
+ #retrieve color from palette
+ color = struct.unpack('>BBBB',struct.pack('>I',colors[curswatch]))
+ actmesh = state["activeMesh"]
+ if actmesh:
+ if(Blender.Window.GetKeyQualifiers() != Blender.Window.Qual["CTRL"]):
+ selfaces = list()
+ for face in actmesh.faces:
+ if face.sel:
+ selfaces.append(face)
+
+ if not "FLT_COL" in actmesh.faces.properties:
+ actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
+ for face in actmesh.faces:
+ face.setProperty("FLT_COL",127) #default
+ try:
+ actmesh.activeColorLayer = "FLT_Fcol"
+ except:
+ actmesh.addColorLayer("FLT_Fcol")
+ actmesh.activeColorLayer = "FLT_Fcol"
+
+
+ for face in selfaces:
+ #First append packed index + color and store in face property
+ face.setProperty("FLT_COL",int(pack_face_index(curswatch,curint)))
+ #Save baked color to face vertex colors
+ for col in face.col:
+ col.r = int(color[0] * curint)
+ col.g = int(color[1] * curint)
+ col.b = int(color[2] * curint)
+ col.a = int(color[3] * curint)
+ else:
+ if Blender.Mesh.Mode() == Blender.Mesh.SelectModes['VERTEX']:
+ if not 'FLT_VCOL' in actmesh.verts.properties:
+ actmesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"])
+ for vert in actmesh.verts:
+ vert.setProperty("FLT_VCOL",127)
+ else:
+ for vert in actmesh.verts:
+ if vert.sel:
+ vert.setProperty("FLT_VCOL",int(pack_face_index(curswatch,curint)))
+
+ if editmode:
+ Blender.Window.EditMode(1)
+
+ Blender.Window.RedrawAll()
+
+ #grab color and intensity from active face
+ elif evt == Draw.VKEY:
+ if Blender.Window.EditMode():
+ Blender.Window.EditMode(0)
+ editmode = 1
+ state = update_state()
+
+ actmesh = state["activeMesh"]
+ activeFace = state["activeFace"]
+
+
+ if activeFace:
+ if not "FLT_COL" in actmesh.faces.properties:
+ actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
+ for face in actmesh.faces:
+ face.setProperty("FLT_COL",127) #default
+ try:
+ actmesh.activeColorLayer = "FLT_Fcol"
+ except:
+ actmesh.addColorLayer("FLT_Fcol")
+ actmesh.activeColorLayer = "FLT_Fcol"
+ tcol = activeFace.getProperty("FLT_COL")
+ (index,intensity) = unpack_face_index(tcol)
+ curswatch = index
+ curint = intensity
+
+ if editmode:
+ Blender.Window.EditMode(1)
+
+ Blender.Window.RedrawAll()
+
+ elif evt == Draw.ESCKEY:
+ Draw.Exit()
+
+ if editmode:
+ Blender.Window.EditMode(1)
+
+def update_all():
+ global colors
+ state = update_state()
+ #update the baked FLT colors for all meshes.
+ for object in state["activeScene"].objects:
+ if object.type == "Mesh":
+ mesh = object.getData(mesh=True)
+ if 'FLT_COL' in mesh.faces.properties:
+ mesh.activeColorLayer = "FLT_Fcol"
+ for face in mesh.faces:
+ (index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
+ color = struct.unpack('>BBBB',struct.pack('>I',colors[index]))
+ #update the vertex colors for this face
+ for col in face.col:
+ col.r = int(color[0] * intensity)
+ col.g = int(color[1] * intensity)
+ col.b = int(color[2] * intensity)
+ col.a = 255
+
+
+def but_event(evt):
+ global palette_size
+ global palette_x
+ global palette_y
+ global colors
+ global curint
+ global curswatch
+ global picker
+ state = update_state()
+
+ if evt == 1:
+ if picker.val:
+ rval = (int(picker.val[0]*255),int(picker.val[1]*255),int(picker.val[2]*255),255)
+ rval = struct.pack('>BBBB',rval[0],rval[1],rval[2],rval[3])
+ rval = struct.unpack('>i',rval)
+ colors[curswatch] = rval[0]
+ #go cd through all meshes and update their FLT colors
+ update_all()
+
+ Draw.Redraw(1)
+def init_pal():
+ global palette_size
+ global palette_x
+ global palette_y
+ global colors
+ global curint
+ global curswatch
+
+ state = update_state()
+
+ if not state["activeScene"].properties.has_key('FLT'):
+ state["activeScene"].properties['FLT'] = dict()
+
+ try:
+ colors = state["activeScene"].properties['FLT']['Color Palette']
+ except:
+ state["activeScene"].properties['FLT']['Color Palette'] = defaultp.pal
+ colors = state["activeScene"].properties['FLT']['Color Palette']
+
+def draw_palette():
+ global palette_size
+ global palette_x
+ global palette_y
+ global colors
+ global curint
+ global curswatch
+ global picker
+
+ state = update_state()
+ init_pal()
+
+ ssize = palette_size
+ xpos = palette_x
+ cid = 0
+
+ highlight = [(palette_x,palette_y),(palette_x+palette_size,palette_y),(palette_x+palette_size,palette_y+palette_size),(palette_x,palette_y+palette_size)]
+ for x in xrange(32):
+ ypos = palette_y
+ for y in xrange(32):
+ color = struct.unpack('>BBBB',struct.pack('>I',colors[cid]))
+ glColor3f(color[0]/255.0,color[1]/255.0,color[2]/255.0)
+ glBegin(GL_POLYGON)
+ glVertex2i(xpos,ypos)
+ glVertex2i(xpos+ssize,ypos)
+ glVertex2i(xpos+ssize,ypos+ssize)
+ glVertex2i(xpos,ypos+ssize)
+ glEnd()
+
+ if curswatch == cid:
+ highlight[0] = (xpos,ypos)
+ highlight[1] = (xpos+ssize,ypos)
+ highlight[2] = (xpos+ssize,ypos+ssize)
+ highlight[3] = (xpos,ypos+ssize)
+
+ glColor3f(0.0,0.0,0.0)
+ glBegin(GL_LINE_LOOP)
+ glVertex2i(xpos,ypos)
+ glVertex2i(xpos+ssize,ypos)
+ glVertex2i(xpos+ssize,ypos+ssize)
+ glVertex2i(xpos,ypos+ssize)
+ glVertex2i(xpos,ypos)
+ glEnd()
+
+
+ cid = cid + 1
+ ypos = ypos + ssize
+
+ xpos = xpos + ssize
+
+ #draw intensity gradient
+ color = struct.unpack('>BBBB',struct.pack('>I',colors[curswatch]))
+ color = [color[0]/255.0,color[1]/255.0,color[2]/255.0]
+ colsteps = [color[0]/255.0,color[1]/255.0,color[2]/255.0]
+ stripwidth = (palette_size * 32.0) / 256
+ strippad = palette_size / 2.0
+
+ xpos = palette_x
+ grady = (palette_y + (palette_size * 32.0)) + strippad
+ for x in xrange(256):
+ color[0] = color[0] - colsteps[0]
+ color[1] = color[1] - colsteps[1]
+ color[2] = color[2] - colsteps[2]
+
+ glColor3f(color[0], color[1] ,color[2])
+ glBegin(GL_POLYGON)
+ glVertex2f(xpos,grady)
+ glVertex2f(xpos+stripwidth,grady)
+ glVertex2f(xpos+stripwidth,grady+palette_size)
+ glVertex2f(xpos,grady+palette_size)
+ glEnd()
+ xpos = xpos + stripwidth
+
+ #draw intensity slider bar
+ #xposition == 512 - ((curint) * 512)
+ xpos = ((palette_size*32) * (1.0 - curint)) + palette_x
+ glColor3f(1.0,1.0,1.0)
+ glBegin(GL_LINE_LOOP)
+ glVertex2i(xpos-6,grady-1)
+ glVertex2i(xpos+6,grady-1)
+ glVertex2i(xpos+6,grady+palette_size+1)
+ glVertex2i(xpos-6,grady+palette_size+1)
+ #glVertex2i(xpos-6,grady+7)
+ glEnd()
+
+ #draw color picker
+ color = struct.unpack('>BBBB',struct.pack('>I',colors[curswatch]))
+ pickcol = (color[0]/255.0,color[1]/255.0,color[2]/255.0)
+ picker = Blender.Draw.ColorPicker(1,highlight[0][0]+1,highlight[0][1]+1,ssize-2,ssize-2,pickcol,ptt)
+
+ #draw highlight swatch
+ glColor3f(1.0,1.0,1.0)
+ glBegin(GL_LINE_LOOP)
+ glVertex2i(highlight[0][0],highlight[0][1])
+ glVertex2i(highlight[1][0],highlight[1][1])
+ glVertex2i(highlight[2][0],highlight[2][1])
+ glVertex2i(highlight[3][0],highlight[3][1])
+ glVertex2i(highlight[0][0],highlight[0][1])
+ glEnd()
+
+def gui():
+ glClearColor(0.5,0.5,0.5,1.0)
+ glClear(GL_COLOR_BUFFER_BIT)
+ draw_palette()
+
+
+init_pal()
+Draw.Register(gui,event,but_event)
+
diff --git a/release/scripts/flt_properties.py b/release/scripts/flt_properties.py
new file mode 100644
index 00000000000..07bcc8def1d
--- /dev/null
+++ b/release/scripts/flt_properties.py
@@ -0,0 +1,619 @@
+#!BPY
+# flt_properties.py. For setting default OpenFLight ID property types
+# Copyright (C) 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.
+
+__bpydoc__ ="""\
+Utility functions and data defintions used by OpenFlight I/O and tool scripts. OpenFlight is a
+registered trademark of MultiGen-Paradigm, Inc.
+"""
+
+
+import struct
+
+bitsLSB = [2147483648]
+for i in xrange(31):
+ bitsLSB.append(bitsLSB[-1]/2)
+bitsRSB = bitsLSB[:]
+bitsRSB.reverse()
+
+def pack_color(col):
+ return struct.pack('>B',col[3]) + struct.pack('>B',col[2]) + struct.pack('>B',col[1]) + struct.pack('>B',col[0])
+
+def unpack_color(col):
+ string = struct.pack('>I', col)
+ r = struct.unpack('>B',string[3:4])
+ g = struct.unpack('>B',string[2:3])
+ b = struct.unpack('>B',string[1:2])
+ a = struct.unpack('>B',string[0:1])
+ return [r,g,b,a]
+
+def reverse_bits(len,num):
+ bitbucket = list()
+ rval = 0
+
+ for i in xrange(len):
+ if num & bitsRSB[i]:
+ bitbucket.append(1)
+ else:
+ bitbucket.append(0)
+
+ bitbucket.reverse()
+
+ for i, bit in enumerate(bitbucket):
+ if bit:
+ rval |= bitsLSB[i]
+
+ return rval
+
+
+opcode_name = { 0: 'db',
+ 1: 'head',
+ 2: 'grp',
+ 4: 'obj',
+ 5: 'face',
+ 10: 'push',
+ 11: 'pop',
+ 14: 'dof',
+ 19: 'push sub',
+ 20: 'pop sub',
+ 21: 'push ext',
+ 22: 'pop ext',
+ 23: 'cont',
+ 31: 'comment',
+ 32: 'color pal',
+ 33: 'long id',
+ 49: 'matrix',
+ 50: 'vector',
+ 52: 'multi-tex',
+ 53: 'uv lst',
+ 55: 'bsp',
+ 60: 'rep',
+ 61: 'inst ref',
+ 62: 'inst def',
+ 63: 'ext ref',
+ 64: 'tex pal',
+ 67: 'vert pal',
+ 68: 'vert w col',
+ 69: 'vert w col & norm',
+ 70: 'vert w col, norm & uv',
+ 71: 'vert w col & uv',
+ 72: 'vert lst',
+ 73: 'lod',
+ 74: 'bndin box',
+ 76: 'rot edge',
+ 78: 'trans',
+ 79: 'scl',
+ 80: 'rot pnt',
+ 81: 'rot and/or scale pnt',
+ 82: 'put',
+ 83: 'eyepoint & trackplane pal',
+ 84: 'mesh',
+ 85: 'local vert pool',
+ 86: 'mesh prim',
+ 87: 'road seg',
+ 88: 'road zone',
+ 89: 'morph vert lst',
+ 90: 'link pal',
+ 91: 'snd',
+ 92: 'rd path',
+ 93: 'snd pal',
+ 94: 'gen matrix',
+ 95: 'txt',
+ 96: 'sw',
+ 97: 'line styl pal',
+ 98: 'clip reg',
+ 100: 'ext',
+ 101: 'light src',
+ 102: 'light src pal',
+ 103: 'reserved',
+ 104: 'reserved',
+ 105: 'bndin sph',
+ 106: 'bndin cyl',
+ 107: 'bndin hull',
+ 108: 'bndin vol cntr',
+ 109: 'bndin vol orient',
+ 110: 'rsrvd',
+ 111: 'light pnt',
+ 112: 'tex map pal',
+ 113: 'mat pal',
+ 114: 'name tab',
+ 115: 'cat',
+ 116: 'cat dat',
+ 117: 'rsrvd',
+ 118: 'rsrvd',
+ 119: 'bounding hist',
+ 120: 'rsrvd',
+ 121: 'rsrvd',
+ 122: 'push attrib',
+ 123: 'pop attrib',
+ 124: 'rsrvd',
+ 125: 'rsrvd',
+ 126: 'curv',
+ 127: 'road const',
+ 128: 'light pnt appear pal',
+ 129: 'light pnt anim pal',
+ 130: 'indexed lp',
+ 131: 'lp sys',
+ 132: 'indx str',
+ 133: 'shdr pal'}
+
+
+typecodes = ['c','C','s','S','i','I','f','d','t']
+
+FLT_GRP = 2
+FLT_OBJ = 4
+FLT_LOD = 73
+FLT_XRF = 63
+FLT_DOF = 14
+FLT_ILP = 111
+FLT_DB = 1
+FLT_FCE = 5
+
+#not actual opcodes
+FLT_NUL = 0
+FLT_EXP = -1
+
+#valid childtypes for each FLT node type
+FLT_CHILDTYPES = {
+ FLT_GRP : [111,2,73,4,14,63],
+ FLT_OBJ : [111],
+ FLT_LOD : [111,2,73,4,14,63],
+ FLT_XRF : [],
+ FLT_DOF : [111,2,73,4,14,63],
+ FLT_ILP : []
+}
+
+#List of nodes that can have faces as children
+FLT_FACETYPES = [
+ FLT_GRP,
+ FLT_OBJ,
+ FLT_LOD,
+ FLT_DOF
+]
+
+def write_prop(fw,type,value,length):
+ if type == 'c':
+ fw.write_char(value)
+ elif type == 'C':
+ fw.write_uchar(value)
+ elif type == 's':
+ fw.write_short(value)
+ elif type == 'S':
+ fw.write_ushort(value)
+ elif type == 'i':
+ fw.write_int(value)
+ elif type == 'I':
+ fw.write_uint(value)
+ elif type == 'd':
+ fw.write_double(value)
+ elif type == 'f':
+ fw.write_float(value)
+ elif type == 't':
+ fw.write_string(value,length)
+
+def read_prop(fw,type,length):
+ rval = None
+ if type == 'c':
+ rval = fw.read_char()
+ elif type == 'C':
+ rval = fw.read_uchar()
+ elif type == 's':
+ rval = fw.read_short()
+ elif type == 'S':
+ rval = fw.read_ushort()
+ elif type == 'i':
+ rval = fw.read_int()
+ elif type == 'I':
+ rval = fw.read_uint()
+ elif type == 'd':
+ rval = fw.read_double()
+ elif type == 'f':
+ rval = fw.read_float()
+ elif type == 't':
+ rval = fw.read_string(length)
+ return rval
+
+FLTGroup = {
+ '3t8!id' : 'G',
+ '4s!priority' : 0,
+ '5s!reserved1' : 0,
+ '6i!flags' : 0,
+ '7s!special1' : 0,
+ '8s!special2' : 0,
+ '9s!significance' : 0,
+ '10c!layer code' : 0,
+ '11c!reserved2' : 0,
+ '12i!reserved3' : 0,
+ '13i!loop count' : 0,
+ '14f!loop duration' : 0,
+ '15f!last frame duration' : 0
+}
+FLTGroupDisplay = [5,11,12]
+
+FLTObject = {
+ '3t8!id' : 'O',
+ '4I!flags' : 0,
+ '5s!priority' : 0,
+ '6S!transp' : 0,
+ '7s!SFX1' : 0,
+ '8s!SFX2' : 0,
+ '9s!significance' : 0,
+ '10s!reserved' : 0
+}
+FLTObjectDisplay = [10]
+
+FLTLOD = {
+ '3t8!id' : 'L',
+ '4i!reserved' : 0,
+ '5d!switch in' : 0,
+ '6d!switch out' : 0,
+ '7s!sfx ID1' : 0,
+ '8s!sfx ID2' : 0,
+ '9I!flags' : 0,
+ '10d!X co' : 0,
+ '11d!Y co' : 0,
+ '12d!Z co' : 0,
+ '13d!Transition' : 0,
+ '14d!Sig Size' : 0
+}
+FLTLODDisplay = [4]
+
+FLTInlineLP = {
+ '3t8!id' : 'Lp',
+ '4s!smc' : 0,
+ '5s!fid' : 0,
+ '6C!back color: a' : 255,
+ '7C!back color: b' : 255,
+ '8C!back color: g' : 255,
+ '9C!back color: r' : 255,
+ '10i!display mode' : 255,
+ '11f!intensity' : 1.0,
+ '12f!back intensity' : 0.0,
+ '13f!minimum defocus' : 0.0,
+ '14f!maximum defocus' : 1.0,
+ '15i!fading mode' : 0,
+ '16i!fog punch mode' : 0,
+ '17i!directional mode' : 1,
+ '18i!range mode' : 0,
+ '19f!min pixel size' : 1.0,
+ '20f!max pixel size' : 1024,
+ '21f!actual size' : 0.25,
+ '22f!trans falloff pixel size' : 0.25,
+ '23f!trans falloff exponent' : 1.0,
+ '24f!trans falloff scalar' : 1.0,
+ '25f!trans falloff clamp' : 1.0,
+ '26f!fog scalar' : 0.25,
+ '27f!fog intensity' : 1.0,
+ '28f!size threshold' : 0.1,
+ '29i!directionality' : 0,
+ '30f!horizontal lobe angle' : 180.0,
+ '31f!vertical lobe angle' : 180.0,
+ '32f!lobe roll angle' : 0.0,
+ '33f!dir falloff exponent' : 1.0,
+ '34f!dir ambient intensity' : 0.1,
+ '35f!anim period' : 0,
+ '36f!anim phase' : 0,
+ '37f!anim enabled' : 0,
+ '38f!significance' : 0.0,
+ '39i!draw order' : 0,
+ '40I!flags' : 813875616,
+ '41f!roti' : 0,
+ '42f!rotj' : 0,
+ '43f!rotk' : 0
+}
+
+FLTInlineLPDisplay = [35,36,37,41,42,43]
+
+FLTXRef = {
+ '3t200!filename' : '', #we dont actually use this value on export
+ '4i!reserved' : 0,
+ '5I!flag' : -478150656,
+ '6s!bbox' : 0,
+ '7s!reserved' : 0
+}
+
+FLTXRefDisplay = [4,7,3]
+
+FLTDOF = {
+ '3t8!id' : 'D',
+ '4i!reserved' : 0,
+ '5d!ORIGX' : 0.0,
+ '6d!ORIGY' : 0.0,
+ '7d!ORIGZ' : 0.0,
+ '8d!XAXIS-X' : 10.0,
+ '9d!XAXIS-Y' : 0.0,
+ '10d!XAXIS-Z' : 0.0,
+ '11d!XYPLANE-X' : 0.0,
+ '12d!XYPLANE-Y' : 10.0,
+ '13d!XZPLANE-Z' : 0.0,
+ '14d!ZMIN' : 0.0,
+ '15d!ZMAX' : 0.0,
+ '16d!ZCUR' : 0.0,
+ '17d!ZSTEP' : 0.0,
+ '18d!YMIN' : 0.0,
+ '19d!YMAX' : 0.0,
+ '20d!YCUR' : 0.0,
+ '21d!YSTEP' : 0.0,
+ '22d!XMIN' : 0.0,
+ '23d!XMAX' : 0.0,
+ '24d!XCUR' : 0.0,
+ '25d!XSTEP' : 0.0,
+ '26d!PITCH-MIN' : 0.0,
+ '27d!PITCH-MAX' : 0.0,
+ '28d!PITCH-CUR' : 0.0,
+ '29d!PITCH-STEP' : 0.0,
+ '30d!ROLL-MIN' : 0.0,
+ '31d!ROLL-MAX' : 0.0,
+ '32d!ROLL-CUR' : 0.0,
+ '33d!ROLL-STEP' : 0.0,
+ '34d!YAW-MIN' : 0.0,
+ '35d!YAW-MAX' : 0.0,
+ '36d!YAW-CUR' : 0.0,
+ '37d!YAW-STEP' : 0.0,
+ '38d!ZSIZE-MIN' : 0.0,
+ '39d!ZSIZE-MAX' : 0.0,
+ '40d!ZSIZE-CUR' : 1.0,
+ '41d!ZSIZE-STEP' : 0.0,
+ '42d!YSIZE-MIN' : 0.0,
+ '43d!YSIZE-MAX' : 0.0,
+ '44d!YSIZE-CUR' : 1.0,
+ '45d!YSIZE-STEP' : 0.0,
+ '46d!XSIZE-MIN' : 0.0,
+ '47d!XSIZE-MAX' : 0.0,
+ '48d!XSIZE-CUR' : 1.0,
+ '49d!XSIZE-STEP' : 0.0,
+ '50I!FLAG' : 1897582,
+ '51i!reserved2' : 0
+}
+
+FLTDOFDisplay = [4]
+
+FLTImage = {
+ '3i!RealU Direction' : 0,
+ '4i!RealV Direction' : 0,
+ '5i!UpX' : 0,
+ '6i!UpY' : 0,
+ '7i!File Format' : 0,
+ '8i!Min Filter' : 1,
+ '9i!Mag Filter' : 1,
+ '10i!Wrap' : 0,
+ '11i!WrapU' : 0,
+ '12i!WrapV' : 0,
+ '13i!Modified' : 0,
+ '14i!PivotX' : 0,
+ '15i!PivotY' : 0,
+ '16i!Enviorment' : 0,
+ '17i!WhiteAlpha' : 0,
+ '18i!reserved1' : 0,
+ '19i!reserved2' : 0,
+ '20i!reserved3' : 0,
+ '21i!reserved4' : 0,
+ '22i!reserved5' : 0,
+ '23i!reserved6' : 0,
+ '24i!reserved7' : 0,
+ '25i!reserved8' : 0,
+ '26i!reserved9' : 0,
+ '27d!RealU Direction' : 0,
+ '28d!RealV Direction' : 0,
+ '29i!Origin' : 0,
+ '30i!Kernel no.' : 0,
+ '31i!Internal Format' : 0,
+ '32i!External Format' : 0,
+ '33i!MipMap Filter?' : 0,
+ '34f!MMF1' : 0.0,
+ '35f!MMF2' : 0.0,
+ '36f!MMF3' : 0.0,
+ '37f!MMF4' : 0.0,
+ '38f!MMF5' : 0.0,
+ '39f!MMF6' : 0.0,
+ '40f!MMF7' : 0.0,
+ '41f!MMF8' : 0.0,
+ '42i!Tex CPs?' : 0,
+ '43f!LOD0 CP' : 0.0,
+ '44f!Scale0 CP' : 0.0,
+ '45f!LOD1 CP' : 0.0,
+ '46f!Scale1 CP' : 0.0,
+ '47f!LOD2 CP' : 0.0,
+ '48f!Scale2 CP' : 0.0,
+ '49f!LOD3 CP' : 0.0,
+ '50f!Scale3 CP' : 0.0,
+ '51f!LOD4 CP' : 0.0,
+ '52f!Scale4 CP' : 0.0,
+ '53f!LOD5 CP' : 0.0,
+ '54f!Scale5 CP' : 0.0,
+ '55f!LOD6 CP' : 0.0,
+ '56f!Scale6 CP' : 0.0,
+ '57f!LOD7 CP' : 0.0,
+ '58f!Scale7 CP' : 0.0,
+ '59f!Control Clamp' : 0.0,
+ '60i!Mag Alpha Filter' : 0,
+ '61i!Mag Color Filter' : 0,
+ '62f!reserved10' : 0,
+ '63f!reserved11' : 0,
+ '64f!reserved12' : 0,
+ '65f!reserved13' : 0,
+ '66f!reserved14' : 0,
+ '67f!reserved15' : 0,
+ '68f!reserved16' : 0,
+ '69f!reserved17' : 0,
+ '70f!reserved18' : 0,
+ '71d!Lambert Central' : 0.0,
+ '72d!Lambert Upper' : 0.0,
+ '73d!Lambert Lower' : 0.0,
+ '74d!reserved19' : 0,
+ '75f!reserved20' : 0,
+ '76f!reserved21' : 0,
+ '77f!reserved22' : 0,
+ '78f!reserved23' : 0,
+ '79f!reserved24' : 0,
+ '80i!Tex Detail?' : 0,
+ '81i!Tex J' : 0,
+ '82i!Tex K' : 0,
+ '83i!Tex M' : 0,
+ '84i!Tex N' : 0,
+ '85i!Tex Scramble' : 0,
+ '86i!Tex Tile?' : 0,
+ '87f!Tex Tile LLU' : 0.0,
+ '88f!Tex Tile LLV' : 0.0,
+ '89f!Tex Tile URU' : 0.0,
+ '90f!Tex Tile URV' : 0.0,
+ '91i!Projection' : 0,
+ '92i!Earth Model' : 0,
+ '93i!reserved25' : 0,
+ '94i!UTM Zone' : 0,
+ '95i!Image Origin' : 0,
+ '96i!GPU' : 0,
+ '97i!reserved26' : 0,
+ '98i!reserved27' : 0,
+ '99i!GPU Hemi' : 0,
+ '100i!reserved41' : 0,
+ '101i!reserved42' : 0,
+ '102i!reserved43' : 0,
+ '103i!Cubemap' : 0,
+ '104t588!reserved44' : '',
+ '105t512!Comments' : '',
+ '106i!reserved28' : 0,
+ '107i!reserved29' : 0,
+ '108i!reserved30' : 0,
+ '109i!reserved31' : 0,
+ '110i!reserved32' : 0,
+ '111i!reserved33' : 0,
+ '112i!reserved34' : 0,
+ '113i!reserved35' : 0,
+ '114i!reserved36' : 0,
+ '115i!reserved37' : 0,
+ '116i!reserved38' : 0,
+ '117i!reserved39' : 0,
+ '118i!reserved40' : 0,
+ '119i!reserved45' : 0,
+ '120i!Format Version' : 0,
+ '121i!GPU num' : 0,
+}
+
+FLTImageDisplay = [18,19,29,21,22,23,24,25,26,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,93,97,98,102,114]
+
+FLTHeader = {
+ '3t8!id' : 'db',
+ '4i!version' : 1620,
+ '5i!editversion' : 0,
+ '6t32!date' : 0,
+ '7s!NGID' : 0,
+ '8s!NLID' : 0,
+ '9s!NOID' : 0,
+ '10s!NFID' : 0,
+ '11s!UMULT' : 1,
+ '12c!units' : 0,
+ '13c!set white' : 0,
+ '14I!flags' : 0x80000000,
+ '15i!reserved1' : 0,
+ '16i!reserved2' : 0,
+ '17i!reserved3' : 0,
+ '18i!reserved4' : 0,
+ '19i!reserved5' : 0,
+ '20i!reserved6' : 0,
+ '21i!projection type' : 0,
+ '22i!reserved7' : 0,
+ '23i!reserved8' : 0,
+ '24i!reserved9' : 0,
+ '25i!reserved10' : 0,
+ '26i!reserved11' : 0,
+ '27i!reserved12' : 0,
+ '28i!reserved13' : 0,
+ '29s!NDID' : 0,
+ '30s!vstore' : 1,
+ '31i!origin' : 0,
+ '32d!sw x' : 0,
+ '33d!sw y' : 0,
+ '34d!dx' : 0,
+ '35d!dy' : 0,
+ '36s!NSID' : 0,
+ '37s!NPID' : 0,
+ '38i!reserved14' : 0,
+ '39i!reserved15' : 0,
+ '40s!NCID' : 0,
+ '41s!NTID' : 0,
+ '42s!NBID' : 0,
+ '43s!NWID' : 0,
+ '44i!reserved14' : 0,
+ '45d!sw lat' : 0,
+ '46d!sw lon' : 0,
+ '47d!ne lat' : 0,
+ '48d!ne lon' : 0,
+ '49d!origin lat' : 0,
+ '50d!origin lon' : 0,
+ '51d!lambert lat1' : 0,
+ '52d!lambert lat2' : 0,
+ '53s!NLSID' : 0,
+ '54s!NLPID' : 0,
+ '55s!NRID' : 0,
+ '56s!NCATID' : 0,
+ '57s!reserved15' : 0,
+ '58s!reserved16' : 0,
+ '59s!reserved17' : 0,
+ '60s!reserved18' : 0,
+ '61i!ellipsoid model' : 1,
+ '62s!NAID' : 0,
+ '63s!NCVID' : 0,
+ '64s!utm zone' : 0,
+ '65t6!reserved19' : 0,
+ '66d!dz' : 0,
+ '67d!radius' : 0,
+ '68S!NMID' : 0,
+ '69S!NLPSID' : 0,
+ '70i!reserved20' : 0,
+ '71d!major axis' : 0,
+ '72d!minor axis' : 0,
+}
+
+FLT_Records = {
+ 2 : FLTGroup,
+ 4 : FLTObject,
+ 73 : FLTLOD,
+ 63 : FLTXRef,
+ 14 : FLTDOF,
+ 1 : FLTHeader,
+ 111 : FLTInlineLP,
+ 'Image' : FLTImage
+}
+
+def process_recordDefs():
+ records = dict()
+ 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
+ return records
+
+
diff --git a/release/scripts/flt_toolbar.py b/release/scripts/flt_toolbar.py
new file mode 100644
index 00000000000..d8a4aa8b4a0
--- /dev/null
+++ b/release/scripts/flt_toolbar.py
@@ -0,0 +1,594 @@
+#!BPY
+
+"""
+Name: 'FLT Toolbar'
+Blender: 240
+Group: 'Misc'
+Tooltip: 'Tools for working with FLT databases'
+"""
+
+__author__ = "Geoffrey Bantle"
+__version__ = "1.0 11/21/07"
+__email__ = ('scripts', 'Author, ')
+__url__ = ('blender', 'elysiun')
+
+__bpydoc__ ="""\
+This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a
+registered trademark of MultiGen-Paradigm, Inc.
+
+Feature overview and more availible at:
+http://wiki.blender.org/index.php/Scripts/Manual/FLTools
+"""
+
+# --------------------------------------------------------------------------
+# flt_palettemanager.py version 0.1 2005/04/08
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
+import Blender.Draw as Draw
+from Blender.BGL import *
+import Blender
+import flt_properties
+reload(flt_properties)
+from flt_properties import *
+
+xrefprefix = ""
+xrefstack = list()
+vofsstack = list()
+vquatstack = list()
+prop_w = 256
+prop_h = 256
+
+
+#event codes
+evcode = {
+ "XREF_MAKE" : 100,
+ "XREF_EDIT" : 101,
+ "XREF_FILE" : 102,
+ "XREF_PICK" : 103,
+ "XREF_SELECT" : 104,
+ "XREF_POP" : 105,
+ "XREF_PREFIX" : 106,
+ "FACE_NAME" : 200,
+ "FACE_MAKESUB" : 201,
+ "FACE_KILLSUB" : 202,
+ "FACE_SELSUB" : 203,
+ "SCENE_UPDATE" : 303,
+ "IDPROP_COPY" : 501,
+ "IDPROP_KILL" : 502,
+ "CLIGHT_MAKE" : 700
+}
+
+XREF_PREFIX = None
+XREF_MAKE = None
+XREF_EDIT = None
+XREF_SELECT = None
+XREF_POP = None
+FACE_MAKESUB = None
+FACE_SELSUB = None
+FACE_KILLSUB = None
+IDPROP_KILL = None
+IDPROP_COPY = None
+SCENE_UPDATE = None
+CLIGHT_MAKE = None
+
+def update_state():
+ state = dict()
+ state["activeScene"] = Blender.Scene.getCurrent()
+ state["activeObject"] = state["activeScene"].getActiveObject()
+ if state["activeObject"] and not state["activeObject"].sel:
+ state["activeObject"] = None
+ state["activeMesh"] = None
+ if state["activeObject"] and state["activeObject"].type == 'Mesh':
+ state["activeMesh"] = state["activeObject"].getData(mesh=True)
+
+ state["activeFace"] = None
+ if state["activeMesh"]:
+ if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
+ state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
+
+ #update editmode
+ state["editmode"] = Blender.Window.EditMode()
+
+ return state
+def pack_face_index(index, intensity):
+ return ((127*intensity)+(128*index))
+def unpack_face_index(face_index):
+ index = face_index / 128
+ intensity = float(face_index - 128.0 * index) / 127.0
+ return(index,intensity)
+
+def idprops_append(object, typecode, props):
+ object.properties["FLT"] = dict()
+ object.properties["FLT"]['type'] = typecode
+ for prop in props:
+ object.properties["FLT"][prop] = props[prop]
+ object.properties["FLT"]['3t8!id'] = object.name
+
+def idprops_kill(object):
+ state = update_state()
+ if object and object.properties.has_key('FLT'):
+ object.properties.pop('FLT')
+
+def idprops_copy(source):
+ state = update_state()
+ if source.properties.has_key('FLT'):
+ for object in state["activeScene"].objects:
+ if object.sel and object != source and (state["activeScene"].Layers & object.Layers):
+ idprops_kill(object)
+ object.properties['FLT'] = dict()
+ for key in source.properties['FLT']:
+ object.properties['FLT'][key] = source.properties['FLT'][key]
+
+def update_all():
+ state = update_state()
+ #update the baked FLT colors for all meshes.
+ for object in state["activeScene"].objects:
+ if object.type == "Mesh":
+ mesh = object.getData(mesh=True)
+ if 'FLT_COL' in mesh.faces.properties:
+ mesh.activeColorLayer = "FLT_Fcol"
+ for face in mesh.faces:
+ (index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
+ color = struct.unpack('>BBBB',struct.pack('>I',state["colors"][index]))
+ #update the vertex colors for this face
+ for col in face.col:
+ col.r = int(color[0] * intensity)
+ col.g = int(color[1] * intensity)
+ col.b = int(color[2] * intensity)
+ col.a = 255
+
+
+#Change this to find the deep parent
+def xref_create():
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+
+ state = update_state()
+
+ def findchildren(object):
+ children = list()
+ for candidate in state["activeScene"].objects:
+ if candidate.parent == object:
+ children.append(candidate)
+ retlist = list(children)
+ for child in children:
+ retlist = retlist + findchildren(child)
+ return retlist
+
+ actObject = state["activeObject"]
+ if actObject and xrefprefix:
+ scenenames = list()
+ for scene in Blender.Scene.Get():
+ scenenames.append(scene.name)
+
+ if xrefprefix in scenenames:
+ #build a unique name for the xref...
+ suffix = 1
+ found = False
+ while not found:
+ candidate = xrefprefix + str(suffix)
+ if not candidate in scenenames:
+ xrefname = candidate
+ found = True
+ suffix+=1
+ else:
+ xrefname = xrefprefix
+ #create our XRef node
+ xnode = state["activeScene"].objects.new('Empty')
+ xnode.name = 'X:' + xrefname
+ xnode.properties['FLT'] = dict()
+ for prop in FLTXRef:
+ xnode.properties['FLT'][prop] = FLTXRef[prop]
+ xnode.properties['FLT']['3t200!filename'] = xrefname + '.flt'
+ xnode.properties['FLT']['type'] = 63
+ xnode.enableDupGroup = True
+ xnode.DupGroup = Blender.Group.New(xrefname) #this is dangerous... be careful!
+
+ #copy rot and loc of actObject
+ xnode.setLocation(actObject.getLocation())
+ xnode.setEuler(actObject.getEuler())
+
+ #build the new scene
+ xrefscene = Blender.Scene.New(xrefname)
+ xrefscene.properties['FLT'] = dict()
+ xrefscene.properties['FLT']['Filename'] = xrefname
+ xrefscene.properties['FLT']['Main'] = 0
+
+ #find the children of actObject so that we can add them to the group
+ linkobjects = findchildren(actObject)
+ linkobjects.append(actObject)
+ for object in linkobjects:
+ xrefscene.objects.link(object)
+ state["activeScene"].objects.unlink(object)
+ xnode.DupGroup.objects.link(object)
+ #clear rotation of actObject and location
+ actObject.setLocation(0.0,0.0,0.0)
+ actObject.setEuler(0.0,0.0,0.0)
+
+ xrefscene.update(1)
+ state["activeScene"].update(1)
+
+def xref_edit():
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+
+ state = update_state()
+
+ actObject = state["activeObject"]
+
+ if actObject and actObject.type == 'Empty' and actObject.DupGroup:
+# if actObject.properties.has_key('FLT') and actObject.properties['FLT']['type'] == 63:
+ for FLTscene in Blender.Scene.Get():
+ if FLTscene.properties.has_key('FLT') and FLTscene.name == actObject.DupGroup.name:
+ actObject.sel = 0
+ xrefstack.append(state["activeScene"])
+ vofsstack.append(Blender.Window.GetViewOffset())
+ vquatstack.append(Blender.Window.GetViewQuat())
+ FLTscene.makeCurrent()
+ Blender.Window.SetViewOffset(0.0,0.0,0.0)
+
+def xref_finish():
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+
+ state = update_state()
+ if xrefstack:
+ scene = xrefstack.pop()
+ Blender.Window.SetViewQuat(vquatstack.pop())
+ Blender.Window.SetViewOffset(vofsstack.pop())
+ scene.makeCurrent()
+
+
+def sortSub(a,b):
+ aindex = a.getProperty("FLT_ORIGINDEX")
+ bindex = b.getProperty("FLT_ORIGINDEX")
+
+ if aindex > bindex:
+ return 1
+ elif aindex < bindex:
+ return -1
+ return 0
+
+def subface_make():
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+
+ editmode = 0
+ if Blender.Window.EditMode():
+ Blender.Window.EditMode(0)
+ editmode = 1
+
+ state = update_state()
+
+ actmesh = state["activeMesh"]
+ activeFace = state["activeFace"]
+ if actmesh:
+ if not "FLT_ORIGINDEX" in actmesh.faces.properties:
+ actmesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"])
+ for i, face in enumerate(actmesh.faces):
+ face.setProperty("FLT_ORIGINDEX",i)
+ if not "FLT_SFLEVEL" in actmesh.faces.properties:
+ actmesh.faces.addPropertyLayer("FLT_SFLEVEL",Blender.Mesh.PropertyTypes["INT"])
+
+ #attach the subfaces to the active face. Note, this doesnt really work 100 percent properly yet, just enough for one level!
+ if activeFace:
+ #steps:
+ #remove actface and selected faces from the facelist
+ #quicksort facelist
+ #append actface and subfaces to end of facelist.
+ #generate new indices
+ facelist = list()
+ sublist = list()
+ for face in actmesh.faces:
+ facelist.append(face)
+ for face in facelist:
+ if face == activeFace:
+ face.setProperty("FLT_SFLEVEL",0)
+ sublist.insert(0,face)
+ elif face.sel:
+ face.setProperty("FLT_SFLEVEL",1)
+ sublist.append(face)
+ for face in sublist:
+ facelist.remove(face)
+ facelist.sort(sortSub)
+ for face in sublist:
+ facelist.append(face)
+ for i, face in enumerate(facelist):
+ face.setProperty("FLT_ORIGINDEX",i)
+ else:
+ pass
+
+ if editmode:
+ Blender.Window.EditMode(1)
+
+def subface_kill():
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+
+ editmode = 0
+ if Blender.Window.EditMode():
+ Blender.Window.EditMode(0)
+ editmode = 1
+ state = update_state()
+
+ actmesh = state["activeMesh"]
+ if actmesh:
+ if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties:
+ for i,face in enumerate(actmesh.faces):
+ face.setProperty("FLT_ORIGINDEX",i)
+ face.setProperty("FLT_SFLEVEL",0)
+ if editmode:
+ Blender.Window.EditMode(1)
+
+def subface_select():
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+
+ editmode = 0
+ if Blender.Window.EditMode():
+ Blender.Window.EditMode(0)
+ editmode = 1
+ state = update_state()
+
+ actmesh = state["activeMesh"]
+ activeFace = state["activeFace"]
+ if actmesh and activeFace:
+ if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties:
+ facelist = list()
+ actIndex = None
+ sublevel = None
+ for face in actmesh.faces:
+ facelist.append(face)
+ facelist.sort(sortSub)
+ for i, face in enumerate(facelist):
+ if face == activeFace:
+ actIndex = i
+ sublevel = face.getProperty("FLT_SFLEVEL")+1
+ break
+ leftover = facelist[actIndex+1:]
+ for face in leftover:
+ if face.getProperty("FLT_SFLEVEL") == sublevel:
+ face.sel = 1
+ else:
+ break
+ if editmode:
+ Blender.Window.EditMode(1)
+
+def select_by_typecode(typecode):
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+
+ state = update_state()
+
+ for object in state["activeScene"].objects:
+ if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers:
+ object.select(1)
+def clight_make():
+ state = update_state()
+ actmesh = state["activeMesh"]
+ actobj = state["activeObject"]
+
+ if actobj and actmesh:
+ actobj.properties['FLT'] = dict()
+ actobj.properties['FLT']['type'] = 111
+ for prop in FLTInlineLP:
+ actobj.properties['FLT'][prop] = FLTInlineLP[prop]
+
+ actmesh.verts.addPropertyLayer("FLT_VCOL", Blender.Mesh.PropertyTypes["INT"])
+ for v in actmesh.verts:
+ v.setProperty("FLT_VCOL", 67295)
+
+def event(evt,val):
+ if evt == Draw.ESCKEY:
+ Draw.Exit()
+
+def but_event(evt):
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+ global evcode
+
+ state = update_state()
+
+ #do Xref buttons
+ if evt == evcode["XREF_PREFIX"]:
+ xrefprefix = XREF_PREFIX.val
+ if evt == evcode["XREF_EDIT"]:
+ xref_edit()
+ if evt == evcode["XREF_SELECT"]:
+ select_by_typecode(63)
+ if evt == evcode["XREF_MAKE"]:
+ xref_create()
+ #do scene buttons
+ if evt == evcode["SCENE_UPDATE"]:
+ update_all()
+ #do face buttons
+ if evt == evcode["FACE_MAKESUB"]:
+ subface_make()
+ if evt== evcode["FACE_KILLSUB"]:
+ subface_kill()
+ if evt== evcode["FACE_SELSUB"]:
+ subface_select()
+ #common buttons
+ if evt == evcode["IDPROP_KILL"]:
+ if state["activeObject"]:
+ idprops_kill(state["activeObject"])
+ if evt == evcode["IDPROP_COPY"]:
+ if state["activeObject"]:
+ idprops_copy(state["activeObject"])
+ if evt == evcode["XREF_POP"]:
+ xref_finish()
+ if evt == evcode["CLIGHT_MAKE"]:
+ clight_make()
+ Draw.Redraw(1)
+ Blender.Window.RedrawAll()
+
+
+def box(x,y,w,h,c,mode):
+ glColor3f(c[0],c[1],c[2])
+ if mode == "outline":
+ glBegin(GL_LINE_LOOP)
+ else:
+ glBegin(GL_POLYGON)
+ glVertex2i(x,y)
+ glVertex2i(x+w,y)
+ glVertex2i(x+w,y+h)
+ glVertex2i(x,y+h)
+ glEnd()
+
+def draw_postcommon(x,y,finaly):
+ global sheetlabel
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+ global evcode
+
+ state = update_state()
+
+ width = prop_w
+ height = prop_h
+
+ #draw the header
+ glColor3f(0.15,0.15,0.15)
+ glBegin(GL_POLYGON)
+ glVertex2i(x-1,y)
+ glVertex2i(x+width+1,y)
+ glVertex2i(x+width+1,y-25)
+ glVertex2i(x-1,y-25)
+ glEnd()
+ glColor3f(1,1,1)
+ glRasterPos2i(x,y-20)
+ sheetlabel = Blender.Draw.Text("FLT Tools Panel")
+ #draw the box outline
+ glColor3f(0,0,0)
+ glBegin(GL_LINE_LOOP)
+ glVertex2i(x-1,y)
+ glVertex2i(x+1+width,y)
+ glVertex2i(x+1+width,finaly-1)
+ glVertex2i(x-1,finaly-1)
+ glEnd()
+ return finaly
+
+
+def draw_propsheet(x,y):
+ global XREF_PREFIX
+ global XREF_MAKE
+ global XREF_EDIT
+ global XREF_SELECT
+ global XREF_POP
+ global FACE_MAKESUB
+ global FACE_SELSUB
+ global FACE_KILLSUB
+ global IDPROP_KILL
+ global IDPROP_COPY
+ global SCENE_UPDATE
+ global CLIGHT_MAKE
+ global xrefprefix
+ global xrefstack
+ global vofsstack
+ global vquatstack
+ global prop_w
+ global prop_h
+ global evcode
+
+ state = update_state()
+
+ width = prop_w
+ height = prop_h
+ origx = x
+ origy = y
+
+ #draw Xref tools
+ y = y-20
+ XREF_PREFIX = Blender.Draw.String("XRef Name:",evcode["XREF_PREFIX"],x,y,width,20,xrefprefix,18,"Xref prefix name, Actual name is generated from this")
+ y = y-20
+ XREF_MAKE = Blender.Draw.PushButton("Make XRef",evcode["XREF_MAKE"],x,y,width,20,"Make External Reference")
+ y = y-20
+ XREF_EDIT = Blender.Draw.PushButton("Edit XRef",evcode["XREF_EDIT"],x,y,width,20,"Edit External Reference")
+ y = y-20
+ XREF_SELECT = Blender.Draw.PushButton("Select XRefs",evcode["XREF_SELECT"],x,y,width,20,"Select External References")
+ y = y - 20
+ XREF_POP = Blender.Draw.PushButton("Return to previous scene",evcode["XREF_POP"],x,y,width,20,"Go up one level in xref hierarchy")
+
+ #Draw facetools
+ y = y-20
+ FACE_MAKESUB = Blender.Draw.PushButton("Make Subfaces",evcode["FACE_MAKESUB"],x,y,width,20,"Make subfaces")
+ y = y-20
+ FACE_SELSUB = Blender.Draw.PushButton("Select Subfaces",evcode["FACE_SELSUB"],x,y,width,20,"Select subfaces")
+ y = y-20
+ FACE_KILLSUB = Blender.Draw.PushButton("Kill Subfaces",evcode["FACE_KILLSUB"],x,y,width,20,"Kill subfaces")
+
+ #Draw ID Property tools
+ y = y - 20
+ IDPROP_KILL = Blender.Draw.PushButton("Delete ID props",evcode["IDPROP_KILL"],x,y,width,20,"Delete ID props")
+ y = y - 20
+ IDPROP_COPY = Blender.Draw.PushButton("Copy to selected",evcode["IDPROP_COPY"],x,y,width,20, "Copy from active to all selected")
+
+ y= y - 20
+ CLIGHT_MAKE = Blender.Draw.PushButton("Make Light Point", evcode["CLIGHT_MAKE"],x,y,width,20,"Create inline light points from current mesh")
+ #General tools
+ y = y-20
+ SCENE_UPDATE = Blender.Draw.PushButton("Update All",evcode["SCENE_UPDATE"],x,y,width,20,"Update all vertex colors")
+ draw_postcommon(origx, origy,y)
+
+def gui():
+ #draw the propsheet/toolbox.
+ psheety = 256
+ #psheetx = psheety + 10
+ draw_propsheet(0,psheety)
+Draw.Register(gui,event,but_event)
+