Final merge of HEAD (bf-blender) into the orange branch.
[blender.git] / release / scripts / DirectX8Exporter.py
1 #!BPY
2
3 """ Registration info for Blender menus:
4 Name: 'DirectX8(.x)...'
5 Blender: 239
6 Group: 'Export'
7 Submenu: 'Export all the scene' export
8 Submenu: 'Export selected obj' exportsel
9 Tip: 'Export to DirectX8 text file format format.'
10 """
11
12 __author__ = "Arben (Ben) Omari"
13 __url__ = ("blender", "elysiun", "Author's site, http://www.omariben.too.it")
14 __version__ = "1.0"
15
16 __bpydoc__ = """\
17 This script exports a Blender mesh with armature to DirectX 8's text file
18 format.
19
20 Notes:<br>
21     Check author's site or the elYsiun forum for a new beta version of the
22 DX exporter.
23 """
24 # DirectX8Exporter.py version 1.0
25 # Copyright (C) 2003  Arben OMARI -- omariarben@everyday.com 
26 #
27 # This program is free software; you can redistribute it and/or modify
28 # it under the terms of the GNU General Public License as published by
29 # the Free Software Foundation; either version 2 of the License, or
30 # (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 # This script export meshes created with Blender in DirectX8 file format
38 # it exports meshes,armatures,materials,normals,texturecoords and animations
39
40 # Grab the latest version here :www.omariben.too.it
41
42 import Blender
43 from Blender import Types, Object, NMesh, Material,Armature
44 from Blender.Mathutils import *
45
46 global new_bon,mat_flip,index_list
47 index_list = []
48 new_bon = {}
49 mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1])
50                 
51
52 #***********************************************
53 #***********************************************
54 #                EXPORTER
55 #***********************************************
56 #***********************************************
57
58 class xExport:
59         def __init__(self, filename):
60                 self.file = open(filename, "w")
61
62 #*********************************************************************************************************************************************
63         #***********************************************
64         #Select Scene objects
65         #***********************************************
66         def SelectObjs(self):
67                 print "exporting..."
68                 self.writeHeader()
69                 for obj in Object.Get():
70                         mesh = obj.getData()
71                         if type(mesh) == Types.NMeshType :
72                                 chld_obj = obj.getParent()
73                                 if chld_obj :
74                                         dt_chld_obj = chld_obj.getData()
75                                         if type(dt_chld_obj) == Types.ArmatureType :
76                                                 self.writeRootBone(chld_obj, obj)
77                                         
78                                 else :
79                                         self.exportMesh(obj)
80                 self.file.write("AnimationSet {\n")
81                 for obj in Object.Get():
82                         mesh = obj.getData()
83                         if type(mesh) == Types.NMeshType :
84                                 ip_list = obj.getIpo()
85                                 if ip_list != None :
86                                         self.writeAnimationObj(obj)
87                         elif type(mesh) == Types.ArmatureType :
88                                 act_list = obj.getAction()
89                                 if act_list != None :
90                                         self.writeAnimation(obj)
91                                 ip_list = obj.getIpo()
92                                 if ip_list != None :
93                                         self.writeAnimationObjArm(obj)
94                 self.file.write("}\n")
95                 self.writeEnd()
96         #***********************************************
97         #Export Mesh without Armature
98         #***********************************************
99         def exportMesh(self, obj):
100                 tex = []
101                 mesh = obj.getData()
102                 self.writeTextures(obj, tex)            
103                 self.writeMeshcoord(obj, mesh)
104                 self.writeMeshMaterialList(obj, mesh, tex)
105                 self.writeMeshNormals(obj, mesh)
106                 self.writeMeshTextureCoords(obj, mesh)
107                 self.file.write(" }\n")
108                 self.file.write("}\n")
109                 
110                                         
111         #***********************************************
112         #Export the Selected Mesh
113         #***********************************************
114         def exportSelMesh(self):
115                 print "exporting ..."
116                 self.writeHeader()
117                 tex = []
118                 obj = Object.GetSelected()[0]
119                 mesh = obj.getData()
120                 if type(mesh) == Types.NMeshType :
121                         self.writeTextures(obj, tex)            
122                         self.writeMeshcoord(obj, mesh)
123                         self.writeMeshMaterialList(obj, mesh, tex)
124                         self.writeMeshNormals(obj, mesh)
125                         self.writeMeshTextureCoords(obj, mesh)
126                         self.file.write(" }\n")
127                         self.file.write("}\n")
128                         ip_list = obj.getIpo()
129                         if ip_list != None :
130                                 self.file.write("AnimationSet {\n")
131                                 self.writeAnimationObj(obj)
132                                 self.file.write("}\n")
133                         print "exporting ..."
134                 else :
135                         print "The selected object is not a mesh"
136                 print "...finished"
137         #***********************************************
138         #Export Mesh with Armature
139         #***********************************************
140         def exportMeshArm(self,arm,arm_ob,ch_obj):
141                 tex = []
142                 mesh = ch_obj.getData()
143                 self.writeTextures(ch_obj, tex)         
144                 self.writeMeshcoordArm(ch_obj, mesh,arm_ob)
145                 self.writeMeshMaterialList(ch_obj, mesh, tex)
146                 self.writeMeshNormals(ch_obj, mesh)
147                 self.writeMeshTextureCoords(ch_obj, mesh)
148                 self.writeSkinWeights(arm,mesh)
149                 self.file.write(" }\n")
150                 self.file.write("}\n")
151                 
152                                 
153         #***********************************************
154         #Export Root Bone
155         #***********************************************
156         def writeRootBone(self,am_ob,child_obj):
157                 global new_bon,mat_flip
158                 space = 0
159                 arm = am_ob.getData()
160                 Blender.Set('curframe',1)
161                 mat_ob = mat_flip * am_ob.matrixWorld
162                 self.writeArmFrames(mat_ob, "RootFrame", 0)
163                 root_bon = arm.getBones()
164                 mat_r = self.writeCombineMatrix(root_bon[0])
165                 name_r = root_bon[0].getName()
166                 new_bon[name_r] = len(root_bon[0].getChildren())
167                 self.writeArmFrames(mat_r, name_r, 1)
168                 self.writeListOfChildrens(root_bon[0],2,arm)
169                 self.file.write("}\n")
170                 self.exportMeshArm(arm,am_ob,child_obj)
171                 
172         #***********************************************
173         #Export Children Bones
174         #***********************************************
175         def writeListOfChildrens(self,bon,space,arm):
176                 global  new_bon
177                 bon_c = bon.getChildren()
178                 Blender.Set('curframe',1)
179                 for n in range(len(bon_c)):
180                         name_h = bon_c[n].getName()
181                         chi_h = bon_c[n].getChildren()
182                         new_bon[name_h] = len(chi_h)
183
184                 if bon_c == [] :
185                         self.CloseBrackets(bon, new_bon, space, arm.getBones()[0])
186                 
187                 for nch in range(len(bon_c)):
188                         mat = self.writeCombineMatrix(bon_c[nch])
189                         name_ch = bon_c[nch].getName()
190                         self.writeArmFrames(mat, name_ch,space)
191                         self.findChildrens(bon_c[nch],space,arm)
192                 
193                 
194         #***********************************************
195         #Create Children structure
196         #***********************************************
197         def CloseBrackets(self, bon, new_bon, space, root_bon):
198                 tab = "  "
199                 self.file.write("%s" % (tab * (space -1)))
200                 self.file.write("}\n")
201                 while bon.hasParent():
202                         if new_bon[bon.getName()] == 0:
203                                 pare = bon.getParent()
204                                 name_p = pare.getName()
205                                 if new_bon[name_p] > 0:
206                                         new_bon[name_p] = new_bon[name_p] - 1
207                                 if new_bon[name_p] == 0 and pare != root_bon:
208                                         self.file.write("%s" % (tab * (space-2)))
209                                         self.file.write("}\n")
210                                 space = space - 1
211                                 bon = pare
212                         else:
213                                 break
214                 
215                         
216         #***********************************************
217         #Create Children structure
218         #***********************************************
219         def findChildrens(self,bon_c,space,arm):
220                 bon_cc = bon_c
221                 space += 1
222                 self.writeListOfChildrens(bon_cc,space,arm)
223         
224         
225         #***********************************************
226         #Offset Matrix
227         #***********************************************
228         def writeMatrixOffset(self,bon):
229                 Blender.Set('curframe',1)
230                 mat_b = bon.getRestMatrix()       
231                 mat_b.invert() 
232                 return mat_b
233
234
235         
236
237         #***********************************************
238         #Combine Matrix
239         #***********************************************
240         def writeCombineMatrix(self,bon):
241                 Blender.Set('curframe',1)
242                 mat_b = bon.getRestMatrix()     
243                 if bon.hasParent():
244                         pare = bon.getParent()
245                         mat_p = pare.getRestMatrix()
246                 else :
247                         mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
248                 mat_p.invert()
249                 mat_rb = mat_b * mat_p
250                 return mat_rb
251
252         #***********************************************
253         #Combine Matrix
254         #***********************************************
255         def writeCombineAnimMatrix(self,bon):
256                 
257                 mat_b = bon.getRestMatrix()     
258                 if bon.hasParent():
259                         pare = bon.getParent()
260                         mat_p = pare.getRestMatrix()
261                 else :
262                         mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
263                 mat_p.invert()
264                 mat_rb = mat_b * mat_p
265                 return mat_rb
266
267
268 #*********************************************************************************************************************************************
269         #***********************************************
270         #Write SkinWeights
271         #***********************************************
272         def writeSkinWeights(self, arm, mesh):
273                 global index_list
274                 
275                 Blender.Set('curframe',1)
276                 self.file.write("  XSkinMeshHeader {\n")
277                 max_infl = 0
278                 for bo in arm.getBones() :
279                         name = bo.getName() 
280                         try :
281                                 vertx_list = mesh.getVertsFromGroup(name,1)
282                                 for inde in vertx_list :
283                                         vert_infl = mesh.getVertexInfluences(inde[0])
284                                         ln_infl = len(vert_infl)
285                                         if ln_infl > max_infl :
286                                                 max_infl = ln_infl
287                                 
288                         except:
289                                 pass
290                 
291                 self.file.write("    %s; \n" % (max_infl))
292                 self.file.write("    %s; \n" % (max_infl * 3))
293                 self.file.write("    %s; \n" % (len(arm.getBones())))
294                 self.file.write("  }\n")
295                 
296                 for bo in arm.getBones() :
297                         bo_list = []
298                         weight_list = []
299                         name = bo.getName() 
300                         try :
301                                 vert_list = mesh.getVertsFromGroup(name,1)
302                                 le = 0
303                                 for indx in vert_list:
304                                         ver_infl = mesh.getVertexInfluences(indx[0])
305                                         len_infl = float(len(ver_infl))
306                                         infl = 1 / len_infl
307                                         i = -1
308                                         for el in index_list :
309                                                 i += 1
310                                                 if el == indx[0] :
311                                                         le +=1
312                                                         bo_list.append(i)
313                                                         weight_list.append(infl)
314
315
316                                 self.file.write("  SkinWeights {\n")
317                                 self.file.write('    "%s"; \n' % (name))
318                                 self.file.write('     %s; \n' % (le))
319                                 count = 0
320                                 for ind in bo_list :
321                                         count += 1
322                                         if count == len(bo_list):
323                                                 self.file.write("    %s; \n" % (ind))
324                                         else :
325                                                 self.file.write("    %s, \n" % (ind))
326                                 cou = 0
327                                 for wegh in weight_list :
328                                         cou += 1
329                                         
330                                         if cou == len(weight_list):
331                                                 self.file.write("    %s; \n" % (round(wegh,6)))
332                                         else :
333                                                 self.file.write("    %s, \n" % (round(wegh,6)))
334
335                         
336                                 matx = self.writeMatrixOffset(bo)
337                         
338                                 self.writeOffsFrames(matx, name, 1)
339                         except :
340                                 pass
341                 self.file.write("  }\n")
342                 
343
344         #***********************************************
345         # Write Matrices
346         #***********************************************
347         def writeArmFrames(self, matx, name, space):
348                 tab = "  "
349                 self.file.write("%s" % (tab * space))
350                 self.file.write("Frame ")  
351                 self.file.write("%s {\n\n" % (name))
352                 self.file.write("%s" % (tab * space))
353                 self.file.write("  FrameTransformMatrix {\n")
354                 self.file.write("%s" % (tab * space))
355                 self.file.write("    %s,%s,%s,%s,\n" %
356                                                         (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
357                 self.file.write("%s" % (tab * space))
358                 self.file.write("    %s,%s,%s,%s,\n" %
359                                                         (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))
360                 self.file.write("%s" % (tab * space))   
361                 self.file.write("    %s,%s,%s,%s,\n" %
362                                                         (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
363                 self.file.write("%s" % (tab * space))
364                 self.file.write("    %s,%s,%s,%s;;\n" %
365                                                         (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],6)))
366                 self.file.write("%s" % (tab * space))
367                 self.file.write("  }\n")
368         
369         #***********************************************
370         # Write Matrices
371         #***********************************************
372         def writeOffsFrames(self, matx, name, space):
373                 tab = "  "
374                 self.file.write("%s" % (tab * space))
375                 self.file.write("    %s,%s,%s,%s,\n" %
376                                                         (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
377                 self.file.write("%s" % (tab * space))
378                 self.file.write("    %s,%s,%s,%s,\n" %
379                                                         (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))
380                 self.file.write("%s" % (tab * space))   
381                 self.file.write("    %s,%s,%s,%s,\n" %
382                                                         (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
383                 self.file.write("%s" % (tab * space))
384                 self.file.write("    %s,%s,%s,%s;;\n" %
385                                                         (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],6)))
386                 self.file.write("%s" % (tab * space))
387                 self.file.write("  }\n")
388         
389          
390 #*********************************************************************************************************************************************
391         
392         #***********************************************
393         #HEADER
394         #***********************************************  
395         def writeHeader(self):
396                 self.file.write("xof 0303txt 0032\n\n\n")
397                 self.file.write("template VertexDuplicationIndices { \n\
398  <b8d65549-d7c9-4995-89cf-53a9a8b031e3>\n\
399  DWORD nIndices;\n\
400  DWORD nOriginalVertices;\n\
401  array DWORD indices[nIndices];\n\
402 }\n\
403 template XSkinMeshHeader {\n\
404  <3cf169ce-ff7c-44ab-93c0-f78f62d172e2>\n\
405  WORD nMaxSkinWeightsPerVertex;\n\
406  WORD nMaxSkinWeightsPerFace;\n\
407  WORD nBones;\n\
408 }\n\
409 template SkinWeights {\n\
410  <6f0d123b-bad2-4167-a0d0-80224f25fabb>\n\
411  STRING transformNodeName;\n\
412  DWORD nWeights;\n\
413  array DWORD vertexIndices[nWeights];\n\
414  array float weights[nWeights];\n\
415  Matrix4x4 matrixOffset;\n\
416 }\n\n")
417                 
418         #***********************************************
419         #CLOSE FILE
420         #***********************************************
421         def writeEnd(self):
422                 self.file.close()
423                 print "... finished"
424
425
426         #***********************************************
427         #EXPORT TEXTURES
428         #***********************************************
429         def writeTextures(self,name, tex):
430                 mesh = name.data
431                 for face in mesh.faces:
432                         if face.image and face.image.name not in tex:
433                                 tex.append(face.image.name)
434                                 
435
436
437         #***********************************************
438         #EXPORT MESH DATA with Armature
439         #***********************************************
440         def writeMeshcoordArm(self, name, meshEX,arm_ob):
441                 global index_list
442                 #ROTATION
443                 mat_arm = arm_ob.matrixWorld
444                 mat_ob = name.getMatrix('localspace')
445                 mat_ob.invert()
446                 mat = mat_arm * mat_ob
447                 mat.invert()
448                 self.writeArmFrames(mat, name.name, 1)
449                 mesh = NMesh.GetRawFromObject(name.name)
450                 self.file.write("Mesh {\n")    
451                 numface=len(mesh.faces)
452                 #VERTICES NUMBER
453                 numvert = 0
454                 for face in mesh.faces:
455                         numvert = numvert + len(face.v)
456                 self.file.write("%s;\n" % (numvert))
457                 #VERTICES COORDINATES
458                 counter = 0
459                 for face in mesh.faces:
460                         counter += 1
461                         for n in range(len(face.v)):
462                                 index_list.append(face.v[n].index)
463                                 vec_vert = Vector([face.v[n].co[0], face.v[n].co[1], face.v[n].co[2], 1])
464                                 f_vec_vert = VecMultMat(vec_vert, mat)
465                                 self.file.write("%s; %s; %s;" % (f_vec_vert[0], f_vec_vert[1], f_vec_vert[2]))
466                                 if counter == numface :
467                                         if n == len(face.v)-1 :
468                                                 self.file.write(";\n")
469                                         else :
470                                                 self.file.write(",\n")
471                                 else :
472                                         self.file.write(",\n")
473
474                 #FACES NUMBER 
475                 self.file.write("%s;\n" % (numface))  
476                 coun,counter = 0, 0
477                 for face in mesh.faces :
478                         coun += 1
479                         if coun == numface:
480                                 if len(face.v) == 3:
481                                         self.file.write("3; %s, %s, %s;;\n" % (counter, counter + 2, counter + 1))
482                                         counter += 3
483                                 elif len(face.v) == 4:
484                                         self.file.write("4; %s, %s, %s, %s;;\n" % (counter, counter + 3, counter + 2, counter + 1))
485                                         counter += 4
486                                 elif len(face.v) < 3:
487                                         print "WARNING:the mesh has faces with less then 3 vertices"
488                                         print "        It my be not exported correctly."
489                         else:
490                                 
491                                 if len(face.v) == 3:
492                                         self.file.write("3; %s, %s, %s;,\n" % (counter, counter + 2, counter + 1))
493                                         counter += 3
494                                 elif len(face.v) == 4:
495                                         self.file.write("4; %s, %s, %s, %s;,\n" % (counter, counter + 3, counter + 2, counter + 1))
496                                         counter += 4
497                                 elif len(face.v) < 3:
498                                         print "WARNING:the mesh has faces with less then 3 vertices"
499                                         print "        It my be not exported correctly."
500
501         #***********************************************
502         #EXPORT MESH DATA without Armature
503         #***********************************************
504         def writeMeshcoord(self, name, mesh):
505                 global index_list
506                 #ROTATION
507                 mat_ob = mat_flip * name.matrixWorld
508                 self.writeArmFrames(mat_ob, name.name, 0)
509
510                 self.file.write("Mesh {\n")    
511                 numface=len(mesh.faces)
512                 #VERTICES NUMBER
513                 numvert = 0
514                 for face in mesh.faces:
515                         numvert = numvert + len(face.v)
516                 self.file.write("%s;\n" % (numvert))
517                 #VERTICES COORDINATES
518                 counter = 0
519                 for face in mesh.faces:
520                         counter += 1
521                         for n in range(len(face.v)):
522                                 index_list.append(face.v[n].index)
523                                 self.file.write("%s; %s; %s;" % (face.v[n].co[0], face.v[n].co[1], face.v[n].co[2]))
524                                 if counter == numface :
525                                         if n == len(face.v)-1 :
526                                                 self.file.write(";\n")
527                                         else :
528                                                 self.file.write(",\n")
529                                 else :
530                                         self.file.write(",\n")
531
532                 #FACES NUMBER 
533                 self.file.write("%s;\n" % (numface))  
534                 coun,counter = 0, 0
535                 for face in mesh.faces :
536                         coun += 1
537                         if coun == numface:
538                                 if len(face.v) == 3:
539                                         self.file.write("3; %s, %s, %s;;\n" % (counter, counter + 2, counter + 1))
540                                         counter += 3
541                                 elif len(face.v) == 4:
542                                         self.file.write("4; %s, %s, %s, %s;;\n" % (counter, counter + 3, counter + 2, counter + 1))
543                                         counter += 4
544                                 elif len(face.v) < 3:
545                                         print "WARNING:the mesh has faces with less then 3 vertices(edges and points)"
546                                         print "        It my be not exported correctly."
547                         else:
548                                 
549                                 if len(face.v) == 3:
550                                         self.file.write("3; %s, %s, %s;,\n" % (counter, counter + 2, counter + 1))
551                                         counter += 3
552                                 elif len(face.v) == 4:
553                                         self.file.write("4; %s, %s, %s, %s;,\n" % (counter, counter + 3, counter + 2, counter + 1))
554                                         counter += 4
555                                 elif len(face.v) < 3:
556                                         print "WARNING:the mesh has faces with less then 3 vertices(edges and points)\n"
557                                         print "        It my be not exported correctly."
558         
559                 
560         #***********************************************
561         #MESH MATERIAL LIST
562         #***********************************************
563         def writeMeshMaterialList(self, name, obj, tex):
564                 self.file.write("  MeshMaterialList {\n")
565                 #HOW MANY MATERIALS ARE USED
566                 count = 0
567                 for mat in Material.Get():
568                         count+=1
569                 self.file.write("    %s;\n" % (len(tex) + count))
570                 #HOW MANY FACES IT HAS
571                 numfaces=len(obj.faces)
572                 self.file.write("    %s;\n" % (numfaces))
573                 ##MATERIALS INDEX FOR EVERY FACE
574                 counter = 0
575                 for face in obj.faces :
576                         counter += 1
577                         mater = face.materialIndex
578                         if counter == numfaces:
579                                 if face.image and face.image.name in tex :
580                                         self.file.write("    %s;;\n" % (tex.index(face.image.name) + count))
581                                 else :
582                                         self.file.write("    %s;;\n" % (mater))
583                         else :
584                                 if face.image and face.image.name in tex :
585                                         self.file.write("    %s,\n" % (tex.index(face.image.name) + count))
586                                 else :
587                                         self.file.write("    %s,\n" % (mater))
588                         
589                 ##MATERIAL NAME
590                 for mat in Material.Get():
591                         self.file.write("  Material")
592                         for a in range(0,len(mat.name)):
593                                 if mat.name[a] == ".":
594                                         print "WARNING:the material " + mat.name + " contains '.' within.Many viewers may refuse to read the exported file"
595                         self.file.write(" %s "% (mat.name))
596                         self.file.write("{\n")
597                         self.file.write("    %s; %s; %s;" % (mat.R, mat.G, mat.B))
598                         self.file.write("%s;;\n" % (mat.alpha))
599                         self.file.write("    %s;\n" % (mat.spec))
600                         self.file.write("    %s; %s; %s;;\n" % (mat.specR, mat.specG, mat.specB))
601                         self.file.write("    0.0; 0.0; 0.0;;\n")
602                         self.file.write("  }\n") 
603                 
604                 for mat in tex:
605                         self.file.write("  Material Mat")
606                         self.file.write("%s "% (len(tex)))
607                         self.file.write("{\n")
608                         self.file.write("    1.0; 1.0; 1.0; 1.0;;\n")
609                         self.file.write("    1.0;\n")
610                         self.file.write("    1.0; 1.0; 1.0;;\n")
611                         self.file.write("    0.0; 0.0; 0.0;;\n")
612                         self.file.write("  TextureFilename {\n")
613                         self.file.write('    "%s" ;'% (mat))
614                         self.file.write("  }\n")
615                         self.file.write("  }\n") 
616                 self.file.write("    }\n")
617
618         #***********************************************
619         #MESH NORMALS
620         #***********************************************
621         def writeMeshNormals(self,name,mesh):
622                 self.file.write("  MeshNormals {\n")
623                 #VERTICES NUMBER
624                 numvert = 0
625                 for face in mesh.faces:
626                         numvert = numvert + len(face.v)
627                 self.file.write("%s;\n" % (numvert))
628                 numfaces=len(mesh.faces)
629                 
630                 #VERTICES NORMAL
631                 counter = 0
632                 for face in mesh.faces:
633                         counter += 1  
634                         for n in range(len(face.v)):
635                                 self.file.write("    %s; %s; %s;" % ((round(face.v[n].no[0],6)),(round(face.v[n].no[1],6)),(round(face.v[n].no[2],6))))
636                                 if counter == numfaces :
637                                         if n == len(face.v)-1 :
638                                                 self.file.write(";\n")
639                                         else :
640                                                 self.file.write(",\n")
641                                 else :
642                                         self.file.write(",\n")
643                 
644
645
646                 #FACES NUMBER 
647                 self.file.write("%s;\n" % (numfaces))  
648                 coun,counter = 0, 0
649                 for face in mesh.faces :
650                         coun += 1
651                         if coun == numfaces:
652                                 if len(face.v) == 3:
653                                         self.file.write("3; %s, %s, %s;;\n" % (counter, counter + 2, counter + 1))
654                                         counter += 3
655                                 else :
656                                         self.file.write("4; %s, %s, %s, %s;;\n" % (counter, counter + 3, counter + 2, counter + 1))
657                                         counter += 4
658                         else:
659                                 
660                                 if len(face.v) == 3:
661                                         self.file.write("3; %s, %s, %s;,\n" % (counter, counter + 2, counter + 1))
662                                         counter += 3
663                                 else :
664                                         self.file.write("4; %s, %s, %s, %s;,\n" % (counter, counter + 3, counter + 2, counter + 1))
665                                         counter += 4
666                 self.file.write("}\n")
667
668         #***********************************************
669         #MESH TEXTURE COORDS
670         #***********************************************
671         def writeMeshTextureCoords(self, name, mesh):
672                 if mesh.hasFaceUV():
673                         self.file.write("MeshTextureCoords {\n")
674                         #VERTICES NUMBER
675                         numvert = 0
676                         for face in mesh.faces:
677                                 numvert += len(face.v)
678                         self.file.write("%s;\n" % (numvert))
679                         #UV COORDS
680                         numfaces = len(mesh.faces)
681                         counter = -1
682                         co = 0
683                         for face in mesh.faces:
684                                 counter += 1
685                                 co += 1
686                                 for n in range(len(face.v)):
687                                         self.file.write("%s;%s;" % (mesh.faces[counter].uv[n][0], -mesh.faces[counter].uv[n][1]))
688                                         if co == numfaces :
689                                                 if n == len(face.v) - 1 :
690                                                         self.file.write(";\n")
691                                                 else :
692                                                         self.file.write(",\n")
693                                         else :
694                                                 self.file.write(",\n")
695
696                         self.file.write("}\n")
697 #***********************************************#***********************************************#***********************************************
698         #***********************************************
699         #FRAMES
700         #***********************************************
701         def writeFrames(self, matx):
702                 
703                 self.file.write("%s,%s,%s,%s," %
704                                                         (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],6)))
705                 self.file.write("%s,%s,%s,%s," %
706                                                         (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],6)))      
707                 self.file.write("%s,%s,%s,%s," %
708                                                         (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],6)))
709                 self.file.write("%s,%s,%s,%s;;" %
710                                                         (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],6)))
711                 
712                 
713                 
714                 
715         #***********************************************
716         #WRITE ANIMATION KEYS
717         #***********************************************
718         def writeAnimation(self,arm_ob):
719                 arm = arm_ob.getData()
720                 act_list = arm_ob.getAction()
721                 ip = act_list.getAllChannelIpos()
722                 for bon in arm.getBones() :
723                         point_list = []
724                         try :
725                                 ip_bon_channel = ip[bon.name]
726                                 ip_bon_name = ip_bon_channel.getName()
727                         
728                                 ip_bon = Blender.Ipo.Get(ip_bon_name)
729                                 poi = ip_bon.getCurves()
730                                 for po in poi[3].getPoints():
731                                         a = po.getPoints()
732                                         point_list.append(int(a[0]))
733                                 point_list.pop(0) 
734                         
735                         
736                                 self.file.write(" Animation { \n")
737                                 self.file.write("  {%s}\n" %(bon.getName()))
738                                 self.file.write("  AnimationKey { \n")
739                                 self.file.write("   4;\n")
740                                 self.file.write("   %s; \n" % (len(point_list)+1))
741
742                                 self.file.write("   %s;" % (1))
743                                 self.file.write("16;")
744                                 mat = self.writeCombineMatrix(bon)
745                                 self.writeFrames(mat)
746                                 self.file.write(",\n")
747
748                                 for fr in point_list:
749                                         self.file.write("   %s;" % (fr))
750                                         self.file.write("16;")
751                                         Blender.Set('curframe',fr)
752                                 
753                                         mat_new = self.writeCombineAnimMatrix(bon)
754                                         self.writeFrames(mat_new)
755                                 
756                                         if fr == point_list[len(point_list)-1]:
757                                                 self.file.write(";\n")
758                                         else:
759                                                 self.file.write(",\n")
760                                 self.file.write("   }\n")
761                                 self.file.write(" }\n")
762                                 self.file.write("\n")
763                         except:
764                                 pass
765                 
766                 
767
768         #***********************************************
769         #WRITE ANIMATION KEYS
770         #***********************************************
771         def writeAnimationObj(self, obj):
772                 point_list = []
773                 ip = obj.getIpo()
774                 poi = ip.getCurves()
775                 for po in poi[0].getPoints():
776                         a = po.getPoints()
777                         point_list.append(int(a[0]))
778                 point_list.pop(0)
779                 
780                 self.file.write(" Animation {\n")
781                 self.file.write("  {")
782                 self.file.write("%s }\n" % (obj.name))
783                 self.file.write("   AnimationKey { \n")
784                 self.file.write("   4;\n")
785                 self.file.write("   %s; \n" % (len(point_list)+1))
786                 self.file.write("   %s;" % (1))
787                 self.file.write("16;")
788                 Blender.Set('curframe',1)
789                 mat = obj.matrixWorld * mat_flip
790                 self.writeFrames(mat)
791                 self.file.write(",\n")
792                 for fr in point_list:
793                         self.file.write("   %s;" % (fr))
794                         self.file.write("16;")
795                         Blender.Set('curframe',fr)
796                                 
797                         mat_new = obj.matrixWorld * mat_flip
798                         self.writeFrames(mat_new)
799
800                         if fr == point_list[len(point_list)-1]:
801                                 self.file.write(";\n")
802                         else:
803                                 self.file.write(",\n")
804                 self.file.write("   }\n")
805                 self.file.write("  }\n")
806
807         #***********************************************
808         #WRITE ANIMATION KEYS
809         #***********************************************
810         def writeAnimationObjArm(self, obj):
811                 point_list = []
812                 ip = obj.getIpo()
813                 poi = ip.getCurves()
814                 for po in poi[0].getPoints():
815                         a = po.getPoints()
816                         point_list.append(int(a[0]))
817                 point_list.pop(0)
818                 
819                 self.file.write(" Animation {\n")
820                 self.file.write("  {RootFrame}\n" )
821                 self.file.write("   AnimationKey { \n")
822                 self.file.write("   4;\n")
823                 self.file.write("   %s; \n" % (len(point_list)+1))
824                 self.file.write("   %s;" % (1))
825                 self.file.write("16;")
826                 Blender.Set('curframe',1)
827                 mat = mat_flip * obj.getMatrix('worldspace')
828                 self.writeFrames(mat)
829                 self.file.write(",\n")
830                 for fr in point_list:
831                         self.file.write("   %s;" % (fr))
832                         self.file.write("16;")
833                         Blender.Set('curframe',fr)
834                                 
835                         mat_new = mat_flip * obj.getMatrix('worldspace')
836                         self.writeFrames(mat_new)
837
838                         if fr == point_list[len(point_list)-1]:
839                                 self.file.write(";\n")
840                         else:
841                                 self.file.write(",\n")
842                 self.file.write("   }\n")
843                 self.file.write("  }\n")
844                 
845 #***********************************************#***********************************************#***********************************************
846
847
848
849 #***********************************************
850 # MAIN
851 #***********************************************
852
853 def my_callback(filename):
854         if filename.find('.x', -2) <= 0: filename += '.x' 
855         xexport = xExport(filename)
856         xexport.SelectObjs()
857
858 def my_callback_sel(filename):
859         if filename.find('.x', -2) <= 0: filename += '.x' 
860         xexport = xExport(filename)
861         xexport.exportSelMesh()
862
863 arg = __script__['arg']
864
865 if arg == 'exportsel':
866         fname = Blender.sys.makename(ext = ".x")
867         Blender.Window.FileSelector(my_callback_sel, "Export DirectX8", fname)  
868 else:
869         fname = Blender.sys.makename(ext = ".x")
870         Blender.Window.FileSelector(my_callback, "Export DirectX8", fname)      
871