Updated some of the internal documentation (comments, etc) to better describe what...
[blender-addons-contrib.git] / io_export_md3.py
index 72768da249c97ef403f1818b6f3dd4596a45e42f..64876ac7113282da7a2a0128790cd41e39aa71b1 100644 (file)
 #
 # ##### END GPL LICENSE BLOCK #####
 
-__author__ = ["Xembie"]
-__version__ = '0.7'
-__url__ = ["www.blender.org"]
-
-"""
-Name: 'Quake Model 3 (.md3)...'
-Blender: 253
-Group: 'Export'
-Tooltip: 'Save a Quake Model 3 File'
-"""
-
-bl_addon_info = {
-    'name': 'Quake Model 3 (.md3',
+bl_info = {
+    'name': 'Quake Model 3 (.md3)',
     'author': 'Xembie',
-    'version': (0,7),
+    'version': (0, 7),
     'blender': (2, 5, 3),
-    'api': 31667,
-    'location': 'File > Import',
-    'description': 'Import files in the Autocad DXF format (.dxf)',
+    'location': 'File > Export',
+    'description': 'Save a Quake Model 3 File)',
     'warning': '', # used for warning icon and text in addons panel
-    'wiki_url': 'http://wiki.blender.org/index.php/Extensions:2.5/Py/'\
+    'wiki_url': 'http://wiki.blender.org/index.php/Extensions:2.6/Py/'\
         'Scripts/',
     'tracker_url': 'http://projects.blender.org/tracker/index.php?'\
-           'func=detail&aid=23160&group_id=153&atid=468',
-    'category': 'Import/Export'}
+        'func=detail&aid=23160',
+    'category': 'Import-Export'}
+
+
 import bpy,struct,math,os
 
 MAX_QPATH = 64
@@ -56,355 +46,355 @@ MD3_MAX_TRIANGLES = 8192
 MD3_XYZ_SCALE = 64.0
 
 class md3Vert:
