~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to release/scripts/export_fbx.py

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2007-05-17 11:47:59 UTC
  • mfrom: (1.2.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20070517114759-yp4ybrnhp2u7pk66
Tags: 2.44-1
* New upstream release.
* Drop debian/patches/01_64bits_stupidity, not needed anymore: as of this
  version blender is 64 bits safe again. Adjust README.Debian accordingly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!BPY
 
2
"""
 
3
Name: 'Autodesk FBX (.fbx)...'
 
4
Blender: 243
 
5
Group: 'Export'
 
6
Tooltip: 'Selection to an ASCII Autodesk FBX '
 
7
"""
 
8
__author__ = "Campbell Barton"
 
9
__url__ = ['www.blender.org', 'blenderartists.org']
 
10
__version__ = "1.1"
 
11
 
 
12
__bpydoc__ = """\
 
13
This script is an exporter to the FBX file format.
 
14
 
 
15
Usage:
 
16
 
 
17
Select the objects you wish to export and run this script from "File->Export" menu.
 
18
All objects that can be represented as a mesh (mesh, curve, metaball, surface, text3d)
 
19
will be exported as mesh data.
 
20
"""
 
21
 
 
22
# --------------------------------------------------------------------------
 
23
# FBX Export v0.1 by Campbell Barton (AKA Ideasman)
 
24
# --------------------------------------------------------------------------
 
25
# ***** BEGIN GPL LICENSE BLOCK *****
 
26
#
 
27
# This program is free software; you can redistribute it and/or
 
28
# modify it under the terms of the GNU General Public License
 
29
# as published by the Free Software Foundation; either version 2
 
30
# of the License, or (at your option) any later version.
 
31
#
 
32
# This program is distributed in the hope that it will be useful,
 
33
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
34
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
35
# GNU General Public License for more details.
 
36
#
 
37
# You should have received a copy of the GNU General Public License
 
38
# along with this program; if not, write to the Free Software Foundation,
 
39
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
40
#
 
41
# ***** END GPL LICENCE BLOCK *****
 
42
# --------------------------------------------------------------------------
 
43
 
 
44
import Blender
 
45
import BPyObject
 
46
import BPyMesh
 
47
import BPySys
 
48
import BPyMessages
 
49
import time
 
50
from math import degrees, atan, pi
 
51
# Used to add the scene name into the filename without using odd chars
 
52
 
 
53
sane_name_mapping_ob = {}
 
54
sane_name_mapping_mat = {}
 
55
sane_name_mapping_tex = {}
 
56
 
 
57
def strip_path(p):
 
58
        return p.split('\\')[-1].split('/')[-1]
 
59
 
 
60
def sane_name(data, dct):
 
61
        if not data: return None
 
62
        name = data.name
 
63
        try:            return dct[name]
 
64
        except:         pass
 
65
        
 
66
        orig_name = name
 
67
        name = BPySys.cleanName(name)
 
68
        dct[orig_name] = name
 
69
        return name
 
70
 
 
71
def sane_obname(data):          return sane_name(data, sane_name_mapping_ob)
 
72
def sane_matname(data):         return sane_name(data, sane_name_mapping_mat)
 
73
def sane_texname(data):         return sane_name(data, sane_name_mapping_tex)
 
74
 
 
75
# May use this later
 
76
"""
 
77
# Auto class, use for datastorage only, a like a dictionary but with limited slots
 
78
def auto_class(slots):
 
79
        exec('class container_class(object): __slots__=%s' % slots)
 
80
        return container_class
 
81
"""
 
82
 
 
83
 
 
84
header_comment = \
 
85
'''; FBX 6.1.0 project file
 
86
; Created by Blender FBX Exporter
 
87
; for support mail cbarton@metavr.com
 
88
; ----------------------------------------------------
 
89
 
 
90
'''
 
91
 
 
92
def write_header(file):
 
93
        file.write(header_comment)
 
94
        curtime = time.localtime()[0:6]
 
95
        # 
 
96
        file.write(\
 
97
'''FBXHeaderExtension:  {
 
98
        FBXHeaderVersion: 1003
 
99
        FBXVersion: 6100
 
100
        CreationTimeStamp:  {
 
101
                Version: 1000
 
102
                Year: %.4i
 
103
                Month: %.2i
 
104
                Day: %.2i
 
105
                Hour: %.2i
 
106
                Minute: %.2i
 
107
                Second: %.2i
 
108
                Millisecond: 0
 
109
        }
 
110
        Creator: "FBX SDK/FBX Plugins build 20070228"
 
111
        OtherFlags:  {
 
112
                FlagPLE: 0
 
113
        }
 
114
}''' % (curtime))
 
115
        
 
116
        file.write('\nCreationTime: "%.4i-%.2i-%.2i %.2i:%.2i:%.2i:000"' % curtime)
 
117
        file.write('\nCreator: "Blender3D version %.2f"' % Blender.Get('version'))
 
118
 
 
119
 
 
120
 
 
121
 
 
122
def write_scene(file, sce, world):
 
123
        
 
124
        def write_object_tx(ob, loc, matrix):
 
125
                '''
 
126
                We have loc to set the location if non blender objects that have a location
 
127
                '''
 
128
                
 
129
                if ob and not matrix:   matrix = ob.matrixWorld
 
130
                matrix_rot = matrix
 
131
                #if matrix:
 
132
                #       matrix = matrix_scale * matrix
 
133
                
 
134
                if matrix:
 
135
                        loc = tuple(matrix.translationPart())
 
136
                        scale = tuple(matrix.scalePart())
 
137
                        
 
138
                        matrix_rot = matrix.rotationPart()
 
139
                        # Lamps need to be rotated
 
140
                        if ob and ob.type =='Lamp':
 
141
                                matrix_rot = Blender.Mathutils.RotationMatrix(90, 4, 'x') * matrix
 
142
                                rot = tuple(matrix_rot.toEuler())
 
143
                        elif ob and ob.type =='Camera':
 
144
                                y = Blender.Mathutils.Vector(0,1,0) * matrix_rot
 
145
                                matrix_rot = matrix_rot * Blender.Mathutils.RotationMatrix(90, 3, 'r', y)
 
146
                                rot = tuple(matrix_rot.toEuler())
 
147
                        else:
 
148
                                rot = tuple(matrix_rot.toEuler())
 
149
                else:
 
150
                        if not loc:
 
151
                                loc = 0,0,0
 
152
                        scale = 1,1,1
 
153
                        rot = 0,0,0
 
154
                
 
155
                file.write('\n\t\t\tProperty: "Lcl Translation", "Lcl Translation", "A+",%.15f,%.15f,%.15f' % loc)
 
156
                file.write('\n\t\t\tProperty: "Lcl Rotation", "Lcl Rotation", "A+",%.15f,%.15f,%.15f' % rot)
 
157
                file.write('\n\t\t\tProperty: "Lcl Scaling", "Lcl Scaling", "A+",%.15f,%.15f,%.15f' % scale)
 
158
                return loc, rot, scale, matrix, matrix_rot
 
159
        
 
160
        def write_object_props(ob=None, loc=None, matrix=None):
 
161
                # if the type is 0 its an empty otherwise its a mesh
 
162
                # only difference at the moment is one has a color
 
163
                file.write('''
 
164
                Properties60:  {
 
165
                        Property: "QuaternionInterpolate", "bool", "",0
 
166
                        Property: "Visibility", "Visibility", "A+",1''')
 
167
                
 
168
                loc, rot, scale, matrix, matrix_rot = write_object_tx(ob, loc, matrix)
 
169
                
 
170
                # Rotation order
 
171
                # eEULER_XYZ
 
172
                # eEULER_XZY
 
173
                # eEULER_YZX
 
174
                # eEULER_YXZ
 
175
                # eEULER_ZXY
 
176
                # eEULER_ZYX 
 
177
                
 
178
                
 
179
                file.write('''
 
180
                        Property: "RotationOffset", "Vector3D", "",0,0,0
 
181
                        Property: "RotationPivot", "Vector3D", "",0,0,0
 
182
                        Property: "ScalingOffset", "Vector3D", "",0,0,0
 
183
                        Property: "ScalingPivot", "Vector3D", "",0,0,0
 
184
                        Property: "TranslationActive", "bool", "",0
 
185
                        Property: "TranslationMin", "Vector3D", "",0,0,0
 
186
                        Property: "TranslationMax", "Vector3D", "",0,0,0
 
187
                        Property: "TranslationMinX", "bool", "",0
 
188
                        Property: "TranslationMinY", "bool", "",0
 
189
                        Property: "TranslationMinZ", "bool", "",0
 
190
                        Property: "TranslationMaxX", "bool", "",0
 
191
                        Property: "TranslationMaxY", "bool", "",0
 
192
                        Property: "TranslationMaxZ", "bool", "",0
 
193
                        Property: "RotationOrder", "enum", "",1
 
194
                        Property: "RotationSpaceForLimitOnly", "bool", "",0
 
195
                        Property: "AxisLen", "double", "",10
 
196
                        Property: "PreRotation", "Vector3D", "",0,0,0
 
197
                        Property: "PostRotation", "Vector3D", "",0,0,0
 
198
                        Property: "RotationActive", "bool", "",0
 
199
                        Property: "RotationMin", "Vector3D", "",0,0,0
 
200
                        Property: "RotationMax", "Vector3D", "",0,0,0
 
201
                        Property: "RotationMinX", "bool", "",0
 
202
                        Property: "RotationMinY", "bool", "",0
 
203
                        Property: "RotationMinZ", "bool", "",0
 
204
                        Property: "RotationMaxX", "bool", "",0
 
205
                        Property: "RotationMaxY", "bool", "",0
 
206
                        Property: "RotationMaxZ", "bool", "",0
 
207
                        Property: "RotationStiffnessX", "double", "",0
 
208
                        Property: "RotationStiffnessY", "double", "",0
 
209
                        Property: "RotationStiffnessZ", "double", "",0
 
210
                        Property: "MinDampRangeX", "double", "",0
 
211
                        Property: "MinDampRangeY", "double", "",0
 
212
                        Property: "MinDampRangeZ", "double", "",0
 
213
                        Property: "MaxDampRangeX", "double", "",0
 
214
                        Property: "MaxDampRangeY", "double", "",0
 
215
                        Property: "MaxDampRangeZ", "double", "",0
 
216
                        Property: "MinDampStrengthX", "double", "",0
 
217
                        Property: "MinDampStrengthY", "double", "",0
 
218
                        Property: "MinDampStrengthZ", "double", "",0
 
219
                        Property: "MaxDampStrengthX", "double", "",0
 
220
                        Property: "MaxDampStrengthY", "double", "",0
 
221
                        Property: "MaxDampStrengthZ", "double", "",0
 
222
                        Property: "PreferedAngleX", "double", "",0
 
223
                        Property: "PreferedAngleY", "double", "",0
 
224
                        Property: "PreferedAngleZ", "double", "",0
 
225
                        Property: "InheritType", "enum", "",0
 
226
                        Property: "ScalingActive", "bool", "",0
 
227
                        Property: "ScalingMin", "Vector3D", "",1,1,1
 
228
                        Property: "ScalingMax", "Vector3D", "",1,1,1
 
229
                        Property: "ScalingMinX", "bool", "",0
 
230
                        Property: "ScalingMinY", "bool", "",0
 
231
                        Property: "ScalingMinZ", "bool", "",0
 
232
                        Property: "ScalingMaxX", "bool", "",0
 
233
                        Property: "ScalingMaxY", "bool", "",0
 
234
                        Property: "ScalingMaxZ", "bool", "",0
 
235
                        Property: "GeometricTranslation", "Vector3D", "",0,0,0
 
236
                        Property: "GeometricRotation", "Vector3D", "",0,0,0
 
237
                        Property: "GeometricScaling", "Vector3D", "",1,1,1
 
238
                        Property: "LookAtProperty", "object", ""
 
239
                        Property: "UpVectorProperty", "object", ""
 
240
                        Property: "Show", "bool", "",1
 
241
                        Property: "NegativePercentShapeSupport", "bool", "",1
 
242
                        Property: "DefaultAttributeIndex", "int", "",0''')
 
243
                if ob:
 
244
                        # Only mesh objects have color 
 
245
                        file.write('\n\t\t\tProperty: "Color", "Color", "A",0.8,0.8,0.8')
 
246
                        file.write('\n\t\t\tProperty: "Size", "double", "",100')
 
247
                        file.write('\n\t\t\tProperty: "Look", "enum", "",1')
 
248
                
 
249
                return loc, rot, scale, matrix, matrix_rot
 
250
        
 
251
        def write_camera_switch():
 
252
                file.write('''
 
253
        Model: "Model::Camera Switcher", "CameraSwitcher" {
 
254
                Version: 232''')
 
255
                
 
256
                write_object_props()
 
257
                file.write('''
 
258
                        Property: "Color", "Color", "A",0.8,0.8,0.8
 
259
                        Property: "Camera Index", "Integer", "A+",100
 
260
                }
 
261
                MultiLayer: 0
 
262
                MultiTake: 1
 
263
                Hidden: "True"
 
264
                Shading: W
 
265
                Culling: "CullingOff"
 
266
                Version: 101
 
267
                Name: "Model::Camera Switcher"
 
268
                CameraId: 0
 
269
                CameraName: 100
 
270
                CameraIndexName: 
 
271
        }''')
 
272
        
 
273
        def write_camera_dummy(name, loc, near, far, proj_type, up):
 
274
                file.write('\n\tModel: "Model::%s", "Camera" {' % name )
 
275
                file.write('\n\t\tVersion: 232')
 
276
                write_object_props(None, loc)
 
277
                
 
278
                file.write('\n\t\t\tProperty: "Color", "Color", "A",0.8,0.8,0.8')
 
279
                file.write('\n\t\t\tProperty: "Roll", "Roll", "A+",0')
 
280
                file.write('\n\t\t\tProperty: "FieldOfView", "FieldOfView", "A+",40')
 
281
                file.write('\n\t\t\tProperty: "FieldOfViewX", "FieldOfView", "A+",1')
 
282
                file.write('\n\t\t\tProperty: "FieldOfViewY", "FieldOfView", "A+",1')
 
283
                file.write('\n\t\t\tProperty: "OpticalCenterX", "Real", "A+",0')
 
284
                file.write('\n\t\t\tProperty: "OpticalCenterY", "Real", "A+",0')
 
285
                file.write('\n\t\t\tProperty: "BackgroundColor", "Color", "A+",0.63,0.63,0.63')
 
286
                file.write('\n\t\t\tProperty: "TurnTable", "Real", "A+",0')
 
287
                file.write('\n\t\t\tProperty: "DisplayTurnTableIcon", "bool", "",1')
 
288
                file.write('\n\t\t\tProperty: "Motion Blur Intensity", "Real", "A+",1')
 
289
                file.write('\n\t\t\tProperty: "UseMotionBlur", "bool", "",0')
 
290
                file.write('\n\t\t\tProperty: "UseRealTimeMotionBlur", "bool", "",1')
 
291
                file.write('\n\t\t\tProperty: "ResolutionMode", "enum", "",0')
 
292
                file.write('\n\t\t\tProperty: "ApertureMode", "enum", "",2')
 
293
                file.write('\n\t\t\tProperty: "GateFit", "enum", "",0')
 
294
                file.write('\n\t\t\tProperty: "FocalLength", "Real", "A+",21.3544940948486')
 
295
                file.write('\n\t\t\tProperty: "CameraFormat", "enum", "",0')
 
296
                file.write('\n\t\t\tProperty: "AspectW", "double", "",320')
 
297
                file.write('\n\t\t\tProperty: "AspectH", "double", "",200')
 
298
                file.write('\n\t\t\tProperty: "PixelAspectRatio", "double", "",1')
 
299
                file.write('\n\t\t\tProperty: "UseFrameColor", "bool", "",0')
 
300
                file.write('\n\t\t\tProperty: "FrameColor", "ColorRGB", "",0.3,0.3,0.3')
 
301
                file.write('\n\t\t\tProperty: "ShowName", "bool", "",1')
 
302
                file.write('\n\t\t\tProperty: "ShowGrid", "bool", "",1')
 
303
                file.write('\n\t\t\tProperty: "ShowOpticalCenter", "bool", "",0')
 
304
                file.write('\n\t\t\tProperty: "ShowAzimut", "bool", "",1')
 
305
                file.write('\n\t\t\tProperty: "ShowTimeCode", "bool", "",0')
 
306
                file.write('\n\t\t\tProperty: "NearPlane", "double", "",%.6f' % near)
 
307
                file.write('\n\t\t\tProperty: "FarPlane", "double", "",%.6f' % far)
 
308
                file.write('\n\t\t\tProperty: "FilmWidth", "double", "",0.816')
 
309
                file.write('\n\t\t\tProperty: "FilmHeight", "double", "",0.612')
 
310
                file.write('\n\t\t\tProperty: "FilmAspectRatio", "double", "",1.33333333333333')
 
311
                file.write('\n\t\t\tProperty: "FilmSqueezeRatio", "double", "",1')
 
312
                file.write('\n\t\t\tProperty: "FilmFormatIndex", "enum", "",4')
 
313
                file.write('\n\t\t\tProperty: "ViewFrustum", "bool", "",1')
 
314
                file.write('\n\t\t\tProperty: "ViewFrustumNearFarPlane", "bool", "",0')
 
315
                file.write('\n\t\t\tProperty: "ViewFrustumBackPlaneMode", "enum", "",2')
 
316
                file.write('\n\t\t\tProperty: "BackPlaneDistance", "double", "",100')
 
317
                file.write('\n\t\t\tProperty: "BackPlaneDistanceMode", "enum", "",0')
 
318
                file.write('\n\t\t\tProperty: "ViewCameraToLookAt", "bool", "",1')
 
319
                file.write('\n\t\t\tProperty: "LockMode", "bool", "",0')
 
320
                file.write('\n\t\t\tProperty: "LockInterestNavigation", "bool", "",0')
 
321
                file.write('\n\t\t\tProperty: "FitImage", "bool", "",0')
 
322
                file.write('\n\t\t\tProperty: "Crop", "bool", "",0')
 
323
                file.write('\n\t\t\tProperty: "Center", "bool", "",1')
 
324
                file.write('\n\t\t\tProperty: "KeepRatio", "bool", "",1')
 
325
                file.write('\n\t\t\tProperty: "BackgroundMode", "enum", "",0')
 
326
                file.write('\n\t\t\tProperty: "BackgroundAlphaTreshold", "double", "",0.5')
 
327
                file.write('\n\t\t\tProperty: "ForegroundTransparent", "bool", "",1')
 
328
                file.write('\n\t\t\tProperty: "DisplaySafeArea", "bool", "",0')
 
329
                file.write('\n\t\t\tProperty: "SafeAreaDisplayStyle", "enum", "",1')
 
330
                file.write('\n\t\t\tProperty: "SafeAreaAspectRatio", "double", "",1.33333333333333')
 
331
                file.write('\n\t\t\tProperty: "Use2DMagnifierZoom", "bool", "",0')
 
332
                file.write('\n\t\t\tProperty: "2D Magnifier Zoom", "Real", "A+",100')
 
333
                file.write('\n\t\t\tProperty: "2D Magnifier X", "Real", "A+",50')
 
334
                file.write('\n\t\t\tProperty: "2D Magnifier Y", "Real", "A+",50')
 
335
                file.write('\n\t\t\tProperty: "CameraProjectionType", "enum", "",%i' % proj_type)
 
336
                file.write('\n\t\t\tProperty: "UseRealTimeDOFAndAA", "bool", "",0')
 
337
                file.write('\n\t\t\tProperty: "UseDepthOfField", "bool", "",0')
 
338
                file.write('\n\t\t\tProperty: "FocusSource", "enum", "",0')
 
339
                file.write('\n\t\t\tProperty: "FocusAngle", "double", "",3.5')
 
340
                file.write('\n\t\t\tProperty: "FocusDistance", "double", "",200')
 
341
                file.write('\n\t\t\tProperty: "UseAntialiasing", "bool", "",0')
 
342
                file.write('\n\t\t\tProperty: "AntialiasingIntensity", "double", "",0.77777')
 
343
                file.write('\n\t\t\tProperty: "UseAccumulationBuffer", "bool", "",0')
 
344
                file.write('\n\t\t\tProperty: "FrameSamplingCount", "int", "",7')
 
345
                file.write('\n\t\t}')
 
346
                file.write('\n\t\tMultiLayer: 0')
 
347
                file.write('\n\t\tMultiTake: 0')
 
348
                file.write('\n\t\tHidden: "True"')
 
349
                file.write('\n\t\tShading: Y')
 
350
                file.write('\n\t\tCulling: "CullingOff"')
 
351
                file.write('\n\t\tTypeFlags: "Camera"')
 
352
                file.write('\n\t\tGeometryVersion: 124')
 
353
                file.write('\n\t\tPosition: %.6f,%.6f,%.6f' % loc)
 
354
                file.write('\n\t\tUp: %i,%i,%i' % up)
 
355
                file.write('\n\t\tLookAt: 0,0,0')
 
356
                file.write('\n\t\tShowInfoOnMoving: 1')
 
357
                file.write('\n\t\tShowAudio: 0')
 
358
                file.write('\n\t\tAudioColor: 0,1,0')
 
359
                file.write('\n\t\tCameraOrthoZoom: 1')
 
360
                file.write('\n\t}')
 
361
        
 
362
        def write_camera_default():
 
363
                # This sucks but to match FBX converter its easier to
 
364
                # write the cameras though they are not needed.
 
365
                write_camera_dummy('Producer Perspective',      (0,71.3,287.5), 10, 4000, 0, (0,1,0))
 
366
                write_camera_dummy('Producer Top',                      (0,4000,0), 1, 30000, 1, (0,0,-1))
 
367
                write_camera_dummy('Producer Bottom',                   (0,-4000,0), 1, 30000, 1, (0,0,-1))
 
368
                write_camera_dummy('Producer Front',                    (0,0,4000), 1, 30000, 1, (0,1,0))
 
369
                write_camera_dummy('Producer Back',                     (0,0,-4000), 1, 30000, 1, (0,1,0))
 
370
                write_camera_dummy('Producer Right',                    (4000,0,0), 1, 30000, 1, (0,1,0))
 
371
                write_camera_dummy('Producer Left',                     (-4000,0,0), 1, 30000, 1, (0,1,0))
 
372
        
 
373
        def write_camera(ob, name):
 
374
                '''
 
375
                Write a blender camera
 
376
                '''
 
377
                render = sce.render
 
378
                width   = render.sizeX
 
379
                height  = render.sizeY
 
380
                aspect  = float(width)/height
 
381
                
 
382
                data = ob.data
 
383
                
 
384
                file.write('\n\tModel: "Model::%s", "Camera" {' % name )
 
385
                file.write('\n\t\tVersion: 232')
 
386
                loc, rot, scale, matrix, matrix_rot = write_object_props(ob)
 
387
                
 
388
                file.write('\n\t\t\tProperty: "Roll", "Roll", "A+",0')
 
389
                file.write('\n\t\t\tProperty: "FieldOfView", "FieldOfView", "A+",%.6f' % data.angle)
 
390
                file.write('\n\t\t\tProperty: "FieldOfViewX", "FieldOfView", "A+",1')
 
391
                file.write('\n\t\t\tProperty: "FieldOfViewY", "FieldOfView", "A+",1')
 
392
                file.write('\n\t\t\tProperty: "FocalLength", "Real", "A+",14.0323972702026')
 
393
                file.write('\n\t\t\tProperty: "OpticalCenterX", "Real", "A+",%.6f' % data.shiftX) # not sure if this is in the correct units?
 
394
                file.write('\n\t\t\tProperty: "OpticalCenterY", "Real", "A+",%.6f' % data.shiftY) # ditto 
 
395
                file.write('\n\t\t\tProperty: "BackgroundColor", "Color", "A+",0,0,0')
 
396
                file.write('\n\t\t\tProperty: "TurnTable", "Real", "A+",0')
 
397
                file.write('\n\t\t\tProperty: "DisplayTurnTableIcon", "bool", "",1')
 
398
                file.write('\n\t\t\tProperty: "Motion Blur Intensity", "Real", "A+",1')
 
399
                file.write('\n\t\t\tProperty: "UseMotionBlur", "bool", "",0')
 
400
                file.write('\n\t\t\tProperty: "UseRealTimeMotionBlur", "bool", "",1')
 
401
                file.write('\n\t\t\tProperty: "ResolutionMode", "enum", "",0')
 
402
                file.write('\n\t\t\tProperty: "ApertureMode", "enum", "",2')
 
403
                file.write('\n\t\t\tProperty: "GateFit", "enum", "",0')
 
404
                file.write('\n\t\t\tProperty: "CameraFormat", "enum", "",0')
 
405
                file.write('\n\t\t\tProperty: "AspectW", "double", "",%i' % width)
 
406
                file.write('\n\t\t\tProperty: "AspectH", "double", "",%i' % height)
 
407
                
 
408
                '''Camera aspect ratio modes.
 
409
                        0 If the ratio mode is eWINDOW_SIZE, both width and height values aren't relevant.
 
410
                        1 If the ratio mode is eFIXED_RATIO, the height value is set to 1.0 and the width value is relative to the height value.
 
411
                        2 If the ratio mode is eFIXED_RESOLUTION, both width and height values are in pixels.
 
412
                        3 If the ratio mode is eFIXED_WIDTH, the width value is in pixels and the height value is relative to the width value.
 
413
                        4 If the ratio mode is eFIXED_HEIGHT, the height value is in pixels and the width value is relative to the height value. 
 
414
                
 
415
                Definition at line 234 of file kfbxcamera.h. '''
 
416
                
 
417
                file.write('\n\t\t\tProperty: "PixelAspectRatio", "double", "",2')
 
418
                
 
419
                file.write('\n\t\t\tProperty: "UseFrameColor", "bool", "",0')
 
420
                file.write('\n\t\t\tProperty: "FrameColor", "ColorRGB", "",0.3,0.3,0.3')
 
421
                file.write('\n\t\t\tProperty: "ShowName", "bool", "",1')
 
422
                file.write('\n\t\t\tProperty: "ShowGrid", "bool", "",1')
 
423
                file.write('\n\t\t\tProperty: "ShowOpticalCenter", "bool", "",0')
 
424
                file.write('\n\t\t\tProperty: "ShowAzimut", "bool", "",1')
 
425
                file.write('\n\t\t\tProperty: "ShowTimeCode", "bool", "",0')
 
426
                file.write('\n\t\t\tProperty: "NearPlane", "double", "",%.6f' % data.clipStart)
 
427
                file.write('\n\t\t\tProperty: "FarPlane", "double", "",%.6f' % data.clipStart)
 
428
                file.write('\n\t\t\tProperty: "FilmWidth", "double", "",1.0')
 
429
                file.write('\n\t\t\tProperty: "FilmHeight", "double", "",1.0')
 
430
                file.write('\n\t\t\tProperty: "FilmAspectRatio", "double", "",%.6f' % aspect)
 
431
                file.write('\n\t\t\tProperty: "FilmSqueezeRatio", "double", "",1')
 
432
                file.write('\n\t\t\tProperty: "FilmFormatIndex", "enum", "",0')
 
433
                file.write('\n\t\t\tProperty: "ViewFrustum", "bool", "",1')
 
434
                file.write('\n\t\t\tProperty: "ViewFrustumNearFarPlane", "bool", "",0')
 
435
                file.write('\n\t\t\tProperty: "ViewFrustumBackPlaneMode", "enum", "",2')
 
436
                file.write('\n\t\t\tProperty: "BackPlaneDistance", "double", "",100')
 
437
                file.write('\n\t\t\tProperty: "BackPlaneDistanceMode", "enum", "",0')
 
438
                file.write('\n\t\t\tProperty: "ViewCameraToLookAt", "bool", "",1')
 
439
                file.write('\n\t\t\tProperty: "LockMode", "bool", "",0')
 
440
                file.write('\n\t\t\tProperty: "LockInterestNavigation", "bool", "",0')
 
441
                file.write('\n\t\t\tProperty: "FitImage", "bool", "",0')
 
442
                file.write('\n\t\t\tProperty: "Crop", "bool", "",0')
 
443
                file.write('\n\t\t\tProperty: "Center", "bool", "",1')
 
444
                file.write('\n\t\t\tProperty: "KeepRatio", "bool", "",1')
 
445
                file.write('\n\t\t\tProperty: "BackgroundMode", "enum", "",0')
 
446
                file.write('\n\t\t\tProperty: "BackgroundAlphaTreshold", "double", "",0.5')
 
447
                file.write('\n\t\t\tProperty: "ForegroundTransparent", "bool", "",1')
 
448
                file.write('\n\t\t\tProperty: "DisplaySafeArea", "bool", "",0')
 
449
                file.write('\n\t\t\tProperty: "SafeAreaDisplayStyle", "enum", "",1')
 
450
                file.write('\n\t\t\tProperty: "SafeAreaAspectRatio", "double", "",%.6f' % aspect)
 
451
                file.write('\n\t\t\tProperty: "Use2DMagnifierZoom", "bool", "",0')
 
452
                file.write('\n\t\t\tProperty: "2D Magnifier Zoom", "Real", "A+",100')
 
453
                file.write('\n\t\t\tProperty: "2D Magnifier X", "Real", "A+",50')
 
454
                file.write('\n\t\t\tProperty: "2D Magnifier Y", "Real", "A+",50')
 
455
                file.write('\n\t\t\tProperty: "CameraProjectionType", "enum", "",0')
 
456
                file.write('\n\t\t\tProperty: "UseRealTimeDOFAndAA", "bool", "",0')
 
457
                file.write('\n\t\t\tProperty: "UseDepthOfField", "bool", "",0')
 
458
                file.write('\n\t\t\tProperty: "FocusSource", "enum", "",0')
 
459
                file.write('\n\t\t\tProperty: "FocusAngle", "double", "",3.5')
 
460
                file.write('\n\t\t\tProperty: "FocusDistance", "double", "",200')
 
461
                file.write('\n\t\t\tProperty: "UseAntialiasing", "bool", "",0')
 
462
                file.write('\n\t\t\tProperty: "AntialiasingIntensity", "double", "",0.77777')
 
463
                file.write('\n\t\t\tProperty: "UseAccumulationBuffer", "bool", "",0')
 
464
                file.write('\n\t\t\tProperty: "FrameSamplingCount", "int", "",7')
 
465
                
 
466
                file.write('\n\t\t}')
 
467
                file.write('\n\t\tMultiLayer: 0')
 
468
                file.write('\n\t\tMultiTake: 0')
 
469
                file.write('\n\t\tShading: Y')
 
470
                file.write('\n\t\tCulling: "CullingOff"')
 
471
                file.write('\n\t\tTypeFlags: "Camera"')
 
472
                file.write('\n\t\tGeometryVersion: 124')
 
473
                file.write('\n\t\tPosition: %.6f,%.6f,%.6f' % loc)
 
474
                file.write('\n\t\tUp: %.6f,%.6f,%.6f' % tuple(Blender.Mathutils.Vector(0,1,0) * matrix_rot) )
 
475
                file.write('\n\t\tLookAt: %.6f,%.6f,%.6f' % tuple(Blender.Mathutils.Vector(0,0,-1)*matrix_rot) )
 
476
                
 
477
                #file.write('\n\t\tUp: 0,0,0' )
 
478
                #file.write('\n\t\tLookAt: 0,0,0' )
 
479
                
 
480
                file.write('\n\t\tShowInfoOnMoving: 1')
 
481
                file.write('\n\t\tShowAudio: 0')
 
482
                file.write('\n\t\tAudioColor: 0,1,0')
 
483
                file.write('\n\t\tCameraOrthoZoom: 1')
 
484
                file.write('\n\t}')
 
485
        
 
486
        def write_light(ob, name):
 
487
                light = ob.data
 
488
                file.write('\n\tModel: "Model::%s", "Light" {' % name)
 
489
                file.write('\n\t\tVersion: 232')
 
490
                
 
491
                write_object_props(ob)
 
492
                
 
493
                # Why are these values here twice?????? - oh well, follow the holy sdk's output
 
494
                
 
495
                # Blender light types match FBX's, funny coincidence, we just need to
 
496
                # be sure that all unsupported types are made into a point light
 
497
                #ePOINT, 
 
498
                #eDIRECTIONAL
 
499
                #eSPOT
 
500
                light_type = light.type
 
501
                if light_type > 3: light_type = 0
 
502
                        
 
503
                file.write('\n\t\t\tProperty: "LightType", "enum", "",%i' % light_type)
 
504
                file.write('\n\t\t\tProperty: "CastLightOnObject", "bool", "",1')
 
505
                file.write('\n\t\t\tProperty: "DrawVolumetricLight", "bool", "",1')
 
506
                file.write('\n\t\t\tProperty: "DrawGroundProjection", "bool", "",1')
 
507
                file.write('\n\t\t\tProperty: "DrawFrontFacingVolumetricLight", "bool", "",0')
 
508
                file.write('\n\t\t\tProperty: "GoboProperty", "object", ""')
 
509
                file.write('\n\t\t\tProperty: "Color", "Color", "A+",1,1,1')
 
510
                file.write('\n\t\t\tProperty: "Intensity", "Intensity", "A+",%.2f' % (light.energy*100))
 
511
                file.write('\n\t\t\tProperty: "Cone angle", "Cone angle", "A+",%.2f' % light.spotSize)
 
512
                file.write('\n\t\t\tProperty: "Fog", "Fog", "A+",50')
 
513
                file.write('\n\t\t\tProperty: "Color", "Color", "A",%.2f,%.2f,%.2f' % tuple(light.col))
 
514
                file.write('\n\t\t\tProperty: "Intensity", "Intensity", "A+",%.2f' % (light.energy*100))
 
515
                file.write('\n\t\t\tProperty: "Cone angle", "Cone angle", "A+",%.2f' % light.spotSize)
 
516
                file.write('\n\t\t\tProperty: "Fog", "Fog", "A+",50')
 
517
                file.write('\n\t\t\tProperty: "LightType", "enum", "",%i' % light_type)
 
518
                file.write('\n\t\t\tProperty: "CastLightOnObject", "bool", "",1')
 
519
                file.write('\n\t\t\tProperty: "DrawGroundProjection", "bool", "",1')
 
520
                file.write('\n\t\t\tProperty: "DrawFrontFacingVolumetricLight", "bool", "",0')
 
521
                file.write('\n\t\t\tProperty: "DrawVolumetricLight", "bool", "",1')
 
522
                file.write('\n\t\t\tProperty: "GoboProperty", "object", ""')
 
523
                file.write('\n\t\t\tProperty: "DecayType", "enum", "",0')
 
524
                file.write('\n\t\t\tProperty: "DecayStart", "double", "",%.2f' % light.dist)
 
525
                file.write('\n\t\t\tProperty: "EnableNearAttenuation", "bool", "",0')
 
526
                file.write('\n\t\t\tProperty: "NearAttenuationStart", "double", "",0')
 
527
                file.write('\n\t\t\tProperty: "NearAttenuationEnd", "double", "",0')
 
528
                file.write('\n\t\t\tProperty: "EnableFarAttenuation", "bool", "",0')
 
529
                file.write('\n\t\t\tProperty: "FarAttenuationStart", "double", "",0')
 
530
                file.write('\n\t\t\tProperty: "FarAttenuationEnd", "double", "",0')
 
531
                file.write('\n\t\t\tProperty: "CastShadows", "bool", "",0')
 
532
                file.write('\n\t\t\tProperty: "ShadowColor", "ColorRGBA", "",0,0,0,1')
 
533
                file.write('\n\t\t}')
 
534
                file.write('\n\t\tMultiLayer: 0')
 
535
                file.write('\n\t\tMultiTake: 0')
 
536
                file.write('\n\t\tShading: Y')
 
537
                file.write('\n\t\tCulling: "CullingOff"')
 
538
                file.write('\n\t\tTypeFlags: "Light"')
 
539
                file.write('\n\t\tGeometryVersion: 124')
 
540
                file.write('\n\t}')
 
541
        
 
542
        # Material Settings
 
543
        if world:
 
544
                world_amb = world.getAmb()
 
545
        else:
 
546
                world_amb = (0,0,0) # Default value
 
547
        
 
548
        
 
549
        def write_material(matname, mat):
 
550
                file.write('\n\tMaterial: "Material::%s", "" {' % matname)
 
551
                
 
552
                # Todo, add more material Properties.
 
553
                if mat:
 
554
                        mat_cold = tuple(mat.rgbCol)
 
555
                        mat_cols = tuple(mat.specCol)
 
556
                        #mat_colm = tuple(mat.mirCol) # we wont use the mirror color
 
557
                        mat_colamb = tuple([c for c in world_amb])
 
558
                        
 
559
                        mat_dif = mat.ref
 
560
                        mat_amb = mat.amb
 
561
                        mat_hard = (float(mat.hard)-1)/5.10
 
562
                        mat_spec = mat.spec/2.0
 
563
                        mat_alpha = mat.alpha
 
564
                        mat_shadeless = mat.mode & Blender.Material.Modes.SHADELESS
 
565
                        if mat_shadeless:
 
566
                                mat_shader = 'Lambert'
 
567
                        else:
 
568
                                if mat.diffuseShader == Blender.Material.Shaders.DIFFUSE_LAMBERT:
 
569
                                        mat_shader = 'Lambert'
 
570
                                else:
 
571
                                        mat_shader = 'Phong'
 
572
                else:
 
573
                        mat_cols = mat_cold = 0.8, 0.8, 0.8
 
574
                        mat_colamb = 0.0,0.0,0.0
 
575
                        # mat_colm 
 
576
                        mat_dif = 1.0
 
577
                        mat_amb = 0.5
 
578
                        mat_hard = 20.0
 
579
                        mat_spec = 0.2
 
580
                        mat_alpha = 1.0
 
581
                        mat_shadeless = False
 
582
                        mat_shader = 'Phong'
 
583
                
 
584
                file.write('\n\t\tVersion: 102')
 
585
                file.write('\n\t\tShadingModel: "%s"' % mat_shader.lower())
 
586
                file.write('\n\t\tMultiLayer: 0')
 
587
                
 
588
                file.write('\n\t\tProperties60:  {')
 
589
                file.write('\n\t\t\tProperty: "ShadingModel", "KString", "", "%s"' % mat_shader)
 
590
                file.write('\n\t\t\tProperty: "MultiLayer", "bool", "",0')
 
591
                file.write('\n\t\t\tProperty: "EmissiveColor", "ColorRGB", "",0,0,0')
 
592
                file.write('\n\t\t\tProperty: "EmissiveFactor", "double", "",1')
 
593
                
 
594
                file.write('\n\t\t\tProperty: "AmbientColor", "ColorRGB", "",%.1f,%.1f,%.1f' % mat_colamb)
 
595
                file.write('\n\t\t\tProperty: "AmbientFactor", "double", "",%.1f' % mat_amb)
 
596
                file.write('\n\t\t\tProperty: "DiffuseColor", "ColorRGB", "",%.1f,%.1f,%.1f' % mat_cold)
 
597
                file.write('\n\t\t\tProperty: "DiffuseFactor", "double", "",%.1f' % mat_dif)
 
598
                file.write('\n\t\t\tProperty: "Bump", "Vector3D", "",0,0,0')
 
599
                file.write('\n\t\t\tProperty: "TransparentColor", "ColorRGB", "",1,1,1')
 
600
                file.write('\n\t\t\tProperty: "TransparencyFactor", "double", "",0')
 
601
                if not mat_shadeless:
 
602
                        file.write('\n\t\t\tProperty: "SpecularColor", "ColorRGB", "",%.1f,%.1f,%.1f' % mat_cols)
 
603
                        file.write('\n\t\t\tProperty: "SpecularFactor", "double", "",%.1f' % mat_spec)
 
604
                        file.write('\n\t\t\tProperty: "ShininessExponent", "double", "",80.0')
 
605
                        file.write('\n\t\t\tProperty: "ReflectionColor", "ColorRGB", "",0,0,0')
 
606
                        file.write('\n\t\t\tProperty: "ReflectionFactor", "double", "",1')
 
607
                file.write('\n\t\t\tProperty: "Emissive", "Vector3D", "",0,0,0')
 
608
                file.write('\n\t\t\tProperty: "Ambient", "Vector3D", "",%.1f,%.1f,%.1f' % mat_colamb)
 
609
                file.write('\n\t\t\tProperty: "Diffuse", "Vector3D", "",%.1f,%.1f,%.1f' % mat_cold)
 
610
                if not mat_shadeless:
 
611
                        file.write('\n\t\t\tProperty: "Specular", "Vector3D", "",%.1f,%.1f,%.1f' % mat_cols)
 
612
                        file.write('\n\t\t\tProperty: "Shininess", "double", "",%.1f' % mat_hard)
 
613
                file.write('\n\t\t\tProperty: "Opacity", "double", "",%.1f' % mat_alpha)
 
614
                if not mat_shadeless:
 
615
                        file.write('\n\t\t\tProperty: "Reflectivity", "double", "",0')
 
616
 
 
617
                file.write('\n\t\t}')
 
618
                file.write('\n\t}')
 
619
        
 
620
        def write_video(texname, tex):
 
621
                # Same as texture really!
 
622
                file.write('\n\tVideo: "Video::%s", "Clip" {' % texname)
 
623
                
 
624
                file.write('''
 
625
                Type: "Clip"
 
626
                Properties60:  {
 
627
                        Property: "FrameRate", "double", "",0
 
628
                        Property: "LastFrame", "int", "",0
 
629
                        Property: "Width", "int", "",0
 
630
                        Property: "Height", "int", "",0''')
 
631
                if tex:
 
632
                        fname = tex.filename
 
633
                        fname_strip = strip_path(fname)
 
634
                else:
 
635
                        fname = fname_strip = ''
 
636
                
 
637
                file.write('\n\t\t\tProperty: "Path", "charptr", "", "%s"' % fname_strip)
 
638
                
 
639
                
 
640
                file.write('''
 
641
                        Property: "StartFrame", "int", "",0
 
642
                        Property: "StopFrame", "int", "",0
 
643
                        Property: "PlaySpeed", "double", "",1
 
644
                        Property: "Offset", "KTime", "",0
 
645
                        Property: "InterlaceMode", "enum", "",0
 
646
                        Property: "FreeRunning", "bool", "",0
 
647
                        Property: "Loop", "bool", "",0
 
648
                        Property: "AccessMode", "enum", "",0
 
649
                }
 
650
                UseMipMap: 0''')
 
651
                
 
652
                file.write('\n\t\tFilename: "%s"' % fname_strip)
 
653
                if fname_strip: fname_strip = '/' + fname_strip
 
654
                file.write('\n\t\tRelativeFilename: "fbx%s"' % fname_strip) # make relative
 
655
                file.write('\n\t}')
 
656
 
 
657
        
 
658
        def write_texture(texname, tex, num):
 
659
                # if tex == None then this is a dummy tex
 
660
                file.write('\n\tTexture: "Texture::%s", "TextureVideoClip" {' % texname)
 
661
                file.write('\n\t\tType: "TextureVideoClip"')
 
662
                file.write('\n\t\tVersion: 202')
 
663
                # TODO, rare case _empty_ exists as a name.
 
664
                file.write('\n\t\tTextureName: "Texture::%s"' % texname)
 
665
                
 
666
                file.write('''
 
667
                Properties60:  {
 
668
                        Property: "Translation", "Vector", "A+",0,0,0
 
669
                        Property: "Rotation", "Vector", "A+",0,0,0
 
670
                        Property: "Scaling", "Vector", "A+",1,1,1''')
 
671
                file.write('\n\t\t\tProperty: "Texture alpha", "Number", "A+",%i' % num)
 
672
                file.write('''
 
673
                        Property: "TextureTypeUse", "enum", "",0
 
674
                        Property: "CurrentTextureBlendMode", "enum", "",1
 
675
                        Property: "UseMaterial", "bool", "",0
 
676
                        Property: "UseMipMap", "bool", "",0
 
677
                        Property: "CurrentMappingType", "enum", "",0
 
678
                        Property: "UVSwap", "bool", "",0
 
679
                        Property: "WrapModeU", "enum", "",0
 
680
                        Property: "WrapModeV", "enum", "",0
 
681
                        Property: "TextureRotationPivot", "Vector3D", "",0,0,0
 
682
                        Property: "TextureScalingPivot", "Vector3D", "",0,0,0
 
683
                        Property: "VideoProperty", "object", ""
 
684
                }''')
 
685
                
 
686
                file.write('\n\t\tMedia: "Video::%s"' % texname)
 
687
                if tex:
 
688
                        fname = tex.filename
 
689
                        file.write('\n\t\tFileName: "%s"' % strip_path(fname))
 
690
                        file.write('\n\t\tRelativeFilename: "fbx/%s"' % strip_path(fname)) # need some make relative command
 
691
                else:
 
692
                        file.write('\n\t\tFileName: ""')
 
693
                        file.write('\n\t\tRelativeFilename: "fbx"')
 
694
                
 
695
                file.write('''
 
696
                ModelUVTranslation: 0,0
 
697
                ModelUVScaling: 1,1
 
698
                Texture_Alpha_Source: "None"
 
699
                Cropping: 0,0,0,0
 
700
        }''')
 
701
        
 
702
        ob_meshes = []
 
703
        ob_lights = []
 
704
        ob_cameras = []
 
705
        materials = {}
 
706
        textures = {}
 
707
        armatures = [] # We should export standalone armatures also
 
708
        armatures_totbones = 0 # we need this because each bone is a model
 
709
        for ob_base in sce.objects.context:
 
710
                for ob, mtx in BPyObject.getDerivedObjects(ob_base):
 
711
                        #for ob in [ob_base,]:
 
712
                        ob_type = ob.type
 
713
                        if ob_type == 'Camera':
 
714
                                ob_cameras.append((sane_obname(ob), ob))
 
715
                        elif ob_type == 'Lamp':
 
716
                                ob_lights.append((sane_obname(ob), ob))
 
717
                        
 
718
                        else:
 
719
                                if ob_type == 'Mesh':   me = ob.getData(mesh=1)
 
720
                                else:                                   me = BPyMesh.getMeshFromObject(ob)
 
721
                                
 
722
                                if me:
 
723
                                        mats = me.materials
 
724
                                        for mat in mats:
 
725
                                                # 2.44 use mat.lib too for uniqueness
 
726
                                                if mat: materials[mat.name] = mat
 
727
                                        
 
728
                                        if me.faceUV:
 
729
                                                uvlayer_orig = me.activeUVLayer
 
730
                                                for uvlayer in me.getUVLayerNames():
 
731
                                                        me.activeUVLayer = uvlayer
 
732
                                                        for f in me.faces:
 
733
                                                                img = f.image
 
734
                                                                if img: textures[img.name] = img
 
735
                                                        
 
736
                                                        me.activeUVLayer = uvlayer_orig
 
737
                                        
 
738
                                        arm = BPyObject.getObjectArmature(ob)
 
739
                                        
 
740
                                        if arm:
 
741
                                                armname = sane_obname(arm)
 
742
                                                bones = arm.bones.values()
 
743
                                                armatures_totbones += len(bones)
 
744
                                                armatures.append((arm, armname, bones))
 
745
                                        else:
 
746
                                                armname = None
 
747
                                        
 
748
                                        #### me.transform(ob.matrixWorld) # Export real ob coords.
 
749
                                        #### High Quality, not realy needed for now.
 
750
                                        #BPyMesh.meshCalcNormals(me) # high quality normals nice for realtime engines.
 
751
                                        ob_meshes.append( (sane_obname(ob), ob, mtx, me, mats, arm, armname) )
 
752
        
 
753
        del ob_type
 
754
        
 
755
        materials = [(sane_matname(mat), mat) for mat in materials.itervalues()]
 
756
        textures = [(sane_texname(img), img) for img in textures.itervalues()]
 
757
        materials.sort() # sort by name
 
758
        textures.sort()
 
759
        
 
760
        if not materials:
 
761
                materials = [('null', None)]
 
762
        
 
763
        material_mapping = {} # blen name : index
 
764
        if textures:
 
765
                texture_mapping_local = {None:0} # ditto
 
766
                i = 0
 
767
                for texname, tex in textures:
 
768
                        texture_mapping_local[tex.name] = i
 
769
                        i+=1
 
770
                textures.insert(0, ('_empty_', None))
 
771
        
 
772
        i = 0
 
773
        for matname, mat in materials:
 
774
                if mat: mat = mat.name
 
775
                material_mapping[mat] = i
 
776
                i+=1
 
777
        
 
778
        camera_count = 8
 
779
        file.write('''
 
780
 
 
781
; Object definitions
 
782
;------------------------------------------------------------------
 
783
 
 
784
Definitions:  {
 
785
        Version: 100
 
786
        Count: %i''' % (\
 
787
                1+1+camera_count+\
 
788
                len(ob_meshes)+\
 
789
                len(ob_lights)+\
 
790
                len(ob_cameras)+\
 
791
                len(armatures)+\
 
792
                armatures_totbones+\
 
793
                len(materials)+\
 
794
                (len(textures)*2))) # add 1 for the root model 1 for global settings
 
795
        
 
796
        file.write('''
 
797
        ObjectType: "Model" {
 
798
                Count: %i
 
799
        }''' % (\
 
800
                1+camera_count+\
 
801
                len(ob_meshes)+\
 
802
                len(ob_lights)+\
 
803
                len(ob_cameras)+\
 
804
                len(armatures)+\
 
805
                armatures_totbones)) # add 1 for the root model
 
806
        
 
807
        file.write('''
 
808
        ObjectType: "Geometry" {
 
809
                Count: %i
 
810
        }''' % len(ob_meshes))
 
811
        
 
812
        if materials:
 
813
                file.write('''
 
814
        ObjectType: "Material" {
 
815
                Count: %i
 
816
        }''' % len(materials))
 
817
        
 
818
        if textures:
 
819
                file.write('''
 
820
        ObjectType: "Texture" {
 
821
                Count: %i
 
822
        }''' % len(textures)) # add 1 for an empty tex
 
823
                file.write('''
 
824
        ObjectType: "Video" {
 
825
                Count: %i
 
826
        }''' % len(textures)) # add 1 for an empty tex
 
827
        
 
828
        file.write('''
 
829
        ObjectType: "GlobalSettings" {
 
830
                Count: 1
 
831
        }
 
832
}
 
833
''')
 
834
        
 
835
        file.write(\
 
836
'''
 
837
; Object properties
 
838
;------------------------------------------------------------------
 
839
 
 
840
Objects:  {''')
 
841
        
 
842
        # To comply with other FBX FILES
 
843
        write_camera_switch()
 
844
        
 
845
        # Write the null object
 
846
        file.write('''
 
847
        Model: "Model::blend_root", "Null" {
 
848
                Version: 232''')
 
849
        write_object_props()
 
850
        
 
851
        file.write('''
 
852
                }
 
853
                MultiLayer: 0
 
854
                MultiTake: 1
 
855
                Shading: Y
 
856
                Culling: "CullingOff"
 
857
                TypeFlags: "Null"
 
858
        }''')
 
859
        
 
860
        for obname, ob in ob_cameras:
 
861
                write_camera(ob, obname)
 
862
 
 
863
        for obname, ob in ob_lights:
 
864
                write_light(ob, obname)
 
865
        
 
866
        for obname, ob, mtx, me, mats, arm, armname in ob_meshes:
 
867
                file.write('\n\tModel: "Model::%s", "Mesh" {' % sane_obname(ob))
 
868
                file.write('\n\t\tVersion: 232') # newline is added in write_object_props
 
869
                write_object_props(ob, None, mtx)
 
870
                file.write('\n\t\t}')
 
871
                file.write('\n\t\tMultiLayer: 0')
 
872
                file.write('\n\t\tMultiTake: 1')
 
873
                file.write('\n\t\tShading: Y')
 
874
                file.write('\n\t\tCulling: "CullingOff"')
 
875
                
 
876
                # Write the Real Mesh data here
 
877
                file.write('\n\t\tVertices: ')
 
878
                i=-1
 
879
                for v in me.verts:
 
880
                        if i==-1:
 
881
                                file.write('%.6f,%.6f,%.6f' % tuple(v.co))
 
882
                                i=0
 
883
                        else:
 
884
                                if i==7:
 
885
                                        file.write('\n\t\t')
 
886
                                        i=0
 
887
                                file.write(',%.6f,%.6f,%.6f'% tuple(v.co))
 
888
                        i+=1
 
889
                file.write('\n\t\tPolygonVertexIndex: ')
 
890
                i=-1
 
891
                for f in me.faces:
 
892
                        fi = [v.index for v in f]
 
893
                        # flip the last index, odd but it looks like
 
894
                        # this is how fbx tells one face from another
 
895
                        fi[-1] = -(fi[-1]+1)
 
896
                        fi = tuple(fi)
 
897
                        if i==-1:
 
898
                                if len(f) == 3:         file.write('%i,%i,%i' % fi )
 
899
                                else:                           file.write('%i,%i,%i,%i' % fi )
 
900
                                i=0
 
901
                        else:
 
902
                                if i==13:
 
903
                                        file.write('\n\t\t')
 
904
                                        i=0
 
905
                                if len(f) == 3:         file.write(',%i,%i,%i' % fi )
 
906
                                else:                           file.write(',%i,%i,%i,%i' % fi )
 
907
                        i+=1
 
908
                
 
909
                ed_val = [None, None]
 
910
                LOOSE = Blender.Mesh.EdgeFlags.LOOSE
 
911
                for ed in me.edges:
 
912
                        if ed.flag & LOOSE:
 
913
                                ed_val[0] = ed.v1.index
 
914
                                ed_val[1] = -(ed.v2.index+1)
 
915
                                if i==-1:
 
916
                                        file.write('%i,%i' % tuple(ed_val) )
 
917
                                        i=0
 
918
                                else:
 
919
                                        if i==13:
 
920
                                                file.write('\n\t\t')
 
921
                                                i=0
 
922
                                        file.write(',%i,%i' % tuple(ed_val) )
 
923
                                i+=1
 
924
                del LOOSE
 
925
                
 
926
                file.write('\n\t\tGeometryVersion: 124')
 
927
                
 
928
                file.write('''
 
929
                LayerElementNormal: 0 {
 
930
                        Version: 101
 
931
                        Name: ""
 
932
                        MappingInformationType: "ByVertice"
 
933
                        ReferenceInformationType: "Direct"
 
934
                        Normals: ''')
 
935
 
 
936
                i=-1
 
937
                for v in me.verts:
 
938
                        if i==-1:
 
939
                                file.write('%.15f,%.15f,%.15f' % tuple(v.no))
 
940
                                i=0
 
941
                        else:
 
942
                                if i==2:
 
943
                                        file.write('\n                   ')
 
944
                                        i=0
 
945
                                file.write(',%.15f,%.15f,%.15f' % tuple(v.no))
 
946
                        i+=1
 
947
                file.write('\n\t\t}')
 
948
                
 
949
                
 
950
                # Write VertexColor Layers
 
951
                collayers = []
 
952
                if me.vertexColors:
 
953
                        collayers = me.getColorLayerNames()
 
954
                        collayer_orig = me.activeColorLayer
 
955
                        for colindex, collayer in enumerate(collayers):
 
956
                                me.activeColorLayer = collayer
 
957
                                file.write('\n\t\tLayerElementColor: %i {' % colindex)
 
958
                                file.write('\n\t\t\tVersion: 101')
 
959
                                file.write('\n\t\t\tName: "%s"' % collayer)
 
960
                                
 
961
                                file.write('''
 
962
                        MappingInformationType: "ByPolygonVertex"
 
963
                        ReferenceInformationType: "IndexToDirect"
 
964
                        Colors: ''')
 
965
                        
 
966
                                i = -1
 
967
                                ii = 0 # Count how many Colors we write
 
968
                                
 
969
                                for f in me.faces:
 
970
                                        for col in f.col:
 
971
                                                if i==-1:
 
972
                                                        file.write('%i,%i,%i' % (col[0], col[1], col[2]))
 
973
                                                        i=0
 
974
                                                else:
 
975
                                                        if i==7:
 
976
                                                                file.write('\n\t\t\t\t')
 
977
                                                                i=0
 
978
                                                        file.write(',%i,%i,%i' % (col[0], col[1], col[2]))
 
979
                                                i+=1
 
980
                                                ii+=1 # One more Color
 
981
                                
 
982
                                file.write('\n\t\t\tColorIndex: ')
 
983
                                i = -1
 
984
                                for j in xrange(ii):
 
985
                                        if i == -1:
 
986
                                                file.write('%i' % j)
 
987
                                                i=0
 
988
                                        else:
 
989
                                                if i==55:
 
990
                                                        file.write('\n\t\t\t\t')
 
991
                                                        i=0
 
992
                                                file.write(',%i' % j)
 
993
                                        i+=1
 
994
                                
 
995
                                file.write('\n\t\t}')
 
996
                
 
997
                
 
998
                
 
999
                # Write UV and texture layers.
 
1000
                uvlayers = []
 
1001
                if me.faceUV:
 
1002
                        uvlayers = me.getUVLayerNames()
 
1003
                        uvlayer_orig = me.activeUVLayer
 
1004
                        for uvindex, uvlayer in enumerate(uvlayers):
 
1005
                                me.activeUVLayer = uvlayer
 
1006
                                file.write('\n\t\tLayerElementUV: %i {' % uvindex)
 
1007
                                file.write('\n\t\t\tVersion: 101')
 
1008
                                file.write('\n\t\t\tName: "%s"' % uvlayer)
 
1009
                                
 
1010
                                file.write('''
 
1011
                        MappingInformationType: "ByPolygonVertex"
 
1012
                        ReferenceInformationType: "IndexToDirect"
 
1013
                        UV: ''')
 
1014
                        
 
1015
                                i = -1
 
1016
                                ii = 0 # Count how many UVs we write
 
1017
                                
 
1018
                                for f in me.faces:
 
1019
                                        for uv in f.uv:
 
1020
                                                if i==-1:
 
1021
                                                        file.write('%.6f,%.6f' % tuple(uv))
 
1022
                                                        i=0
 
1023
                                                else:
 
1024
                                                        if i==7:
 
1025
                                                                file.write('\n                   ')
 
1026
                                                                i=0
 
1027
                                                        file.write(',%.6f,%.6f' % tuple(uv))
 
1028
                                                i+=1
 
1029
                                                ii+=1 # One more UV
 
1030
                                
 
1031
                                file.write('\n\t\t\tUVIndex: ')
 
1032
                                i = -1
 
1033
                                for j in xrange(ii):
 
1034
                                        if i == -1:
 
1035
                                                file.write('%i'  % j)
 
1036
                                                i=0
 
1037
                                        else:
 
1038
                                                if i==55:
 
1039
                                                        file.write('\n\t\t\t\t')
 
1040
                                                        i=0
 
1041
                                                file.write(',%i' % j)
 
1042
                                        i+=1
 
1043
                                
 
1044
                                file.write('\n\t\t}')
 
1045
                                
 
1046
                                if textures:
 
1047
                                        file.write('\n\t\tLayerElementTexture: %i {' % uvindex)
 
1048
                                        file.write('\n\t\t\tVersion: 101')
 
1049
                                        file.write('\n\t\t\tName: "%s"' % uvlayer)
 
1050
                                        
 
1051
                                        file.write('''
 
1052
                        MappingInformationType: "ByPolygon"
 
1053
                        ReferenceInformationType: "IndexToDirect"
 
1054
                        BlendMode: "Translucent"
 
1055
                        TextureAlpha: 1
 
1056
                        TextureId: ''')
 
1057
                                        i=-1
 
1058
                                        for f in me.faces:
 
1059
                                                img_key = f.image
 
1060
                                                if img_key: img_key = img_key.name
 
1061
                                                
 
1062
                                                if i==-1:
 
1063
                                                        i=0
 
1064
                                                        file.write( '%s' % texture_mapping_local[img_key])
 
1065
                                                else:
 
1066
                                                        if i==55:
 
1067
                                                                file.write('\n                   ')
 
1068
                                                                i=0
 
1069
                                                        
 
1070
                                                        file.write(',%s' % texture_mapping_local[img_key])
 
1071
                                                i+=1
 
1072
                                else:
 
1073
                                        file.write('''
 
1074
                LayerElementTexture: 0 {
 
1075
                        Version: 101
 
1076
                        Name: ""
 
1077
                        MappingInformationType: "NoMappingInformation"
 
1078
                        ReferenceInformationType: "IndexToDirect"
 
1079
                        BlendMode: "Translucent"
 
1080
                        TextureAlpha: 1
 
1081
                        TextureId: ''')
 
1082
                                file.write('\n\t\t}')
 
1083
                        
 
1084
                        me.activeUVLayer = uvlayer_orig
 
1085
                        
 
1086
                # Done with UV/textures.
 
1087
                
 
1088
                if materials:
 
1089
                        file.write('''
 
1090
                LayerElementMaterial: 0 {
 
1091
                        Version: 101
 
1092
                        Name: ""
 
1093
                        MappingInformationType: "ByPolygon"
 
1094
                        ReferenceInformationType: "IndexToDirect"
 
1095
                        Materials: ''')
 
1096
                        
 
1097
                        # Build a material mapping for this 
 
1098
                        material_mapping_local = {} # local-index : global index.
 
1099
                        for i, mat in enumerate(mats):
 
1100
                                if mat:
 
1101
                                        material_mapping_local[i] = material_mapping[mat.name]
 
1102
                                else:
 
1103
                                        material_mapping_local[i] = 0 # None material is zero for now.
 
1104
                        
 
1105
                        if not material_mapping_local:
 
1106
                                material_mapping_local[0] = 0
 
1107
                        
 
1108
                        len_material_mapping_local = len(material_mapping_local)
 
1109
                        
 
1110
                        i=-1
 
1111
                        for f in me.faces:
 
1112
                                f_mat = f.mat
 
1113
                                if f_mat >= len_material_mapping_local:
 
1114
                                        f_mat = 0
 
1115
                                
 
1116
                                if i==-1:
 
1117
                                        i=0
 
1118
                                        file.write( '%s' % material_mapping_local[f_mat])
 
1119
                                else:
 
1120
                                        if i==55:
 
1121
                                                file.write('\n\t\t\t\t')
 
1122
                                                i=0
 
1123
                                        
 
1124
                                        file.write(',%s' % material_mapping_local[f_mat])
 
1125
                                i+=1
 
1126
                        
 
1127
                        file.write('\n\t\t}')
 
1128
                
 
1129
                file.write('''
 
1130
                Layer: 0 {
 
1131
                        Version: 100
 
1132
                        LayerElement:  {
 
1133
                                Type: "LayerElementNormal"
 
1134
                                TypedIndex: 0
 
1135
                        }''')
 
1136
                
 
1137
                if materials:
 
1138
                        file.write('''
 
1139
                        LayerElement:  {
 
1140
                                Type: "LayerElementMaterial"
 
1141
                                TypedIndex: 0
 
1142
                        }''')
 
1143
                        
 
1144
                # Always write this
 
1145
                if textures:
 
1146
                        file.write('''
 
1147
                        LayerElement:  {
 
1148
                                Type: "LayerElementTexture"
 
1149
                                TypedIndex: 0
 
1150
                        }''')
 
1151
                
 
1152
                if me.vertexColors:
 
1153
                        file.write('''
 
1154
                        LayerElement:  {
 
1155
                                Type: "LayerElementColor"
 
1156
                                TypedIndex: 0
 
1157
                        }''')
 
1158
                
 
1159
                if me.faceUV:
 
1160
                        file.write('''
 
1161
                        LayerElement:  {
 
1162
                                Type: "LayerElementUV"
 
1163
                                TypedIndex: 0
 
1164
                        }''')
 
1165
                
 
1166
                
 
1167
                file.write('\n\t\t}')
 
1168
                
 
1169
                if len(uvlayers) > 1:
 
1170
                        for i in xrange(1, len(uvlayers)):
 
1171
                                
 
1172
                                file.write('\n\t\tLayer: %i {' % i)
 
1173
                                file.write('\n\t\t\tVersion: 100')
 
1174
                                
 
1175
                                file.write('''
 
1176
                        LayerElement:  {
 
1177
                                Type: "LayerElementUV"''')
 
1178
                                
 
1179
                                file.write('\n\t\t\t\tTypedIndex: %i' % i)
 
1180
                                file.write('\n\t\t\t}')
 
1181
                                
 
1182
                                if textures:
 
1183
                                        
 
1184
                                        file.write('''
 
1185
                        LayerElement:  {
 
1186
                                Type: "LayerElementTexture"''')
 
1187
                                        
 
1188
                                        file.write('\n\t\t\t\tTypedIndex: %i' % i)
 
1189
                                        file.write('\n\t\t\t}')
 
1190
                                
 
1191
                                file.write('\n\t\t}')
 
1192
                
 
1193
                if len(collayers) > 1:
 
1194
                        # Take into account any UV layers
 
1195
                        layer_offset = 0
 
1196
                        if uvlayers: layer_offset = len(uvlayers)-1
 
1197
                        
 
1198
                        for i in xrange(layer_offset, len(collayers)+layer_offset):
 
1199
                                file.write('\n\t\tLayer: %i {' % i)
 
1200
                                file.write('\n\t\t\tVersion: 100')
 
1201
                                
 
1202
                                file.write('''
 
1203
                        LayerElement:  {
 
1204
                                Type: "LayerElementColor"''')
 
1205
                                
 
1206
                                file.write('\n\t\t\t\tTypedIndex: %i' % i)
 
1207
                                file.write('\n\t\t\t}')
 
1208
                                file.write('\n\t\t}')
 
1209
                file.write('\n\t}')     
 
1210
        
 
1211
        write_camera_default()
 
1212
        
 
1213
        for matname, mat in materials:
 
1214
                write_material(matname, mat)
 
1215
        
 
1216
        # each texture uses a video, odd
 
1217
        for texname, tex in textures:
 
1218
                write_video(texname, tex)
 
1219
        i = 0
 
1220
        for texname, tex in textures:
 
1221
                write_texture(texname, tex, i)
 
1222
                i+=1
 
1223
        
 
1224
        # Finish Writing Objects
 
1225
        # Write global settings
 
1226
        file.write('''
 
1227
        GlobalSettings:  {
 
1228
                Version: 1000
 
1229
                Properties60:  {
 
1230
                        Property: "UpAxis", "int", "",1
 
1231
                        Property: "UpAxisSign", "int", "",1
 
1232
                        Property: "FrontAxis", "int", "",2
 
1233
                        Property: "FrontAxisSign", "int", "",1
 
1234
                        Property: "CoordAxis", "int", "",0
 
1235
                        Property: "CoordAxisSign", "int", "",1
 
1236
                        Property: "UnitScaleFactor", "double", "",1
 
1237
                }
 
1238
        }
 
1239
''')    
 
1240
        file.write('}')
 
1241
        
 
1242
        file.write('''
 
1243
 
 
1244
; Object relations
 
1245
;------------------------------------------------------------------
 
1246
 
 
1247
Relations:  {''')
 
1248
 
 
1249
        file.write('\n\tModel: "Model::blend_root", "Null" {\n\t}')
 
1250
        for obname, ob in ob_cameras:
 
1251
                file.write('\n\tModel: "Model::%s", "Camera" {\n\t}' % obname)
 
1252
        
 
1253
        for obname, ob in ob_lights:
 
1254
                file.write('\n\tModel: "Model::%s", "Light" {\n\t}' % obname)
 
1255
        
 
1256
        for obname, ob, mtx, me, mats, arm, armname in ob_meshes:
 
1257
                file.write('\n\tModel: "Model::%s", "Mesh" {\n\t}' % obname)
 
1258
        
 
1259
        file.write('''
 
1260
        Model: "Model::Producer Perspective", "Camera" {
 
1261
        }
 
1262
        Model: "Model::Producer Top", "Camera" {
 
1263
        }
 
1264
        Model: "Model::Producer Bottom", "Camera" {
 
1265
        }
 
1266
        Model: "Model::Producer Front", "Camera" {
 
1267
        }
 
1268
        Model: "Model::Producer Back", "Camera" {
 
1269
        }
 
1270
        Model: "Model::Producer Right", "Camera" {
 
1271
        }
 
1272
        Model: "Model::Producer Left", "Camera" {
 
1273
        }
 
1274
        Model: "Model::Camera Switcher", "CameraSwitcher" {
 
1275
        }''')
 
1276
        
 
1277
        for matname, mat in materials:
 
1278
                file.write('\n\tMaterial: "Material::%s", "" {\n\t}' % matname)
 
1279
 
 
1280
        if textures:
 
1281
                for texname, tex in textures:
 
1282
                        file.write('\n\tTexture: "Texture::%s", "TextureVideoClip" {\n\t}' % texname)
 
1283
                for texname, tex in textures:
 
1284
                        file.write('\n\tVideo: "Video::%s", "Clip" {\n\t}' % texname)
 
1285
 
 
1286
        file.write('\n}')
 
1287
        file.write('''
 
1288
 
 
1289
; Object connections
 
1290
;------------------------------------------------------------------
 
1291
 
 
1292
Connections:  {''')
 
1293
 
 
1294
        # write the fake root node
 
1295
        file.write('\n\tConnect: "OO", "Model::blend_root", "Model::Scene"')
 
1296
        
 
1297
        for obname, ob in ob_cameras:
 
1298
                file.write('\n\tConnect: "OO", "Model::%s", "Model::blend_root"' % obname)
 
1299
        
 
1300
        for obname, ob in ob_lights:
 
1301
                file.write('\n\tConnect: "OO", "Model::%s", "Model::blend_root"' % obname)
 
1302
        
 
1303
        for obname, ob, mtx, me, mats, arm, armname in ob_meshes:
 
1304
                file.write('\n\tConnect: "OO", "Model::%s", "Model::blend_root"' % obname)
 
1305
        
 
1306
        for obname, ob, mtx, me, mats, arm, armname in ob_meshes:
 
1307
                # Connect all materials to all objects, not good form but ok for now.
 
1308
                for mat in mats:
 
1309
                        file.write('\n\tConnect: "OO", "Material::%s", "Model::%s"' % (sane_matname(mat), obname))
 
1310
        
 
1311
        if textures:
 
1312
                for obname, ob, mtx, me, mats, arm, armname in ob_meshes:
 
1313
                        for texname, tex in textures:
 
1314
                                file.write('\n\tConnect: "OO", "Texture::%s", "Model::%s"' % (texname, obname))
 
1315
                
 
1316
                for texname, tex in textures:
 
1317
                        file.write('\n\tConnect: "OO", "Video::%s", "Texture::%s"' % (texname, texname))
 
1318
        
 
1319
        file.write('\n}')
 
1320
        
 
1321
        
 
1322
        # Clear mesh data Only when writing with modifiers applied
 
1323
        #for obname, ob, me, mats, arm, armname in objects:
 
1324
        #       me.verts = None
 
1325
 
 
1326
 
 
1327
def write_footer(file, sce, world):
 
1328
        
 
1329
        tuple(world.hor)
 
1330
        tuple(world.amb)
 
1331
        
 
1332
        has_mist = world.mode & 1
 
1333
        
 
1334
        mist_intense, mist_start, mist_end, mist_height = world.mist
 
1335
        
 
1336
        render = sce.render
 
1337
        
 
1338
        file.write('\n;Takes and animation section')
 
1339
        file.write('\n;----------------------------------------------------')
 
1340
        file.write('\n')
 
1341
        file.write('\nTakes:  {')
 
1342
        file.write('\n\tCurrent: ""')
 
1343
        file.write('\n}')
 
1344
        file.write('\n;Version 5 settings')
 
1345
        file.write('\n;------------------------------------------------------------------')
 
1346
        file.write('\n')
 
1347
        file.write('\nVersion5:  {')
 
1348
        file.write('\n\tAmbientRenderSettings:  {')
 
1349
        file.write('\n\t\tVersion: 101')
 
1350
        file.write('\n\t\tAmbientLightColor: %.1f,%.1f,%.1f,0' % tuple(world.amb))
 
1351
        file.write('\n\t}')
 
1352
        file.write('\n\tFogOptions:  {')
 
1353
        file.write('\n\t\tFlogEnable: %i' % has_mist)
 
1354
        file.write('\n\t\tFogMode: 0')
 
1355
        file.write('\n\t\tFogDensity: %.3f' % mist_intense)
 
1356
        file.write('\n\t\tFogStart: %.3f' % mist_start)
 
1357
        file.write('\n\t\tFogEnd: %.3f' % mist_end)
 
1358
        file.write('\n\t\tFogColor: %.1f,%.1f,%.1f,1' % tuple(world.hor))
 
1359
        file.write('\n\t}')
 
1360
        file.write('\n\tSettings:  {')
 
1361
        file.write('\n\t\tFrameRate: "%i"' % render.fps)
 
1362
        file.write('\n\t\tTimeFormat: 1')
 
1363
        file.write('\n\t\tSnapOnFrames: 0')
 
1364
        file.write('\n\t\tReferenceTimeIndex: -1')
 
1365
        file.write('\n\t\tTimeLineStartTime: %i' % render.sFrame)
 
1366
        file.write('\n\t\tTimeLineStopTime: %i' % render.eFrame)
 
1367
        file.write('\n\t}')
 
1368
        file.write('\n\tRendererSetting:  {')
 
1369
        file.write('\n\t\tDefaultCamera: "Producer Perspective"')
 
1370
        file.write('\n\t\tDefaultViewingMode: 0')
 
1371
        file.write('\n\t}')
 
1372
        file.write('\n}')
 
1373
        file.write('\n')
 
1374
        
 
1375
        # Incase sombody imports this, clean up by clearing global dicts
 
1376
        sane_name_mapping_ob.clear()
 
1377
        sane_name_mapping_mat.clear()
 
1378
        sane_name_mapping_tex.clear()
 
1379
        
 
1380
 
 
1381
import bpy
 
1382
def write_ui(filename):
 
1383
        if not filename.lower().endswith('.fbx'):
 
1384
                filename += '.fbx'
 
1385
        
 
1386
        #if not BPyMessages.Warning_SaveOver(filename):
 
1387
        #       return
 
1388
        sce = bpy.data.scenes.active
 
1389
        world = sce.world
 
1390
        
 
1391
        Blender.Window.WaitCursor(1)
 
1392
        file = open(filename, 'w')
 
1393
        write_header(file)
 
1394
        write_scene(file, sce, world)
 
1395
        write_footer(file, sce, world)
 
1396
        Blender.Window.WaitCursor(0)
 
1397
 
 
1398
if __name__ == '__main__':
 
1399
        Blender.Window.FileSelector(write_ui, 'Export FBX', Blender.sys.makename(ext='.fbx'))
 
1400
        #write_ui('/test.fbx')