Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

supcom-importer-V3

By: Pureon on Feb 6th, 2012  |  syntax: Python  |  size: 25.36 KB  |  views: 215  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!BPY
  2.  
  3. #**************************************************************************************************
  4. # Supreme Commander Importer for Blender3D - www.blender3d.org
  5. #
  6. # Written by dan - www.sup-com.net
  7. #
  8. # History
  9. #   0.1.0   06/06/06   - Initial version.
  10. #   0.2.0   06/06/10   - Added SCA (Animation) support
  11. #   0.3.0   06/07/02   - Alpha release
  12. #
  13. # Todo
  14. #   - Material/uv map 2
  15. #   - Bone pos/rot for scm & sca. Not perfect to use gentle words.
  16. #   - Make sca loading independent of the scm_mesh. (e.g get bone pos/loc from armature instead)
  17. #   - GUI for loading
  18. #
  19. #**************************************************************************************************
  20.  
  21. """
  22. Name: 'SupCom Model (.scm) 3.5'
  23. Blender: 232
  24. Group: 'Import'
  25. Tooltip: 'Import Supreme Commander Models (*.scm) and Animations (*.sca)'
  26. """
  27.  
  28. import Blender
  29. from Blender import NMesh, Scene, Object
  30.  
  31. from Blender import Mathutils
  32. from Blender.Mathutils import *
  33.  
  34. from Blender.BGL import *
  35. from Blender import Draw
  36. from Blender.Draw import *
  37.  
  38. import os
  39. from os import path
  40.  
  41.  
  42. import struct
  43. import string
  44. import math
  45. from math import *
  46.  
  47.  
  48. VERSION = '3.5'
  49.  
  50. ######################################################
  51. # User defined behaviour, Select as you need
  52. ######################################################
  53.  
  54. #Enable Progress Bar ( 0 = faster )
  55. PROG_BAR_ENABLE = 1
  56. #how many steps a progress bar has (the lesser the faster)
  57. PROG_BAR_STEP = 25
  58.  
  59. #LOG File for debuging
  60. #Enable LOG File (0 = Disabled , 1 = Enabled )
  61. LOG_ENABLE = 0
  62. #Filename / Path. Default is blender directory Filename SC-E_LOG.txt
  63. LOG_FILENAME = "SC-E_LOG.txt"
  64.  
  65. ######################################################
  66. # Init Supreme Commander SCM( _bone, _vertex, _mesh), SCA(_bone, _frame, _anim) Layout
  67. ######################################################
  68. #xy_to_xz_transform = Matrix([1, 0, 0], [ 0, 0, 1], [ 0, 1, 0])
  69. xy_to_xz_transform = Matrix([1, 0, 0], [ 0, 0, 1], [ 0, -1, 0])
  70.  
  71.  
  72.         #       -1      0       0
  73.         #       0       0       1
  74.         #       0       1       0
  75.  
  76.  
  77. class scm_bone :
  78.        
  79.         name = ""
  80.         #rest_pose_inv = []
  81.         rel_mat = []
  82.         rel_mat_inv = []
  83.         position = []
  84.         rotation = []
  85.         #abs_pos = []
  86.         parent = 0
  87.         parent_index = 0
  88.        
  89.         rel_matrix_inv = []
  90.         #children = []
  91.         #numchildren = 0
  92.         #global xy_to_xz_transform
  93.        
  94.         def __init__(self, name):
  95.                 self.name = name
  96.                 #self.rest_pose_inv = [[0.0] * 4] * 4
  97.                 #self.position = [0.0] * 3
  98.                 #self.rotation = [0.0] * 4
  99.                 self.rel_mat_inv = Matrix([0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0])
  100.                 self.rel_mat = Matrix([0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0])
  101.                 self.rotation = Quaternion(0,0,0,0)
  102.                 self.position = Vector(0,0,0)
  103.  
  104.         def load(self, file):
  105.                 #global xy_to_xz_transform
  106.                 bonestruct = '16f3f4f4i'
  107.                 buffer = file.read(struct.calcsize(bonestruct))
  108.                 readout = struct.unpack(bonestruct, buffer)
  109.  
  110.                 #supcom information:
  111.                 readRPI = Matrix([0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0])
  112.                 #// Inverse transform of the bone relative to the local origin of the mesh
  113.                 #// 4x4 Matrix with row major (i.e. D3D default ordering)
  114.                 for i in range(4):
  115.                         readRPI[i] = readout[i*4:i*4+4]
  116.                
  117.                 self.rel_mat_inv = Matrix(readRPI[0], readRPI[1], readRPI[2], readRPI[3])#*xy_to_xz_transform #note rot here changes pointing direction of spikie
  118.                 self.rel_mat = self.rel_mat_inv.invert()
  119.  
  120.                 #self.rel_mat = (Matrix(rest_pose_inv).invert())
  121.  
  122.                 #// Position relative to the parent bone.
  123.                 pos = readout[16:19]
  124.                 self.position = Vector(pos[0], pos[1], pos[2])
  125.                
  126.                 #// Rotation relative to the parent bone.
  127.                 rot = readout[19:23]
  128.                 self.rotation = Quaternion( rot[0], rot[1], rot[2], rot[3] )
  129.  
  130.                 #// Index of the bone's parent in the SCM_BoneData array
  131.                 self.parent_index = readout[24]
  132.                
  133.                 # Read bone name
  134.                 #oldpos = file.tell()
  135.                 #file.seek(bone[..], 0)
  136.                 #self.name = file.readline()
  137.                 #file.seek(oldpos, 0)
  138.  
  139.                
  140.                 return self
  141.        
  142.         def dump(self):
  143.                 print 'Bone       ', self.name
  144.                 print 'Position   ', self.position
  145.                 print 'Rotation   ', self.rotation
  146.                 print 'Parent Idx ', self.parent_index         
  147.                 if (self.parent != 0):
  148.                         print 'Parent     ', self.parent.name
  149.                 else:
  150.                         print 'Parent     <NONE>'              
  151.                 print 'Rest Pose Inv.'
  152.                 #for row in range(4):
  153.                         #print '  ', self.rest_pose_inv[row]           
  154.  
  155.  
  156. class scm_vertex :
  157.        
  158.         position = []
  159.         tangent = []
  160.         normal = []
  161.         binormal = []
  162.         uv1 = []
  163.         uv2 = []
  164.         bone_index = []
  165.  
  166.         def __init__(self):
  167.                 self.position   = Vector(0,0,0)
  168.                 self.tangent    = Vector(0,0,0)
  169.                 self.normal     = Vector(0,0,0)
  170.                 self.binormal   = Vector(0,0,0)
  171.                 self.uv1        = Vector(0,0)
  172.                 self.uv2        = Vector(0,0)
  173.                 self.bone_index = [0]*4
  174.  
  175.         def load(self, file):
  176.                
  177.                 vertstruct = '3f3f3f3f2f2f4B'
  178.                 vertsize = struct.calcsize(vertstruct)
  179.                
  180.                 buffer = file.read(vertsize)
  181.                 vertex = struct.unpack(vertstruct, buffer)
  182.                
  183.                 self.position = vertex[0:3]
  184.                 self.tangent = vertex[3:6]
  185.                 self.normal = vertex[6:9]
  186.                 self.binormal = vertex[9:12]
  187.                 self.uv1 = vertex[12:14]
  188.                 self.uv2 = vertex[14:16]
  189.                 self.bone_index = vertex[16:20]
  190.                
  191.                 return self
  192.        
  193.         def dump(self):
  194.                 print 'position ', self.position
  195.                 print 'tangent  ', self.tangent
  196.                 print 'normal   ', self.normal
  197.                 print 'binormal ', self.binormal
  198.                 print 'uv1      ', self.uv1
  199.                 print 'uv2      ', self.uv2
  200.                 print 'bones    ', self.bone_index
  201.  
  202.  
  203. class scm_mesh :
  204.        
  205.         bones = []
  206.         vertices = []
  207.         faces = []
  208.         info = []
  209.         filename = ""
  210.        
  211.         def __init__(self):
  212.                 self.bones = []
  213.                 self.vertices = []
  214.                 self.faces = []
  215.                 self.info = []
  216.                 self.filename = ""
  217.  
  218.         def load(self, filename):      
  219.                 global xy_to_xz_transform
  220.                 self.filename = filename
  221.                 scm = file(filename, 'rb')
  222.                
  223.                 # Read header
  224.                 headerstruct = '4s11L'
  225.                 buffer = scm.read(struct.calcsize(headerstruct))
  226.                 header = struct.unpack(headerstruct, buffer)
  227.                
  228.                 marker = header[0]
  229.                 version = header[1]
  230.                 boneoffset = header[2]
  231.                 bonecount = header[3]
  232.                 vertoffset = header[4]
  233.                 extravertoffset = header[5]
  234.                 vertcount = header[6]
  235.                 indexoffset = header[7]
  236.                 indexcount = header[8]
  237.                 tricount = indexcount / 3 #?
  238.                 infooffset = header[9]
  239.                 infocount = header[10]
  240.                 totalbonecount = header[11]
  241.                
  242.                 if (marker != 'MODL'):
  243.                         print 'Not a valid scm'
  244.                         return
  245.                        
  246.                 if (version != 5):
  247.                         print 'Unsupported version (%d)' % version
  248.                         return
  249.                
  250.                 # Read bone names
  251.                 scm.seek(pad(scm.tell()), 1)
  252.                 length = (boneoffset - 4) - scm.tell()
  253.  
  254.                 # This should probably be handeled by the scm_bone reader as it contains the nameoffset. But I'm lazy
  255.                 # and logic tells me it's written in the same order as the bones.
  256.                 buffer = scm.read(length)              
  257.                 rawnames = struct.unpack(str(length)+'s',buffer)               
  258.                 bonenames = string.split(rawnames[0],'\0')[:-1]
  259.                
  260.                 # Read bones
  261.                 scm.seek(boneoffset, 0)
  262.                 for b in range(0, totalbonecount):
  263.                         bone = scm_bone(bonenames[b])
  264.                         bone.load(scm)                 
  265.                         self.bones.append(bone)
  266.                                
  267.                 #show them (for debug)                         
  268.                 #for b in range(0, totalbonecount):
  269.                         #print "bone %d has %d children = " %(b, self.bones[b].numchildren)
  270.                
  271.                 # Set parent (this could probably be done in the other loop since parents are usually written to the file
  272.                 # before the children. But you never know..
  273.                 for bone in self.bones:
  274.                         if (bone.parent_index != -1):
  275.                                 bone.parent = self.bones[bone.parent_index]
  276.                         else:
  277.                                 bone.parent = 0
  278.                
  279.                         # the bone matrix relative to the parent.
  280.                         if (bone.parent != 0):
  281.                                 mrel = (bone.rel_mat) * Matrix(bone.parent.rel_mat).invert() #* xy_to_xz_transform
  282.                                 bone.rel_matrix_inv = Matrix(mrel).invert()
  283.                         else:
  284.                                 mrel = bone.rel_mat * xy_to_xz_transform  #there is no parent
  285.                                 bone.rel_matrix_inv = Matrix(mrel).invert()
  286.                                
  287.                                
  288.                 #self.rest_pose = Matrix(self.rest_pose[0], self.rest_pose[1], self.rest_pose[2], self.rest_pose[3])            in sc =  rest pose inv
  289.                 #self.rel_mat = (Matrix(self.rest_pose).invert()) * xy_to_xz_transform                                  in sc = rest pose yz
  290.                        
  291.                
  292.                 # Read vertices
  293.                 scm.seek(vertoffset, 0)
  294.                 for b in range(0, vertcount):
  295.                         vert = scm_vertex()
  296.                         vert.load(scm)                 
  297.                         self.vertices.append(vert)
  298.                
  299.                 # Read extra vertex data               
  300.                 # Not implemented in Sup Com 1.0!
  301.                
  302.                 # Read indices (triangles)
  303.                 tristruct = '3h'
  304.                 trisize = struct.calcsize(tristruct)
  305.                        
  306.                 scm.seek(indexoffset, 0)                       
  307.                 for t in range(tricount):                      
  308.                         buffer = scm.read(trisize)
  309.                         face = struct.unpack(tristruct, buffer)
  310.                         self.faces.append(list(face))
  311.                        
  312.                
  313.                 # Read info
  314.                 if (infocount > 0):
  315.                         scm.seek(infooffset)
  316.                         buffer = scm.read()
  317.                         rawinfo = struct.unpack(str(len(buffer))+'s',buffer)           
  318.                         self.info = string.split(rawinfo[0],'\0')[:-1]
  319.                
  320.                 scm.close()    
  321.                
  322.                 return self
  323.  
  324.         def dump(self):
  325.                 print ''
  326.                 print 'Filename: ', self.filename
  327.                 print 'Bones ', len(self.bones)
  328.                 print 'Verts ', len(self.vertices)
  329.                 print 'Faces ', len(self.faces)        
  330.                 print ''
  331.                 print 'INFO: '
  332.                 for info in self.info:
  333.                         print '  ', info
  334.                
  335.  
  336.  
  337. class sca_bone:
  338.  
  339.         position = []
  340.         rotation = []
  341.         #changed: rototation -> rotation
  342.         pose_pos = []
  343.         pose_rot = []
  344.         rel_matrix = []
  345.         pose_matrix = []
  346.         #rel_mat = None
  347.  
  348.         def __init__(self, pos, rot):
  349.                 self.position = pos
  350.                 self.rotation = rot
  351.                 self.rel_matrix = None
  352.                 self.pose_matrix = None
  353.                 #self.rel_mat = None
  354.                
  355.  
  356.         def dump(self):
  357.                 print 'Position ', self.position
  358.                 print 'Rotation ', self.rotation
  359.                
  360.  
  361.  
  362. class sca_frame:
  363.  
  364.         keytime = 0.0
  365.         keyflags = 0
  366.         bones = []
  367.         anim = None
  368.        
  369.         def __init__(self, anim):
  370.                 self.keytime = 0.0
  371.                 self.keyflags = 0
  372.                 self.bones = []
  373.                 self.anim = anim
  374.  
  375.         def load(self, file):          
  376.                 frameheader_fmt = 'fl'
  377.                 frameheader_size = struct.calcsize(frameheader_fmt)
  378.                 buffer = file.read(frameheader_size)
  379.                
  380.                 (self.keytime, self.keyflags) = struct.unpack(frameheader_fmt, buffer)
  381.                
  382.                 posrot_fmt = '3f4f'
  383.                 posrot_size = struct.calcsize(posrot_fmt)
  384.                
  385.                 for b in range (0, self.anim.numbones) :
  386.                         buffer = file.read(posrot_size)
  387.                         posrot = struct.unpack(posrot_fmt, buffer)                     
  388.                         bone = sca_bone(posrot[0:3], posrot[3:7])                      
  389.                         self.bones.append(bone)
  390.  
  391.         def dump(self):
  392.                 print 'Time  ', self.keytime
  393.                 print 'Flags ', self.keyflags
  394.                
  395.  
  396.  
  397. class sca_anim :
  398.        
  399.         filename = ""
  400.         frames = []
  401.         bones = []
  402.         bonelinks = []
  403.         bonenames = []
  404.         numbones = 0
  405.         duration = 0.0
  406.        
  407.         def __init__(self):
  408.                 self.filename = ""
  409.                 self.frames = []
  410.                 self.bones = []
  411.                 self.numbones = 0
  412.                 self.bonelinks = []
  413.                 self.bonenames = []
  414.                 self.duration = 0.0
  415.  
  416.  
  417.  
  418.  
  419.         def calcAnimBoneMatrix(self, frame, bone_index, armature_bones, frame_index):
  420.                 global xy_to_xz_transform
  421.                
  422.                 bone = frame.bones[bone_index];
  423.                 parent_index = self.bonelinks[bone_index]
  424.  
  425.                 # note that the pos/rot of the armature_bones are still in relative supcom coordinates.
  426.                 # so we can correct the relative pos-increase by the relative armature-increase
  427.                 pose_rel_pos = Vector(bone.position)
  428.                 pose_rel_rot = Quaternion(bone.rotation)
  429.  
  430.                 # the matrix representation... it's easier to work with matrix notation I think.
  431.                 # the rotation:
  432.                 pose_rel_matrix = (pose_rel_rot.toMatrix()).resize4x4()
  433.                
  434.                
  435.                 # the translation:
  436.                 for i in xrange(3):
  437.                         pose_rel_matrix[3][i] = pose_rel_pos[i]
  438.  
  439.                 #pose_rel_matrix = pose_rel_matrix * xy_to_xz_transform
  440.                 #rel_pos = pose_rel_pos - armature_bones[bone_index].position
  441.                 #rel_rot = DifferenceQuats(pose_rel_rot, armature_bones[bone_index].rotation)
  442.                
  443.                 if (parent_index == -1) :
  444.                         # for the root bone, this is already the absolution pos/rot, but,
  445.                         # the root bone should be rotated into the blender coordinates
  446.                         bone.rel_matrix = pose_rel_matrix * xy_to_xz_transform
  447.                        
  448.                         #testmat =(bone.rel_mat) * Matrix(bone.parent.rel_mat).invert()
  449.                        
  450.                 if (parent_index >= 0):
  451.                         # for all the children, they are seen relative to the parents.
  452.                         bone.rel_matrix = pose_rel_matrix
  453.                
  454.                 # Call all children
  455.                 for b in range(len(self.bonelinks)):
  456.                         if (self.bonelinks[b] == bone_index):
  457.                                 self.calcAnimBoneMatrix(frame, b, armature_bones, frame_index)
  458.  
  459.                 # the (rendered) animation positions are relative to
  460.                 # both the parent, and to the relative rest position of the bone.
  461.                 bone.pose_matrix = Matrix(bone.rel_matrix * armature_bones[bone_index].rel_matrix_inv)#* xy_to_xz_transform)
  462.  
  463.                 #bone.pose_matrix = bone.pose_matrix * xy_to_xz_transform
  464.                 # pose position relative to the armature
  465.                 bone.pose_pos = Vector(bone.pose_matrix.translationPart())
  466.                
  467.                 bone.pose_rot = bone.pose_matrix.toQuat()
  468.                
  469.                 #test = bone.pose_matrix.toQuat()
  470.                 #bone.pose_rot = Quaternion( test.x, test.y, test.z, test.w)
  471.  
  472.  
  473.         def load(self, filename):
  474.                 self.filename = filename
  475.                 sca = file(filename, 'rb')
  476.                
  477.                 # Read header
  478.                 headerstruct = '4sllflllll'
  479.                 buffer = sca.read(struct.calcsize(headerstruct))
  480.                 header = struct.unpack(headerstruct, buffer)
  481.                
  482.                 (magic,             \
  483.                  version,           \
  484.                  numframes,         \
  485.                  self.duration,     \
  486.                  self.numbones,     \
  487.                  namesoffset,       \
  488.                  linksoffset,       \
  489.                  animoffset,        \
  490.                  framesize) = struct.unpack(headerstruct, buffer)
  491.                
  492.                 if (magic != 'ANIM'):
  493.                         print 'Not a valid .sca animation file'
  494.                         return
  495.                
  496.                 if (version != 5):
  497.                         print 'Unsupported sca version: %d'  % version
  498.                         return
  499.                
  500.                 # Read bone names
  501.                 sca.seek(namesoffset, 0)
  502.                 length = linksoffset - namesoffset
  503.                 buffer = sca.read(length)              
  504.                 rawnames = struct.unpack(str(length)+'s',buffer)               
  505.                 self.bonenames = string.split(rawnames[0], '\0')[:-1]
  506.                
  507.                 # Read links
  508.                 links_fmt = str(self.numbones)+'l'
  509.                 links_size = struct.calcsize(links_fmt)
  510.                
  511.                 buffer = sca.read(links_size)
  512.                 self.bonelinks = struct.unpack(links_fmt, buffer)
  513.                        
  514.                 posrot_fmt = '3f4f'
  515.                 posrot_size = struct.calcsize(posrot_fmt)
  516.                
  517.                 sca.seek(animoffset)
  518.                 buffer = sca.read(posrot_size)
  519.                 root_posrot = struct.unpack(posrot_fmt, buffer)
  520.                
  521.                 for f in range (0, numframes) :
  522.                         frame = sca_frame(self)
  523.                         frame.load(sca)
  524.                         self.frames.append(frame)
  525.                
  526.                 sca.close()
  527.                
  528.                 return self
  529.  
  530.         def dump(self):
  531.                 print 'SCA:  ', self.filename
  532.                 print 'Duration: %fs' % self.duration
  533.                 print 'Num loaded frames ', len(self.frames)
  534.                
  535.                 print 'Bonelinks'              
  536.                 for link in self.bonelinks:
  537.                         print ' ', link
  538.                
  539.                 print 'Bone names'
  540.                 for name in self.bonenames:
  541.                         print ' ', name
  542.        
  543.                                
  544. def pad(size):
  545.         val = 32 - (size % 32)
  546.        
  547.         if (val > 31):
  548.                 return 0
  549.                
  550.         return val
  551.                        
  552.                        
  553. #**************************************************************************************************
  554. # Blender Interface
  555. #**************************************************************************************************
  556.  
  557. def read_scm() :
  558.         global xy_to_xz_transform
  559.         global scm_filepath # [0] both [1] path [2] name
  560.         global sca_filepath # [0] both [1] path [2] name
  561.        
  562.         print "=== LOADING Sup Com Model ==="
  563.         print ""
  564.        
  565.         xy_to_xz_transform.resize4x4()
  566.        
  567.         scene = Blender.Scene.GetCurrent()      
  568.        
  569.         mesh = scm_mesh()
  570.        
  571.         if (mesh.load(scm_filepath[0]) == None):
  572.                 print 'Failed to load %s' %scm_filepath[2]
  573.                 return
  574.        
  575.         ProgBarLSCM = ProgressBar( "Imp: load SCM", (2*len(mesh.vertices) + len(mesh.faces)))  
  576.        
  577.         armature_name = string.rstrip(scm_filepath[2], ".scm")
  578.         print "armature ", armature_name
  579.        
  580.         ###             CREATE ARMATURE
  581.         armObj = Object.New('Armature', armature_name)  #bad
  582.        
  583.         armData = Blender.Armature.Armature(armature_name)
  584.         armData.drawAxes = True
  585.         armData.makeEditable() 
  586.          
  587.         for index in range(len(mesh.bones)):
  588.                 bone = mesh.bones[index]       
  589.                 blender_bone = Blender.Armature.Editbone()             
  590.                 #not nice parent may not exist,  but usualy should exist (depends on storing in scm)
  591.                 if (bone.parent != 0) :
  592.                         blender_bone.parent = armData.bones[bone.parent.name]
  593.                
  594.  
  595.                 #blender_bone.options(Armature.CONNECTED)
  596.                 blender_bone.matrix = Matrix(bone.rel_mat * xy_to_xz_transform)        
  597.                                
  598.                 armData.bones[bone.name] = blender_bone
  599.  
  600.        
  601.         #save changes (after linking!)
  602.         armObj.link(armData)
  603.         scene.link(armObj)
  604.         #scene.objects.new(armData)
  605.         ###             CREATE MESH
  606.         meshData = Blender.Mesh.New('Mesh')
  607.        
  608.         ProgBarLSCM.text = "IMP: Verticles"
  609.         #add verts
  610.         vertlist = []
  611.         for vert in mesh.vertices:
  612.                 ProgBarLSCM.do()
  613.                 vertlist.append(Vector(vert.position)*xy_to_xz_transform)
  614.        
  615.         meshData.verts.extend(vertlist)
  616.  
  617.         meshData.vertexUV = True
  618.         for i_v in xrange(len(meshData.verts)):
  619.                 uv1 = mesh.vertices[i_v].uv1
  620.                 meshData.verts[i_v].uvco = Vector(uv1[0], 1.0-uv1[1])
  621.        
  622.         ProgBarLSCM.text = "IMP: Faces"
  623.        
  624.         #reverse faces
  625.         #for face in mesh.faces:
  626.         #       face.reverse()
  627.                
  628.         #add faces
  629.         meshData.faces.extend(mesh.faces)      
  630.         meshData.faceUV = True 
  631.         for face in meshData.faces :
  632.                 ProgBarLSCM.do()
  633.                 face.uv = [face.verts[i].uvco for i in range(3)]
  634.        
  635.         #put in scene
  636.         mesh_obj = Object.New('Mesh','Mesh')
  637.         mesh_obj.link(meshData)
  638.        
  639.         #scene.objects.new(meshData)
  640.  
  641.         #assigns vertex groups #mesh must be in object
  642.         for bone in mesh.bones:
  643.                 meshData.addVertGroup(bone.name)
  644.  
  645.         for vertex_index in range(len(mesh.vertices)):
  646.                 ProgBarLSCM.do()
  647.                 vertex = mesh.vertices[vertex_index]
  648.                 bone_index = vertex.bone_index[0]
  649.                 meshData.assignVertsToGroup(mesh.bones[bone_index].name, [vertex_index], 1.0, Blender.Mesh.AssignModes.REPLACE) #'REPLACE'
  650.        
  651.         # it works... but you've to select/change to edit mode for the object to show up.
  652.         # dunno why that is, maybe because Nmesh is depracated.
  653.         meshData.update()
  654.                
  655.         #bones disapear wen update ?
  656.         #armData.update()
  657.  
  658.         scene.link(mesh_obj)
  659.        
  660.         #must be in scene
  661.         #armObj = None
  662.         #meshObj = None
  663.         #for obj in Object.Get():
  664.         #       if obj.getType() == 'Armature':
  665.         #               armObj = obj
  666.         #       if obj.getType() == 'Mesh':
  667.         #               meshObj = obj
  668.                        
  669.         #mesh_obj = Blender.Object.Get('Mesh')
  670.         armObj.makeParentDeform([mesh_obj], 0, 0)
  671.         #makeParentVertex(objects, indices, noninverse=0, fast=0)
  672.        
  673.         meshData.update()
  674.         armData.update()
  675.  
  676.         if len(mesh.info):
  677.                 print "=== INFO ==="
  678.                 for info in mesh.info:
  679.                         print "",info
  680.  
  681.         print "=== COMPLETE ==="
  682.        
  683.         if sca_filepath[0] != "" :
  684.                 read_anim(mesh)
  685.  
  686.        
  687.  
  688.  
  689. def read_anim(mesh):
  690.         global xy_to_xz_transform
  691.         global sca_filepath # [0] both [1] path [2] name
  692.        
  693.         #xy_to_xz_quat = xy_to_xz_transform.toQuat()
  694.        
  695.         print "=== LOADING Sup Com Animation ==="
  696.         print ""
  697.        
  698.         anim = sca_anim()
  699.         anim.load(sca_filepath[0])
  700.        
  701.         ProgBarLSCA = ProgressBar( "Imp: Frames", len(anim.frames))
  702.        
  703.         scene = Blender.Scene.GetCurrent()
  704.        
  705.         arm_obj = None
  706.         for obj in scene.objects:
  707.                 data = obj.getData()
  708.                 if type(data) is Blender.Types.ArmatureType:
  709.                         arm_obj = obj
  710.                         break
  711.                
  712.         if arm_obj == None:
  713.                 print "couldn't apply animation, no armature in the scene"
  714.                 return
  715.         #arm_obj = armObj
  716.  
  717.         print arm_obj.name
  718.         #actionpath, actionname = os.path.split(filename)
  719.        
  720.         action = Blender.Armature.NLA.NewAction(sca_filepath[2])
  721.         action.setActive(arm_obj)
  722.        
  723.         pose = arm_obj.getPose()
  724.        
  725.         for frame_index in xrange(len(anim.frames)):
  726.                 ProgBarLSCA.do()
  727.  
  728.                 Blender.Set("curframe", frame_index+1)
  729.                 frame = anim.frames[frame_index]
  730.  
  731.                 # this changes the relative orientation (supcom) to absolute orientation (blender)
  732.                 anim.calcAnimBoneMatrix(frame, 0, mesh.bones, frame_index)
  733.  
  734.                 # this inserts the bones information into blender.
  735.                 for b in range(len(frame.bones)):
  736.                         pose_bone = pose.bones[anim.bonenames[b]]
  737.                        
  738.                         if (pose_bone == None):
  739.                                 print 'Frame %d - Bone \"%s\" not found' % (frame_index, anim.bonenames[b])
  740.                                 continue       
  741.                                
  742.                         anim_bone = frame.bones[b]
  743.                        
  744.                         pose_bone.loc =  anim_bone.pose_pos
  745.                         pose_bone.quat = anim_bone.pose_rot
  746.                         pose_bone.size = Vector(1,1,1)
  747.                                        
  748.                         pose.update()
  749.                         pose_bone.insertKey(arm_obj, frame_index+1, [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT, Blender.Object.Pose.SIZE])
  750.                         pose.update()
  751.        
  752.         Blender.Set("curframe", 1)
  753.        
  754.         #scene = Blender.Scene.GetCurrent()
  755.         context = scene.getRenderingContext()
  756.  
  757.         context.endFrame(len(anim.frames)+1)
  758.        
  759.         print "=== COMPLETE ==="
  760.  
  761.  
  762.  
  763. ######################################################
  764. # GUI
  765. ######################################################
  766.        
  767. log = []
  768. log_max_lines = 14
  769. LOG_FILE = None
  770.  
  771. #log to file
  772. def LOGn(message):
  773.         global LOG_FILE
  774.         global LOG_ENABLE
  775.         global LOG_FILENAME
  776.        
  777.         if LOG_ENABLE :
  778.                 if LOG_FILE == None :                  
  779.                         LOG_FILE = open( LOG_FILENAME, 'w')
  780.                         LOG_FILE.write('SupCom Exporter LOG File:\n\n')
  781.                        
  782.                         LOGp( "LOG enabled: %s" % (LOG_FILENAME))
  783.                         Log(message + '\n')
  784.                        
  785.                 else :         
  786.                         LOG_FILE.write(message + '\n')
  787.                        
  788. #Log to file, to console and exp window                                
  789. def LOGp(message):
  790.         global log, log_max_lines
  791.        
  792.         LOGn(message)
  793.         print message  
  794.         log.append(message)
  795.        
  796.         if len(log) > log_max_lines:
  797.                 del log[0]
  798.                
  799.                
  800. counter = []
  801. cLog = []
  802. #log for a amount of errors like vertex errors
  803. def countLOG(message):
  804.         global cLog
  805.         global counter
  806.        
  807.         cont = False
  808.        
  809.         for i in xrange(len(cLog)):
  810.                 if cLog[i] == message:
  811.                         cont = True
  812.                         counter[i] +=1
  813.                         break
  814.                        
  815.         if not cont :
  816.                
  817.                 cLog.append( message)
  818.                 counter.append( 1)
  819.  
  820. def closeLog():
  821.         global cLog, LOG_FILE
  822.         global counter
  823.        
  824.         for i in xrange(len(cLog)):
  825.                 LOGp("%s (Times:%d)" % (cLog[i], counter[i]))
  826.  
  827.         if LOG_FILE != None :
  828.                 LOG_FILE.close()       
  829.                
  830.         Blender.Window.RedrawAll()
  831.                
  832.  
  833. class ProgressBar :
  834.  
  835.         global PROG_BAR_STEP
  836.         global PROG_BAR_ENABLE
  837.        
  838.         progress = 0
  839.         progressold = 0
  840.         current = 0    
  841.         end = 0
  842.         div = 0
  843.         text = "None"  
  844.        
  845.         def __init__(self, text, end):
  846.                 self.progress = 0
  847.                 self.progressold = 0
  848.                 self.current = 0
  849.                 self.end = end
  850.                 self.text = text
  851.                 self.div = PROG_BAR_STEP
  852.                
  853.                 #it looks like blender needs to init this progress bar with 0.0
  854.                 if PROG_BAR_ENABLE :
  855.                         Blender.Window.DrawProgressBar ( 0.0 , text)
  856.                
  857.         def do(self):  
  858.                
  859.                 if PROG_BAR_ENABLE :
  860.                         self.current += 1
  861.                         self.progress = (self.current*self.div)/self.end
  862.                        
  863.                         if self.progress != self.progressold :
  864.                                 self.progressold = self.progress
  865.                                 Blender.Window.DrawProgressBar ( float(self.progress)/self.div , self.text)
  866.                                
  867.  
  868.  
  869.  
  870. # Events
  871. EVENT_DRAW = 1
  872. EVENT_EXIT = 2
  873. EVENT_SCMDIR = 3
  874. EVENT_SCADIR = 4
  875.  
  876.  
  877. show_log = 0
  878.  
  879. sca_filepath = [ "", "", "None"]
  880. scm_filepath = [ "", "", "None"]
  881.  
  882. def anim_fileselector_callback(filename):
  883.         global sca_filepath
  884.        
  885.         sca_filepath[0] = filename
  886.        
  887.         #print "Filename%sI\n" % filename
  888.         #if ( filename != "" ) :
  889.                 #sca_filepath = [ "" , "None"]
  890.                 #return
  891.         #else :
  892.        
  893.         length = len(filename)
  894.         if filename[length-4:length] == ".sca" :               
  895.                 sca_filepath[1], sca_filepath[2]  = os.path.split(filename)
  896.         else :
  897.                 sca_filepath[0] = ""
  898.                 sca_filepath[1] = ""
  899.                 sca_filepath[2] = "Non Supported"
  900.         #sca_filepath[1] , sca_filepath[2] = os.path.split(filename)
  901.  
  902.  
  903. def fileselector_callback(filename):
  904.         global scm_filepath
  905.         #sadly you cant check whether the cancel button is pressed
  906.         scm_filepath[0] = filename
  907.         #print "Filename%sI\n" % filename
  908.         #if ( filename != "" ) :
  909.         length = len(filename)
  910.         if filename[length-4:length] == ".scm" :               
  911.                 scm_filepath[1], scm_filepath[2]  = os.path.split(filename)
  912.         else :
  913.                 scm_filepath[0] = ""
  914.                 scm_filepath[1] = ""
  915.                 scm_filepath[2] = "Non Supported"
  916.         #       Exit()
  917.        
  918.  
  919. #def forcequit()
  920. #       Exit()
  921.  
  922.        
  923. def draw():
  924.         global EVENT_DRAW, EVENT_EXIT,EVENT_SCADIR,EVENT_SCADIR
  925.         global scm_filepath, sca_filepath, show_log
  926.         global log_max_lines, log
  927.         global VERSION
  928.  
  929.         # Titles
  930.         glClear(GL_COLOR_BUFFER_BIT)
  931.        
  932.         top = 60 + log_max_lines * 12 + 8
  933.         #top = 500
  934.         top_x = 304
  935.        
  936.         glColor3f(0.8, 0.8, 1)
  937.         glRecti(top_x, top, 4, 4)
  938.         glBegin(GL_LINES)
  939.         glColor3f(0.8, 0.8, 0.8)
  940.         glVertex2d(4, top)
  941.         glVertex2d(4, 4)
  942.         glVertex2d(4, 4)
  943.         glVertex2d(top_x, 4)
  944.         glColor3f(0.5, 0.5, 0.5)
  945.         glVertex2d(top_x, top)
  946.         glVertex2d(4, top)
  947.         glVertex2d(top_x, top)
  948.         glVertex2d(top_x, top-1)
  949.         glEnd()
  950.        
  951.         glColor3f(0, 0, 0)
  952.         glRasterPos2d(10, top-16)
  953.         Text("Supreme Commander Importer " + VERSION)  
  954.  
  955.         # Show exporting log
  956.         if show_log:
  957.  
  958.                 for index in range(0, len(log)):
  959.                         i = (len(log) - 1) - index
  960.                         glRasterPos2i(10, 40 + i*12)
  961.                         Text(log[index]) #, 'tiny')
  962.                
  963.                
  964.                 Button("Close", EVENT_EXIT , 10, 10, 80, 18)
  965.  
  966.                 # Exporter GUI
  967.         else:
  968.                
  969.                
  970.  
  971.                 #if scm_directory.val == 'scm':
  972.                 #if scm_filepath[1] == 'None' :
  973.                         #automatically launch the browse window once
  974.                 #       Blender.Window.FileSelector (fileselector_callback, "Select SCM File", "*.scm")
  975.                         #Exit() # why dont you go to exit?, never
  976.                 #       forcequit()
  977.  
  978.                
  979.                 Blender.Draw.Button("Browse SCM", EVENT_SCMDIR, 10, 45, 80, 18, "Select scm")
  980.                 Blender.Draw.Button("Browse SCA", EVENT_SCADIR, 10, 80, 80, 18, "Select sca")  
  981.                
  982.                 glRasterPos2d(100, 47)
  983.                 if scm_filepath[0] == "" :
  984.                         Text("SCM: " + scm_filepath[2])
  985.                 else:
  986.                         Text(":" + scm_filepath[2])
  987.                        
  988.                 glRasterPos2d(100, 82)
  989.                 if sca_filepath[0] == "" :
  990.                         Text("SCA: " + sca_filepath[2])
  991.                 else :
  992.                         Text(":" + sca_filepath[2])
  993.  
  994.                 # Draw and Exit Buttons
  995.                 Button("Import", EVENT_DRAW , 10, 10, 80, 18)
  996.                 Button("Exit", EVENT_EXIT , 100, 10, 80, 18)
  997.  
  998. def event(evt, val):   
  999.         if (evt == QKEY and not val):
  1000.                 Exit()
  1001.  
  1002. def bevent(evt):
  1003.         global EVENT_DRAW,EVENT_EXIT
  1004.         global scm_filepath
  1005.         global show_log
  1006.  
  1007.         if (evt == EVENT_EXIT):
  1008.                 #show_log = 1
  1009.                 Exit()
  1010.        
  1011.         elif (evt == EVENT_SCMDIR):
  1012.                 Blender.Window.FileSelector (fileselector_callback, "Select SCM File")
  1013.                 Blender.Redraw()
  1014.                
  1015.         elif (evt == EVENT_SCADIR):
  1016.                 if scm_filepath[0] != "" :                     
  1017.                         Blender.Window.FileSelector (anim_fileselector_callback, "Select SCA File", scm_filepath[1]+"\\")                      
  1018.                 else :
  1019.                         Blender.Window.FileSelector (anim_fileselector_callback, "Select SCA File")                    
  1020.                 Blender.Redraw()
  1021.        
  1022.         elif (evt == EVENT_DRAW):
  1023.                
  1024.                 if (scm_filepath[0] != ''):            
  1025.                         show_log = 1                   
  1026.                         read_scm()
  1027.                        
  1028.                 #if (sca_filepath[0] != ''):
  1029.                 #       show_log = 1
  1030.                 #       read_sca()
  1031.                
  1032.                 Blender.Redraw()
  1033.  
  1034.                
  1035.  
  1036. Register(draw, event, bevent)
  1037.  
  1038. #open fileselector automaticly
  1039. Blender.Window.FileSelector (fileselector_callback, "Select SCM File")