-       xyz = []
-       normal = 0
-       binaryFormat = "<3hH"
-       
-       def __init__(self):
-               self.xyz = [0.0, 0.0, 0.0]
-               self.normal = 0
-               
-       def GetSize(self):
-               return struct.calcsize(self.binaryFormat)
-       
-       # copied from PhaethonH <phaethon@linux.ucla.edu> md3.py
-       def Decode(self, latlng):
-               lat = (latlng >> 8) & 0xFF;
-               lng = (latlng) & 0xFF;
-               lat *= math.pi / 128;
-               lng *= math.pi / 128;
-               x = math.cos(lat) * math.sin(lng)
-               y = math.sin(lat) * math.sin(lng)
-               z =                 math.cos(lng)
-               retval = [ x, y, z ]
-               return retval
-       
-       # copied from PhaethonH <phaethon@linux.ucla.edu> md3.py
-       def Encode(self, normal):
-               x = normal[0]
-               y = normal[1]
-               z = normal[2]
-               # normalize
-               l = math.sqrt((x*x) + (y*y) + (z*z))
-               if l == 0:
-                       return 0
-               x = x/l
-               y = y/l
-               z = z/l
-               
-               if (x == 0.0) & (y == 0.0) :
-                       if z > 0.0:
-                               return 0
-                       else:
-                               return (128 << 8)
-               
-               lng = math.acos(z) * 255 / (2 * math.pi)
-               lat = math.atan2(y, x) * 255 / (2 * math.pi)
-               retval = ((int(lat) & 0xFF) << 8) | (int(lng) & 0xFF)
-               return retval
-               
-       def Save(self, file):
-               tmpData = [0] * 4
-               tmpData[0] = int(self.xyz[0] * MD3_XYZ_SCALE)
-               tmpData[1] = int(self.xyz[1] * MD3_XYZ_SCALE)
-               tmpData[2] = int(self.xyz[2] * MD3_XYZ_SCALE)
-               tmpData[3] = self.normal
-               data = struct.pack(self.binaryFormat, tmpData[0], tmpData[1], tmpData[2], tmpData[3])
-               file.write(data)
-               
+    xyz = []
+    normal = 0
+    binaryFormat = "<3hH"
+    
+    def __init__(self):
+        self.xyz = [0.0, 0.0, 0.0]
+        self.normal = 0
+        
+    def GetSize(self):
+        return struct.calcsize(self.binaryFormat)
+    
+    # copied from PhaethonH <phaethon@linux.ucla.edu> md3.py
+    def Decode(self, latlng):
+        lat = (latlng >> 8) & 0xFF;
+        lng = (latlng) & 0xFF;
+        lat *= math.pi / 128;
+        lng *= math.pi / 128;
+        x = math.cos(lat) * math.sin(lng)
+        y = math.sin(lat) * math.sin(lng)
+        z =                 math.cos(lng)
+        retval = [ x, y, z ]
+        return retval
+    
+    # copied from PhaethonH <phaethon@linux.ucla.edu> md3.py
+    def Encode(self, normal):
+        x = normal[0]
+        y = normal[1]
+        z = normal[2]
+        # normalize
+        l = math.sqrt((x*x) + (y*y) + (z*z))
+        if l == 0:
+            return 0
+        x = x/l
+        y = y/l
+        z = z/l
+        
+        if (x == 0.0) & (y == 0.0) :
+            if z > 0.0:
+                return 0
+            else:
+                return (128 << 8)
+        
+        lng = math.acos(z) * 255 / (2 * math.pi)
+        lat = math.atan2(y, x) * 255 / (2 * math.pi)
+        retval = ((int(lat) & 0xFF) << 8) | (int(lng) & 0xFF)
+        return retval
+        
+    def Save(self, file):
+        tmpData = [0] * 4
+        tmpData[0] = int(self.xyz[0] * MD3_XYZ_SCALE)
+        tmpData[1] = int(self.xyz[1] * MD3_XYZ_SCALE)
+        tmpData[2] = int(self.xyz[2] * MD3_XYZ_SCALE)
+        tmpData[3] = self.normal
+        data = struct.pack(self.binaryFormat, tmpData[0], tmpData[1], tmpData[2], tmpData[3])
+        file.write(data)
+        
 class md3TexCoord:
-       u = 0.0
-       v = 0.0
+    u = 0.0
+    v = 0.0
 
-       binaryFormat = "<2f"
+    binaryFormat = "<2f"
 
-       def __init__(self):
-               self.u = 0.0
-               self.v = 0.0
-               
-       def GetSize(self):
-               return struct.calcsize(self.binaryFormat)
+    def __init__(self):
+        self.u = 0.0
+        self.v = 0.0
+        
+    def GetSize(self):
+        return struct.calcsize(self.binaryFormat)
 
-       def Save(self, file):
-               tmpData = [0] * 2
-               tmpData[0] = self.u
-               tmpData[1] = 1.0 - self.v
-               data = struct.pack(self.binaryFormat, tmpData[0], tmpData[1])
-               file.write(data)
+    def Save(self, file):
+        tmpData = [0] * 2
+        tmpData[0] = self.u
+        tmpData[1] = 1.0 - self.v
+        data = struct.pack(self.binaryFormat, tmpData[0], tmpData[1])
+        file.write(data)
 
 class md3Triangle:
-       indexes = []
+    indexes = []
 
-       binaryFormat = "<3i"
+    binaryFormat = "<3i"
 
-       def __init__(self):
-               self.indexes = [ 0, 0, 0 ]
-               
-       def GetSize(self):
-               return struct.calcsize(self.binaryFormat)
+    def __init__(self):
+        self.indexes = [ 0, 0, 0 ]
+        
+    def GetSize(self):
+        return struct.calcsize(self.binaryFormat)
 
-       def Save(self, file):
-               tmpData = [0] * 3
-               tmpData[0] = self.indexes[0]
-               tmpData[1] = self.indexes[2] # reverse
-               tmpData[2] = self.indexes[1] # reverse
-               data = struct.pack(self.binaryFormat,tmpData[0], tmpData[1], tmpData[2])
-               file.write(data)
+    def Save(self, file):
+        tmpData = [0] * 3
+        tmpData[0] = self.indexes[0]
+        tmpData[1] = self.indexes[2] # reverse
+        tmpData[2] = self.indexes[1] # reverse
+        data = struct.pack(self.binaryFormat,tmpData[0], tmpData[1], tmpData[2])
+        file.write(data)
 
 class md3Shader:
-       name = ""
-       index = 0
-       
-       binaryFormat = "<%dsi" % MAX_QPATH
-
-       def __init__(self):
-               self.name = ""
-               self.index = 0
-               
-       def GetSize(self):
-               return struct.calcsize(self.binaryFormat)
-
-       def Save(self, file):
-               tmpData = [0] * 2
-               tmpData[0] = self.name
-               tmpData[1] = self.index
-               data = struct.pack(self.binaryFormat, tmpData[0], tmpData[1])
-               file.write(data)
+    name = ""
+    index = 0
+    
+    binaryFormat = "<%dsi" % MAX_QPATH
+
+    def __init__(self):
+        self.name = ""
+        self.index = 0
+        
+    def GetSize(self):
+        return struct.calcsize(self.binaryFormat)
+
+    def Save(self, file):
+        tmpData = [0] * 2
+        tmpData[0] = self.name
+        tmpData[1] = self.index
+        data = struct.pack(self.binaryFormat, tmpData[0], tmpData[1])
+        file.write(data)
 
 class md3Surface:
-       ident = ""
-       name = ""
-       flags = 0
-       numFrames = 0
-       numShaders = 0
-       numVerts = 0
-       numTriangles = 0
-       ofsTriangles = 0
-       ofsShaders = 0
-       ofsUV = 0
-       ofsVerts = 0
-       ofsEnd = 0
-       shaders = []
-       triangles = []
-       uv = []
-       verts = []
-       
-       binaryFormat = "<4s%ds10i" % MAX_QPATH  # 1 int, name, then 10 ints
-       
-       def __init__(self):
-               self.ident = ""
-               self.name = ""
-               self.flags = 0
-               self.numFrames = 0
-               self.numShaders = 0
-               self.numVerts = 0
-               self.numTriangles = 0
-               self.ofsTriangles = 0
-               self.ofsShaders = 0
-               self.ofsUV = 0
-               self.ofsVerts = 0
-               self.ofsEnd
-               self.shaders = []
-               self.triangles = []
-               self.uv = []
-               self.verts = []
-               
-       def GetSize(self):
-               sz = struct.calcsize(self.binaryFormat)
-               self.ofsTriangles = sz
-               for t in self.triangles:
-                       sz += t.GetSize()
-               self.ofsShaders = sz
-               for s in self.shaders:
-                       sz += s.GetSize()
-               self.ofsUV = sz
-               for u in self.uv:
-                       sz += u.GetSize()
-               self.ofsVerts = sz
-               for v in self.verts:
-                       sz += v.GetSize()
-               self.ofsEnd = sz
-               return self.ofsEnd
-       
-       def Save(self, file):
-               self.GetSize()
-               tmpData = [0] * 12
-               tmpData[0] = self.ident
-               tmpData[1] = self.name
-               tmpData[2] = self.flags
-               tmpData[3] = self.numFrames
-               tmpData[4] = self.numShaders
-               tmpData[5] = self.numVerts
-               tmpData[6] = self.numTriangles
-               tmpData[7] = self.ofsTriangles
-               tmpData[8] = self.ofsShaders
-               tmpData[9] = self.ofsUV
-               tmpData[10] = self.ofsVerts
-               tmpData[11] = self.ofsEnd
-               data = struct.pack(self.binaryFormat, tmpData[0],tmpData[1],tmpData[2],tmpData[3],tmpData[4],tmpData[5],tmpData[6],tmpData[7],tmpData[8],tmpData[9],tmpData[10],tmpData[11])
-               file.write(data)
-
-               # write the tri data
-               for t in self.triangles:
-                       t.Save(file)
-
-               # save the shader coordinates
-               for s in self.shaders:
-                       s.Save(file)
-
-               # save the uv info
-               for u in self.uv:
-                       u.Save(file)
-
-               # save the verts
-               for v in self.verts:
-                       v.Save(file)
+    ident = ""
+    name = ""
+    flags = 0
+    numFrames = 0
+    numShaders = 0
+    numVerts = 0
+    numTriangles = 0
+    ofsTriangles = 0
+    ofsShaders = 0
+    ofsUV = 0
+    ofsVerts = 0
+    ofsEnd = 0
+    shaders = []
+    triangles = []
+    uv = []
+    verts = []
+    
+    binaryFormat = "<4s%ds10i" % MAX_QPATH  # 1 int, name, then 10 ints
+    
+    def __init__(self):
+        self.ident = ""
+        self.name = ""
+        self.flags = 0
+        self.numFrames = 0
+        self.numShaders = 0
+        self.numVerts = 0
+        self.numTriangles = 0
+        self.ofsTriangles = 0
+        self.ofsShaders = 0
+        self.ofsUV = 0
+        self.ofsVerts = 0
+        self.ofsEnd
+        self.shaders = []
+        self.triangles = []
+        self.uv = []
+        self.verts = []
+        
+    def GetSize(self):
+        sz = struct.calcsize(self.binaryFormat)
+        self.ofsTriangles = sz
+        for t in self.triangles:
+            sz += t.GetSize()
+        self.ofsShaders = sz
+        for s in self.shaders:
+            sz += s.GetSize()
+        self.ofsUV = sz
+        for u in self.uv:
+            sz += u.GetSize()
+        self.ofsVerts = sz
+        for v in self.verts:
+            sz += v.GetSize()
+        self.ofsEnd = sz
+        return self.ofsEnd
+    
+    def Save(self, file):
+        self.GetSize()
+        tmpData = [0] * 12
+        tmpData[0] = self.ident
+        tmpData[1] = self.name
+        tmpData[2] = self.flags
+        tmpData[3] = self.numFrames
+        tmpData[4] = self.numShaders
+        tmpData[5] = self.numVerts
+        tmpData[6] = self.numTriangles
+        tmpData[7] = self.ofsTriangles
+        tmpData[8] = self.ofsShaders
+        tmpData[9] = self.ofsUV
+        tmpData[10] = self.ofsVerts
+        tmpData[11] = self.ofsEnd
+        data = struct.pack(self.binaryFormat, tmpData[0],tmpData[1],tmpData[2],tmpData[3],tmpData[4],tmpData[5],tmpData[6],tmpData[7],tmpData[8],tmpData[9],tmpData[10],tmpData[11])
+        file.write(data)
+
+        # write the tri data
+        for t in self.triangles:
+            t.Save(file)
+
+        # save the shader coordinates
+        for s in self.shaders:
+            s.Save(file)
+
+        # save the uv info
+        for u in self.uv:
+            u.Save(file)
+
+        # save the verts
+        for v in self.verts:
+            v.Save(file)
 
 class md3Tag:
-       name = ""
-       origin = []
-       axis = []
-       
-       binaryFormat="<%ds3f9f" % MAX_QPATH
-       
-       def __init__(self):
-               self.name = ""
-               self.origin = [0, 0, 0]
-               self.axis = [0, 0, 0, 0, 0, 0, 0, 0, 0]
-               
-       def GetSize(self):
-               return struct.calcsize(self.binaryFormat)
-               
-       def Save(self, file):
-               tmpData = [0] * 13
-               tmpData[0] = self.name
-               tmpData[1] = float(self.origin[0])
-               tmpData[2] = float(self.origin[1])
-               tmpData[3] = float(self.origin[2])
-               tmpData[4] = float(self.axis[0])
-               tmpData[5] = float(self.axis[1])
-               tmpData[6] = float(self.axis[2])
-               tmpData[7] = float(self.axis[3])
-               tmpData[8] = float(self.axis[4])
-               tmpData[9] = float(self.axis[5])
-               tmpData[10] = float(self.axis[6])
-               tmpData[11] = float(self.axis[7])
-               tmpData[12] = float(self.axis[8])
-               data = struct.pack(self.binaryFormat, tmpData[0],tmpData[1],tmpData[2],tmpData[3],tmpData[4],tmpData[5],tmpData[6], tmpData[7], tmpData[8], tmpData[9], tmpData[10], tmpData[11], tmpData[12])
-               file.write(data)
-       
+    name = ""
+    origin = []
+    axis = []
+    
+    binaryFormat="<%ds3f9f" % MAX_QPATH
+    
+    def __init__(self):
+        self.name = ""
+        self.origin = [0, 0, 0]
+        self.axis = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+        
+    def GetSize(self):
+        return struct.calcsize(self.binaryFormat)
+        
+    def Save(self, file):
+        tmpData = [0] * 13
+        tmpData[0] = self.name
+        tmpData[1] = float(self.origin[0])
+        tmpData[2] = float(self.origin[1])
+        tmpData[3] = float(self.origin[2])
+        tmpData[4] = float(self.axis[0])
+        tmpData[5] = float(self.axis[1])
+        tmpData[6] = float(self.axis[2])
+        tmpData[7] = float(self.axis[3])
+        tmpData[8] = float(self.axis[4])
+        tmpData[9] = float(self.axis[5])
+        tmpData[10] = float(self.axis[6])
+        tmpData[11] = float(self.axis[7])
+        tmpData[12] = float(self.axis[8])
+        data = struct.pack(self.binaryFormat, tmpData[0],tmpData[1],tmpData[2],tmpData[3],tmpData[4],tmpData[5],tmpData[6], tmpData[7], tmpData[8], tmpData[9], tmpData[10], tmpData[11], tmpData[12])
+        file.write(data)
+    
 class md3Frame:
-       mins = 0
-       maxs = 0
-       localOrigin = 0
-       radius = 0.0
-       name = ""
-       
-       binaryFormat="<3f3f3ff16s"
-       
-       def __init__(self):
-               self.mins = [0, 0, 0]
-               self.maxs = [0, 0, 0]
-               self.localOrigin = [0, 0, 0]
-               self.radius = 0.0
-               self.name = ""
-               
-       def GetSize(self):
-               return struct.calcsize(self.binaryFormat)
-
-       def Save(self, file):
-               tmpData = [0] * 11
-               tmpData[0] = self.mins[0]
-               tmpData[1] = self.mins[1]
-               tmpData[2] = self.mins[2]
-               tmpData[3] = self.maxs[0]
-               tmpData[4] = self.maxs[1]
-               tmpData[5] = self.maxs[2]
-               tmpData[6] = self.localOrigin[0]
-               tmpData[7] = self.localOrigin[1]
-               tmpData[8] = self.localOrigin[2]
-               tmpData[9] = self.radius
-               tmpData[10] = self.name
-               data = struct.pack(self.binaryFormat, tmpData[0],tmpData[1],tmpData[2],tmpData[3],tmpData[4],tmpData[5],tmpData[6],tmpData[7], tmpData[8], tmpData[9], tmpData[10])
-               file.write(data)
+    mins = 0
+    maxs = 0
+    localOrigin = 0
+    radius = 0.0
+    name = ""
+    
+    binaryFormat="<3f3f3ff16s"
+    
+    def __init__(self):
+        self.mins = [0, 0, 0]
+        self.maxs = [0, 0, 0]
+        self.localOrigin = [0, 0, 0]
+        self.radius = 0.0
+        self.name = ""
+        
+    def GetSize(self):
+        return struct.calcsize(self.binaryFormat)
+
+    def Save(self, file):
+        tmpData = [0] * 11
+        tmpData[0] = self.mins[0]
+        tmpData[1] = self.mins[1]
+        tmpData[2] = self.mins[2]
+        tmpData[3] = self.maxs[0]
+        tmpData[4] = self.maxs[1]
+        tmpData[5] = self.maxs[2]
+        tmpData[6] = self.localOrigin[0]
+        tmpData[7] = self.localOrigin[1]
+        tmpData[8] = self.localOrigin[2]
+        tmpData[9] = self.radius
+        tmpData[10] = self.name
+        data = struct.pack(self.binaryFormat, tmpData[0],tmpData[1],tmpData[2],tmpData[3],tmpData[4],tmpData[5],tmpData[6],tmpData[7], tmpData[8], tmpData[9], tmpData[10])
+        file.write(data)
 
 class md3Object:
-       # header structure
-       ident = ""                      # this is used to identify the file (must be IDP3)
-       version = 0                     # the version number of the file (Must be 15)
-       name = ""
-       flags = 0
-       numFrames = 0
-       numTags = 0
-       numSurfaces = 0
-       numSkins = 0
-       ofsFrames = 0
-       ofsTags = 0
-       ofsSurfaces = 0
-       ofsEnd = 0
-       frames = []
-       tags = []
-       surfaces = []
-
-       binaryFormat="<4si%ds9i" % MAX_QPATH  # little-endian (<), 17 integers (17i)
-
-       def __init__(self):
-               self.ident = 0
-               self.version = 0
-               self.name = ""
-               self.flags = 0
-               self.numFrames = 0
-               self.numTags = 0
-               self.numSurfaces = 0
-               self.numSkins = 0
-               self.ofsFrames = 0
-               self.ofsTags = 0
-               self.ofsSurfaces = 0
-               self.ofsEnd = 0
-               self.frames = []
-               self.tags = []
-               self.surfaces = []
-
-       def GetSize(self):
-               self.ofsFrames = struct.calcsize(self.binaryFormat)
-               self.ofsTags = self.ofsFrames
-               for f in self.frames:
-                       self.ofsTags += f.GetSize()
-               self.ofsSurfaces += self.ofsTags
-               for t in self.tags:
-                       self.ofsSurfaces += t.GetSize()
-               self.ofsEnd = self.ofsSurfaces
-               for s in self.surfaces:
-                       self.ofsEnd += s.GetSize()
-               return self.ofsEnd
-               
-       def Save(self, file):
-               self.GetSize()
-               tmpData = [0] * 12
-               tmpData[0] = self.ident
-               tmpData[1] = self.version
-               tmpData[2] = self.name
-               tmpData[3] = self.flags
-               tmpData[4] = self.numFrames
-               tmpData[5] = self.numTags
-               tmpData[6] = self.numSurfaces
-               tmpData[7] = self.numSkins
-               tmpData[8] = self.ofsFrames
-               tmpData[9] = self.ofsTags
-               tmpData[10] = self.ofsSurfaces
-               tmpData[11] = self.ofsEnd
-
-               data = struct.pack(self.binaryFormat, tmpData[0],tmpData[1],tmpData[2],tmpData[3],tmpData[4],tmpData[5],tmpData[6],tmpData[7], tmpData[8], tmpData[9], tmpData[10], tmpData[11])
-               file.write(data)
-
-               for f in self.frames:
-                       f.Save(file)
-                       
-               for t in self.tags:
-                       t.Save(file)
-                       
-               for s in self.surfaces:
-                       s.Save(file)
+    # header structure
+    ident = ""            # this is used to identify the file (must be IDP3)
+    version = 0            # the version number of the file (Must be 15)
+    name = ""
+    flags = 0
+    numFrames = 0
+    numTags = 0
+    numSurfaces = 0
+    numSkins = 0
+    ofsFrames = 0
+    ofsTags = 0
+    ofsSurfaces = 0
+    ofsEnd = 0
+    frames = []
+    tags = []
+    surfaces = []
+
+    binaryFormat="<4si%ds9i" % MAX_QPATH  # little-endian (<), 17 integers (17i)
+
+    def __init__(self):
+        self.ident = 0
+        self.version = 0
+        self.name = ""
+        self.flags = 0
+        self.numFrames = 0
+        self.numTags = 0
+        self.numSurfaces = 0
+        self.numSkins = 0
+        self.ofsFrames = 0
+        self.ofsTags = 0
+        self.ofsSurfaces = 0
+        self.ofsEnd = 0
+        self.frames = []
+        self.tags = []
+        self.surfaces = []
+
+    def GetSize(self):
+        self.ofsFrames = struct.calcsize(self.binaryFormat)
+        self.ofsTags = self.ofsFrames
+        for f in self.frames:
+            self.ofsTags += f.GetSize()
+        self.ofsSurfaces += self.ofsTags
+        for t in self.tags:
+            self.ofsSurfaces += t.GetSize()
+        self.ofsEnd = self.ofsSurfaces
+        for s in self.surfaces:
+            self.ofsEnd += s.GetSize()
+        return self.ofsEnd
+        
+    def Save(self, file):
+        self.GetSize()
+        tmpData = [0] * 12
+        tmpData[0] = self.ident
+        tmpData[1] = self.version
+        tmpData[2] = self.name
+        tmpData[3] = self.flags
+        tmpData[4] = self.numFrames
+        tmpData[5] = self.numTags
+        tmpData[6] = self.numSurfaces
+        tmpData[7] = self.numSkins
+        tmpData[8] = self.ofsFrames
+        tmpData[9] = self.ofsTags
+        tmpData[10] = self.ofsSurfaces
+        tmpData[11] = self.ofsEnd
+
+        data = struct.pack(self.binaryFormat, tmpData[0],tmpData[1],tmpData[2],tmpData[3],tmpData[4],tmpData[5],tmpData[6],tmpData[7], tmpData[8], tmpData[9], tmpData[10], tmpData[11])
+        file.write(data)
+
+        for f in self.frames:
+            f.Save(file)
+            
+        for t in self.tags:
+            t.Save(file)
+            
+        for s in self.surfaces:
+            s.Save(file)
 
 
 def message(log,msg):
@@ -652,7 +642,7 @@ def save_md3(settings):
 
 from bpy.props import *
 class ExportMD3(bpy.types.Operator):
-  '''Export to Quake Model 3 (.md3)'''
+  """Export to Quake Model 3 (.md3)"""
   bl_idname = "export.md3"
   bl_label = 'Export MD3'
 
@@ -682,24 +672,23 @@ class ExportMD3(bpy.types.Operator):
    return {'FINISHED'}
 
   def invoke(self, context, event):
-    wm = context.manager
-    wm.add_fileselect(self)
+    wm = context.window_manager
+    wm.fileselect_add(self)
     return {'RUNNING_MODAL'}
 
-  def poll(self, context):
-    return context.active_object != None
+  @classmethod
+  def poll(cls, context):
+    return context.active_object is not None
 
 def menu_func(self, context):
-  newpath = os.path.splitext(bpy.context.main.filepath)[0] + ".md3"
+  newpath = os.path.splitext(bpy.context.blend_data.filepath)[0] + ".md3"
   self.layout.operator(ExportMD3.bl_idname, text="Quake Model 3 (.md3)").filepath = newpath 
 
 def register():
-  bpy.types.register(ExportMD3)
   bpy.types.INFO_MT_file_export.append(menu_func)
 
 def unregister():
-  bpy.types.unregister(ExportMD3)
   bpy.types.INFO_MT_file_export.remove(menu_func)
 
 if __name__ == "__main__":
-  register()
\ No newline at end of file
+  register()