diff --git a/io_export_unreal_psk_psa.py b/io_export_unreal_psk_psa.py
index 59bb37075ce731c48d1e459f88b5292b698bb685..4d7f65cb3f8a1f25f7bc8e48d5617bd2435458e3 100644
--- a/io_export_unreal_psk_psa.py
+++ b/io_export_unreal_psk_psa.py
@@ -1,34 +1,34 @@
- #  ***** GPL LICENSE BLOCK *****
- #
- #  This program is free software: you can redistribute it and/or modify
- #  it under the terms of the GNU General Public License as published by
- #  the Free Software Foundation, either version 3 of the License, or
- #  (at your option) any later version.
- #
- #  This program is distributed in the hope that it will be useful,
- #  but WITHOUT ANY WARRANTY; without even the implied warranty of
- #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- #  GNU General Public License for more details.
- #
- #  You should have received a copy of the GNU General Public License
- #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- #  All rights reserved.
- #  ***** GPL LICENSE BLOCK *****
+#  ***** GPL LICENSE BLOCK *****
+#
+#  This program is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#  All rights reserved.
+#  ***** GPL LICENSE BLOCK *****
 
 bl_addon_info = {
-    "name": "Export Skeleletal Mesh/Animation Data",
-    "author": "Darknet/Optimus_P-Fat/Active_Trash/Sinsoft",
-    "version": (2,0),
-    "blender": (2, 5, 3),
-    "api": 31847,
-    "location": "File > Export > Skeletal Mesh/Animation Data (.psk/.psa)",
-    "description": "Export Unreal Engine (.psk)",
-    "warning": "",
-    "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
-        "Scripts/File_I-O/Unreal_psk_psa",
-    "tracker_url": "https://projects.blender.org/tracker/index.php?"\
-        "func=detail&aid=21366&group_id=153&atid=469",
-    "category": "Import/Export"}
+	"name": "Export Skeleletal Mesh/Animation Data",
+	"author": "Darknet/Optimus_P-Fat/Active_Trash/Sinsoft",
+	"version": (2,0),
+	"blender": (2, 5, 3),
+	"api": 31847,
+	"location": "File > Export > Skeletal Mesh/Animation Data (.psk/.psa)",
+	"description": "Export Unreal Engine (.psk)",
+	"warning": "",
+	"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
+		"Scripts/File_I-O/Unreal_psk_psa",
+	"tracker_url": "https://projects.blender.org/tracker/index.php?"\
+		"func=detail&aid=21366&group_id=153&atid=469",
+	"category": "Import/Export"}
 
 """
 -- Unreal Skeletal Mesh and Animation Export (.psk  and .psa) export script v0.0.1 --<br> 
@@ -114,256 +114,256 @@ SIZE_VTRIANGLE = 12
 # Generic Object->Integer mapping
 # the object must be usable as a dictionary key
 class ObjMap:
-    def __init__(self):
-        self.dict = {}
-        self.next = 0
-    def get(self, obj):
-        if obj in self.dict:
-            return self.dict[obj]
-        else:
-            id = self.next
-            self.next = self.next + 1
-            self.dict[obj] = id
-            return id
-        
-    def items(self):
-        getval = operator.itemgetter(0)
-        getkey = operator.itemgetter(1)
-        return map(getval, sorted(self.dict.items(), key=getkey))
+	def __init__(self):
+		self.dict = {}
+		self.next = 0
+	def get(self, obj):
+		if obj in self.dict:
+			return self.dict[obj]
+		else:
+			id = self.next
+			self.next = self.next + 1
+			self.dict[obj] = id
+			return id
+		
+	def items(self):
+		getval = operator.itemgetter(0)
+		getkey = operator.itemgetter(1)
+		return map(getval, sorted(self.dict.items(), key=getkey))
 
 ########################################################################
 # RG - UNREAL DATA STRUCTS - CONVERTED FROM C STRUCTS GIVEN ON UDN SITE 
 # provided here: http://udn.epicgames.com/Two/BinaryFormatSpecifications.html
 # updated UDK (Unreal Engine 3): http://udn.epicgames.com/Three/BinaryFormatSpecifications.html
 class FQuat:
-    def __init__(self): 
-        self.X = 0.0
-        self.Y = 0.0
-        self.Z = 0.0
-        self.W = 1.0
-        
-    def dump(self):
-        data = pack('ffff', self.X, self.Y, self.Z, self.W)
-        return data
-        
-    def __cmp__(self, other):
-        return cmp(self.X, other.X) \
-            or cmp(self.Y, other.Y) \
-            or cmp(self.Z, other.Z) \
-            or cmp(self.W, other.W)
-        
-    def __hash__(self):
-        return hash(self.X) ^ hash(self.Y) ^ hash(self.Z) ^ hash(self.W)
-        
-    def __str__(self):
-        return "[%f,%f,%f,%f](FQuat)" % (self.X, self.Y, self.Z, self.W)
-        
+	def __init__(self): 
+		self.X = 0.0
+		self.Y = 0.0
+		self.Z = 0.0
+		self.W = 1.0
+		
+	def dump(self):
+		data = pack('ffff', self.X, self.Y, self.Z, self.W)
+		return data
+		
+	def __cmp__(self, other):
+		return cmp(self.X, other.X) \
+			or cmp(self.Y, other.Y) \
+			or cmp(self.Z, other.Z) \
+			or cmp(self.W, other.W)
+		
+	def __hash__(self):
+		return hash(self.X) ^ hash(self.Y) ^ hash(self.Z) ^ hash(self.W)
+		
+	def __str__(self):
+		return "[%f,%f,%f,%f](FQuat)" % (self.X, self.Y, self.Z, self.W)
+		
 class FVector(object):
-    def __init__(self, X=0.0, Y=0.0, Z=0.0):
-        self.X = X
-        self.Y = Y
-        self.Z = Z
-        
-    def dump(self):
-        data = pack('fff', self.X, self.Y, self.Z)
-        return data
-        
-    def __cmp__(self, other):
-        return cmp(self.X, other.X) \
-            or cmp(self.Y, other.Y) \
-            or cmp(self.Z, other.Z)
-        
-    def _key(self):
-        return (type(self).__name__, self.X, self.Y, self.Z)
-        
-    def __hash__(self):
-        return hash(self._key())
-        
-    def __eq__(self, other):
-        if not hasattr(other, '_key'):
-            return False
-        return self._key() == other._key() 
-        
-    def dot(self, other):
-        return self.X * other.X + self.Y * other.Y + self.Z * other.Z
-    
-    def cross(self, other):
-        return FVector(self.Y * other.Z - self.Z * other.Y,
-                self.Z * other.X - self.X * other.Z,
-                self.X * other.Y - self.Y * other.X)
-                
-    def sub(self, other):
-        return FVector(self.X - other.X,
-            self.Y - other.Y,
-            self.Z - other.Z)
+	def __init__(self, X=0.0, Y=0.0, Z=0.0):
+		self.X = X
+		self.Y = Y
+		self.Z = Z
+		
+	def dump(self):
+		data = pack('fff', self.X, self.Y, self.Z)
+		return data
+		
+	def __cmp__(self, other):
+		return cmp(self.X, other.X) \
+			or cmp(self.Y, other.Y) \
+			or cmp(self.Z, other.Z)
+		
+	def _key(self):
+		return (type(self).__name__, self.X, self.Y, self.Z)
+		
+	def __hash__(self):
+		return hash(self._key())
+		
+	def __eq__(self, other):
+		if not hasattr(other, '_key'):
+			return False
+		return self._key() == other._key() 
+		
+	def dot(self, other):
+		return self.X * other.X + self.Y * other.Y + self.Z * other.Z
+	
+	def cross(self, other):
+		return FVector(self.Y * other.Z - self.Z * other.Y,
+				self.Z * other.X - self.X * other.Z,
+				self.X * other.Y - self.Y * other.X)
+				
+	def sub(self, other):
+		return FVector(self.X - other.X,
+			self.Y - other.Y,
+			self.Z - other.Z)
 
 class VJointPos:
-    def __init__(self):
-        self.Orientation = FQuat()
-        self.Position = FVector()
-        self.Length = 0.0
-        self.XSize = 0.0
-        self.YSize = 0.0
-        self.ZSize = 0.0
-        
-    def dump(self):
-        data = self.Orientation.dump() + self.Position.dump() + pack('4f', self.Length, self.XSize, self.YSize, self.ZSize)
-        return data
-            
+	def __init__(self):
+		self.Orientation = FQuat()
+		self.Position = FVector()
+		self.Length = 0.0
+		self.XSize = 0.0
+		self.YSize = 0.0
+		self.ZSize = 0.0
+		
+	def dump(self):
+		data = self.Orientation.dump() + self.Position.dump() + pack('4f', self.Length, self.XSize, self.YSize, self.ZSize)
+		return data
+			
 class AnimInfoBinary:
-    def __init__(self):
-        self.Name = "" # length=64
-        self.Group = ""    # length=64
-        self.TotalBones = 0
-        self.RootInclude = 0
-        self.KeyCompressionStyle = 0
-        self.KeyQuotum = 0
-        self.KeyPrediction = 0.0
-        self.TrackTime = 0.0
-        self.AnimRate = 0.0
-        self.StartBone = 0
-        self.FirstRawFrame = 0
-        self.NumRawFrames = 0
-        
-    def dump(self):
-        data = pack('64s64siiiifffiii', self.Name, self.Group, self.TotalBones, self.RootInclude, self.KeyCompressionStyle, self.KeyQuotum, self.KeyPrediction, self.TrackTime, self.AnimRate, self.StartBone, self.FirstRawFrame, self.NumRawFrames)
-        return data
+	def __init__(self):
+		self.Name = "" # length=64
+		self.Group = ""    # length=64
+		self.TotalBones = 0
+		self.RootInclude = 0
+		self.KeyCompressionStyle = 0
+		self.KeyQuotum = 0
+		self.KeyPrediction = 0.0
+		self.TrackTime = 0.0
+		self.AnimRate = 0.0
+		self.StartBone = 0
+		self.FirstRawFrame = 0
+		self.NumRawFrames = 0
+		
+	def dump(self):
+		data = pack('64s64siiiifffiii', self.Name, self.Group, self.TotalBones, self.RootInclude, self.KeyCompressionStyle, self.KeyQuotum, self.KeyPrediction, self.TrackTime, self.AnimRate, self.StartBone, self.FirstRawFrame, self.NumRawFrames)
+		return data
 
 class VChunkHeader:
-    def __init__(self, name, type_size):
-        self.ChunkID = name # length=20
-        self.TypeFlag = 1999801 # special value
-        self.DataSize = type_size
-        self.DataCount = 0
-        
-    def dump(self):
-        data = pack('20siii', self.ChunkID, self.TypeFlag, self.DataSize, self.DataCount)
-        return data
-        
+	def __init__(self, name, type_size):
+		self.ChunkID = name # length=20
+		self.TypeFlag = 1999801 # special value
+		self.DataSize = type_size
+		self.DataCount = 0
+		
+	def dump(self):
+		data = pack('20siii', self.ChunkID, self.TypeFlag, self.DataSize, self.DataCount)
+		return data
+		
 class VMaterial:
-    def __init__(self):
-        self.MaterialName = "" # length=64
-        self.TextureIndex = 0
-        self.PolyFlags = 0 # DWORD
-        self.AuxMaterial = 0
-        self.AuxFlags = 0 # DWORD
-        self.LodBias = 0
-        self.LodStyle = 0
-        
-    def dump(self):
-        data = pack('64siLiLii', self.MaterialName, self.TextureIndex, self.PolyFlags, self.AuxMaterial, self.AuxFlags, self.LodBias, self.LodStyle)
-        return data
+	def __init__(self):
+		self.MaterialName = "" # length=64
+		self.TextureIndex = 0
+		self.PolyFlags = 0 # DWORD
+		self.AuxMaterial = 0
+		self.AuxFlags = 0 # DWORD
+		self.LodBias = 0
+		self.LodStyle = 0
+		
+	def dump(self):
+		data = pack('64siLiLii', self.MaterialName, self.TextureIndex, self.PolyFlags, self.AuxMaterial, self.AuxFlags, self.LodBias, self.LodStyle)
+		return data
 
 class VBone:
-    def __init__(self):
-        self.Name = "" # length = 64
-        self.Flags = 0 # DWORD
-        self.NumChildren = 0
-        self.ParentIndex = 0
-        self.BonePos = VJointPos()
-        
-    def dump(self):
-        data = pack('64sLii', self.Name, self.Flags, self.NumChildren, self.ParentIndex) + self.BonePos.dump()
-        return data
+	def __init__(self):
+		self.Name = "" # length = 64
+		self.Flags = 0 # DWORD
+		self.NumChildren = 0
+		self.ParentIndex = 0
+		self.BonePos = VJointPos()
+		
+	def dump(self):
+		data = pack('64sLii', self.Name, self.Flags, self.NumChildren, self.ParentIndex) + self.BonePos.dump()
+		return data
 
 #same as above - whatever - this is how Epic does it...        
 class FNamedBoneBinary:
-    def __init__(self):
-        self.Name = "" # length = 64
-        self.Flags = 0 # DWORD
-        self.NumChildren = 0
-        self.ParentIndex = 0
-        self.BonePos = VJointPos()
-        
-        self.IsRealBone = 0  # this is set to 1 when the bone is actually a bone in the mesh and not a dummy
-        
-    def dump(self):
-        data = pack('64sLii', self.Name, self.Flags, self.NumChildren, self.ParentIndex) + self.BonePos.dump()
-        return data
-    
+	def __init__(self):
+		self.Name = "" # length = 64
+		self.Flags = 0 # DWORD
+		self.NumChildren = 0
+		self.ParentIndex = 0
+		self.BonePos = VJointPos()
+		
+		self.IsRealBone = 0  # this is set to 1 when the bone is actually a bone in the mesh and not a dummy
+		
+	def dump(self):
+		data = pack('64sLii', self.Name, self.Flags, self.NumChildren, self.ParentIndex) + self.BonePos.dump()
+		return data
+	
 class VRawBoneInfluence:
-    def __init__(self):
-        self.Weight = 0.0
-        self.PointIndex = 0
-        self.BoneIndex = 0
-        
-    def dump(self):
-        data = pack('fii', self.Weight, self.PointIndex, self.BoneIndex)
-        return data
-        
+	def __init__(self):
+		self.Weight = 0.0
+		self.PointIndex = 0
+		self.BoneIndex = 0
+		
+	def dump(self):
+		data = pack('fii', self.Weight, self.PointIndex, self.BoneIndex)
+		return data
+		
 class VQuatAnimKey:
-    def __init__(self):
-        self.Position = FVector()
-        self.Orientation = FQuat()
-        self.Time = 0.0
-        
-    def dump(self):
-        data = self.Position.dump() + self.Orientation.dump() + pack('f', self.Time)
-        return data
-        
+	def __init__(self):
+		self.Position = FVector()
+		self.Orientation = FQuat()
+		self.Time = 0.0
+		
+	def dump(self):
+		data = self.Position.dump() + self.Orientation.dump() + pack('f', self.Time)
+		return data
+		
 class VVertex(object):
-    def __init__(self):
-        self.PointIndex = 0 # WORD
-        self.U = 0.0
-        self.V = 0.0
-        self.MatIndex = 0 #BYTE
-        self.Reserved = 0 #BYTE
-        
-    def dump(self):
-        data = pack('HHffBBH', self.PointIndex, 0, self.U, self.V, self.MatIndex, self.Reserved, 0)
-        return data
-        
-    def __cmp__(self, other):
-        return cmp(self.PointIndex, other.PointIndex) \
-            or cmp(self.U, other.U) \
-            or cmp(self.V, other.V) \
-            or cmp(self.MatIndex, other.MatIndex) \
-            or cmp(self.Reserved, other.Reserved)
-    
-    def _key(self):
-        return (type(self).__name__,self.PointIndex, self.U, self.V,self.MatIndex,self.Reserved)
-        
-    def __hash__(self):
-        return hash(self._key())
-        
-    def __eq__(self, other):
-        if not hasattr(other, '_key'):
-            return False
-        return self._key() == other._key()
-        
+	def __init__(self):
+		self.PointIndex = 0 # WORD
+		self.U = 0.0
+		self.V = 0.0
+		self.MatIndex = 0 #BYTE
+		self.Reserved = 0 #BYTE
+		
+	def dump(self):
+		data = pack('HHffBBH', self.PointIndex, 0, self.U, self.V, self.MatIndex, self.Reserved, 0)
+		return data
+		
+	def __cmp__(self, other):
+		return cmp(self.PointIndex, other.PointIndex) \
+			or cmp(self.U, other.U) \
+			or cmp(self.V, other.V) \
+			or cmp(self.MatIndex, other.MatIndex) \
+			or cmp(self.Reserved, other.Reserved)
+	
+	def _key(self):
+		return (type(self).__name__,self.PointIndex, self.U, self.V,self.MatIndex,self.Reserved)
+		
+	def __hash__(self):
+		return hash(self._key())
+		
+	def __eq__(self, other):
+		if not hasattr(other, '_key'):
+			return False
+		return self._key() == other._key()
+		
 class VPoint(object):
-    def __init__(self):
-        self.Point = FVector()
-        
-    def dump(self):
-        return self.Point.dump()
-        
-    def __cmp__(self, other):
-        return cmp(self.Point, other.Point)
-    
-    def _key(self):
-        return (type(self).__name__, self.Point)
-    
-    def __hash__(self):
-        return hash(self._key())
-        
-    def __eq__(self, other):
-        if not hasattr(other, '_key'):
-            return False
-        return self._key() == other._key() 
-        
+	def __init__(self):
+		self.Point = FVector()
+		
+	def dump(self):
+		return self.Point.dump()
+		
+	def __cmp__(self, other):
+		return cmp(self.Point, other.Point)
+	
+	def _key(self):
+		return (type(self).__name__, self.Point)
+	
+	def __hash__(self):
+		return hash(self._key())
+		
+	def __eq__(self, other):
+		if not hasattr(other, '_key'):
+			return False
+		return self._key() == other._key() 
+		
 class VTriangle:
-    def __init__(self):
-        self.WedgeIndex0 = 0 # WORD
-        self.WedgeIndex1 = 0 # WORD
-        self.WedgeIndex2 = 0 # WORD
-        self.MatIndex = 0 # BYTE
-        self.AuxMatIndex = 0 # BYTE
-        self.SmoothingGroups = 0 # DWORD
-        
-    def dump(self):
-        data = pack('HHHBBL', self.WedgeIndex0, self.WedgeIndex1, self.WedgeIndex2, self.MatIndex, self.AuxMatIndex, self.SmoothingGroups)
-        return data
+	def __init__(self):
+		self.WedgeIndex0 = 0 # WORD
+		self.WedgeIndex1 = 0 # WORD
+		self.WedgeIndex2 = 0 # WORD
+		self.MatIndex = 0 # BYTE
+		self.AuxMatIndex = 0 # BYTE
+		self.SmoothingGroups = 0 # DWORD
+		
+	def dump(self):
+		data = pack('HHHBBL', self.WedgeIndex0, self.WedgeIndex1, self.WedgeIndex2, self.MatIndex, self.AuxMatIndex, self.SmoothingGroups)
+		return data
 
 # END UNREAL DATA STRUCTS
 ########################################################################
@@ -372,99 +372,99 @@ class VTriangle:
 #RG - helper class to handle the normal way the UT files are stored 
 #as sections consisting of a header and then a list of data structures
 class FileSection:
-    def __init__(self, name, type_size):
-        self.Header = VChunkHeader(name, type_size)
-        self.Data = [] # list of datatypes
-        
-    def dump(self):
-        data = self.Header.dump()
-        for i in range(len(self.Data)):
-            data = data + self.Data[i].dump()
-        return data
-        
-    def UpdateHeader(self):
-        self.Header.DataCount = len(self.Data)
-        
+	def __init__(self, name, type_size):
+		self.Header = VChunkHeader(name, type_size)
+		self.Data = [] # list of datatypes
+		
+	def dump(self):
+		data = self.Header.dump()
+		for i in range(len(self.Data)):
+			data = data + self.Data[i].dump()
+		return data
+		
+	def UpdateHeader(self):
+		self.Header.DataCount = len(self.Data)
+		
 class PSKFile:
-    def __init__(self):
-        self.GeneralHeader = VChunkHeader("ACTRHEAD", 0)
-        self.Points = FileSection("PNTS0000", SIZE_VPOINT)        #VPoint
-        self.Wedges = FileSection("VTXW0000", SIZE_VVERTEX)        #VVertex
-        self.Faces = FileSection("FACE0000", SIZE_VTRIANGLE)        #VTriangle
-        self.Materials = FileSection("MATT0000", SIZE_VMATERIAL)    #VMaterial
-        self.Bones = FileSection("REFSKELT", SIZE_VBONE)        #VBone
-        self.Influences = FileSection("RAWWEIGHTS", SIZE_VRAWBONEINFLUENCE)    #VRawBoneInfluence
-        
-        #RG - this mapping is not dumped, but is used internally to store the new point indices 
-        # for vertex groups calculated during the mesh dump, so they can be used again
-        # to dump bone influences during the armature dump
-        #
-        # the key in this dictionary is the VertexGroup/Bone Name, and the value
-        # is a list of tuples containing the new point index and the weight, in that order
-        #
-        # Layout:
-        # { groupname : [ (index, weight), ... ], ... }
-        #
-        # example: 
-        # { 'MyVertexGroup' : [ (0, 1.0), (5, 1.0), (3, 0.5) ] , 'OtherGroup' : [(2, 1.0)] }
-        
-        self.VertexGroups = {} 
-        
-    def AddPoint(self, p):
-        #print ('AddPoint')
-        self.Points.Data.append(p)
-        
-    def AddWedge(self, w):
-        #print ('AddWedge')
-        self.Wedges.Data.append(w)
-    
-    def AddFace(self, f):
-        #print ('AddFace')
-        self.Faces.Data.append(f)
-        
-    def AddMaterial(self, m):
-        #print ('AddMaterial')
-        self.Materials.Data.append(m)
-        
-    def AddBone(self, b):
-        #print ('AddBone [%s]: Position: (x=%f, y=%f, z=%f) Rotation=(%f,%f,%f,%f)'  % (b.Name, b.BonePos.Position.X, b.BonePos.Position.Y, b.BonePos.Position.Z, b.BonePos.Orientation.X,b.BonePos.Orientation.Y,b.BonePos.Orientation.Z,b.BonePos.Orientation.W))
-        self.Bones.Data.append(b)
-        
-    def AddInfluence(self, i):
-        #print ('AddInfluence')
-        self.Influences.Data.append(i)
-        
-    def UpdateHeaders(self):
-        self.Points.UpdateHeader()
-        self.Wedges.UpdateHeader()
-        self.Faces.UpdateHeader()
-        self.Materials.UpdateHeader()
-        self.Bones.UpdateHeader()
-        self.Influences.UpdateHeader()
-        
-    def dump(self):
-        self.UpdateHeaders()
-        data = self.GeneralHeader.dump() + self.Points.dump() + self.Wedges.dump() + self.Faces.dump() + self.Materials.dump() + self.Bones.dump() + self.Influences.dump()
-        return data
-        
-    def GetMatByIndex(self, mat_index):
-        if mat_index >= 0 and len(self.Materials.Data) > mat_index:
-            return self.Materials.Data[mat_index]
-        else:
-            m = VMaterial()
-            m.MaterialName = "Mat%i" % mat_index
-            self.AddMaterial(m)
-            return m
-        
-    def PrintOut(self):
-        print ("--- PSK FILE EXPORTED ---")
-        print ('point count: %i' % len(self.Points.Data))
-        print ('wedge count: %i' % len(self.Wedges.Data))
-        print ('face count: %i' % len(self.Faces.Data))
-        print ('material count: %i' % len(self.Materials.Data))
-        print ('bone count: %i' % len(self.Bones.Data))
-        print ('inlfuence count: %i' % len(self.Influences.Data))
-        print ('-------------------------')
+	def __init__(self):
+		self.GeneralHeader = VChunkHeader("ACTRHEAD", 0)
+		self.Points = FileSection("PNTS0000", SIZE_VPOINT)        #VPoint
+		self.Wedges = FileSection("VTXW0000", SIZE_VVERTEX)        #VVertex
+		self.Faces = FileSection("FACE0000", SIZE_VTRIANGLE)        #VTriangle
+		self.Materials = FileSection("MATT0000", SIZE_VMATERIAL)    #VMaterial
+		self.Bones = FileSection("REFSKELT", SIZE_VBONE)        #VBone
+		self.Influences = FileSection("RAWWEIGHTS", SIZE_VRAWBONEINFLUENCE)    #VRawBoneInfluence
+		
+		#RG - this mapping is not dumped, but is used internally to store the new point indices 
+		# for vertex groups calculated during the mesh dump, so they can be used again
+		# to dump bone influences during the armature dump
+		#
+		# the key in this dictionary is the VertexGroup/Bone Name, and the value
+		# is a list of tuples containing the new point index and the weight, in that order
+		#
+		# Layout:
+		# { groupname : [ (index, weight), ... ], ... }
+		#
+		# example: 
+		# { 'MyVertexGroup' : [ (0, 1.0), (5, 1.0), (3, 0.5) ] , 'OtherGroup' : [(2, 1.0)] }
+		
+		self.VertexGroups = {} 
+		
+	def AddPoint(self, p):
+		#print ('AddPoint')
+		self.Points.Data.append(p)
+		
+	def AddWedge(self, w):
+		#print ('AddWedge')
+		self.Wedges.Data.append(w)
+	
+	def AddFace(self, f):
+		#print ('AddFace')
+		self.Faces.Data.append(f)
+		
+	def AddMaterial(self, m):
+		#print ('AddMaterial')
+		self.Materials.Data.append(m)
+		
+	def AddBone(self, b):
+		#print ('AddBone [%s]: Position: (x=%f, y=%f, z=%f) Rotation=(%f,%f,%f,%f)'  % (b.Name, b.BonePos.Position.X, b.BonePos.Position.Y, b.BonePos.Position.Z, b.BonePos.Orientation.X,b.BonePos.Orientation.Y,b.BonePos.Orientation.Z,b.BonePos.Orientation.W))
+		self.Bones.Data.append(b)
+		
+	def AddInfluence(self, i):
+		#print ('AddInfluence')
+		self.Influences.Data.append(i)
+		
+	def UpdateHeaders(self):
+		self.Points.UpdateHeader()
+		self.Wedges.UpdateHeader()
+		self.Faces.UpdateHeader()
+		self.Materials.UpdateHeader()
+		self.Bones.UpdateHeader()
+		self.Influences.UpdateHeader()
+		
+	def dump(self):
+		self.UpdateHeaders()
+		data = self.GeneralHeader.dump() + self.Points.dump() + self.Wedges.dump() + self.Faces.dump() + self.Materials.dump() + self.Bones.dump() + self.Influences.dump()
+		return data
+		
+	def GetMatByIndex(self, mat_index):
+		if mat_index >= 0 and len(self.Materials.Data) > mat_index:
+			return self.Materials.Data[mat_index]
+		else:
+			m = VMaterial()
+			m.MaterialName = "Mat%i" % mat_index
+			self.AddMaterial(m)
+			return m
+		
+	def PrintOut(self):
+		print ("--- PSK FILE EXPORTED ---")
+		print ('point count: %i' % len(self.Points.Data))
+		print ('wedge count: %i' % len(self.Wedges.Data))
+		print ('face count: %i' % len(self.Faces.Data))
+		print ('material count: %i' % len(self.Materials.Data))
+		print ('bone count: %i' % len(self.Bones.Data))
+		print ('inlfuence count: %i' % len(self.Influences.Data))
+		print ('-------------------------')
 
 # PSA FILE NOTES FROM UDN:
 #
@@ -481,947 +481,1134 @@ class PSKFile:
 #    the offsets & rotations that are in the VBones making up the reference skeleton from the PSK)
 
 class PSAFile:
-    def __init__(self):
-        self.GeneralHeader = VChunkHeader("ANIMHEAD", 0)
-        self.Bones = FileSection("BONENAMES", SIZE_FNAMEDBONEBINARY)    #FNamedBoneBinary
-        self.Animations = FileSection("ANIMINFO", SIZE_ANIMINFOBINARY)    #AnimInfoBinary
-        self.RawKeys = FileSection("ANIMKEYS", SIZE_VQUATANIMKEY)    #VQuatAnimKey
-        
-        # this will take the format of key=Bone Name, value = (BoneIndex, Bone Object)
-        # THIS IS NOT DUMPED
-        self.BoneLookup = {} 
-        
-    def dump(self):
-        data = self.Generalheader.dump() + self.Bones.dump() + self.Animations.dump() + self.RawKeys.dump()
-        return data
-    
-    def AddBone(self, b):
-        #LOUD
-        #print "AddBone: " + b.Name
-        self.Bones.Data.append(b)
-        
-    def AddAnimation(self, a):
-        #LOUD
-        #print "AddAnimation: %s, TotalBones: %i, AnimRate: %f, NumRawFrames: %i, TrackTime: %f" % (a.Name, a.TotalBones, a.AnimRate, a.NumRawFrames, a.TrackTime)
-        self.Animations.Data.append(a)
-        
-    def AddRawKey(self, k):
-        #LOUD
-        #print "AddRawKey [%i]: Time: %f, Quat: x=%f, y=%f, z=%f, w=%f, Position: x=%f, y=%f, z=%f" % (len(self.RawKeys.Data), k.Time, k.Orientation.X, k.Orientation.Y, k.Orientation.Z, k.Orientation.W, k.Position.X, k.Position.Y, k.Position.Z)
-        self.RawKeys.Data.append(k)
-        
-    def UpdateHeaders(self):
-        self.Bones.UpdateHeader()
-        self.Animations.UpdateHeader()
-        self.RawKeys.UpdateHeader()
-        
-    def GetBoneByIndex(self, bone_index):
-        if bone_index >= 0 and len(self.Bones.Data) > bone_index:
-            return self.Bones.Data[bone_index]
-    
-    def IsEmpty(self):
-        return (len(self.Bones.Data) == 0 or len(self.Animations.Data) == 0)
-    
-    def StoreBone(self, b):
-        self.BoneLookup[b.Name] = [-1, b]
-                    
-    def UseBone(self, bone_name):
-        if bone_name in self.BoneLookup:
-            bone_data = self.BoneLookup[bone_name]
-            
-            if bone_data[0] == -1:
-                bone_data[0] = len(self.Bones.Data)
-                self.AddBone(bone_data[1])
-                #self.Bones.Data.append(bone_data[1])
-            
-            return bone_data[0]
-            
-    def GetBoneByName(self, bone_name):
-        if bone_name in self.BoneLookup:
-            bone_data = self.BoneLookup[bone_name]
-            return bone_data[1]
-        
-    def GetBoneIndex(self, bone_name):
-        if bone_name in self.BoneLookup:
-            bone_data = self.BoneLookup[bone_name]
-            return bone_data[0]
-        
-    def dump(self):
-        self.UpdateHeaders()
-        data = self.GeneralHeader.dump() + self.Bones.dump() + self.Animations.dump() + self.RawKeys.dump()
-        return data
-        
-    def PrintOut(self):
-        print ('--- PSA FILE EXPORTED ---')
-        print ('bone count: %i' % len(self.Bones.Data))
-        print ('animation count: %i' % len(self.Animations.Data))
-        print ('rawkey count: %i' % len(self.RawKeys.Data))
-        print ('-------------------------')
-        
+	def __init__(self):
+		self.GeneralHeader = VChunkHeader("ANIMHEAD", 0)
+		self.Bones = FileSection("BONENAMES", SIZE_FNAMEDBONEBINARY)    #FNamedBoneBinary
+		self.Animations = FileSection("ANIMINFO", SIZE_ANIMINFOBINARY)    #AnimInfoBinary
+		self.RawKeys = FileSection("ANIMKEYS", SIZE_VQUATANIMKEY)    #VQuatAnimKey
+		
+		# this will take the format of key=Bone Name, value = (BoneIndex, Bone Object)
+		# THIS IS NOT DUMPED
+		self.BoneLookup = {} 
+		
+	def dump(self):
+		data = self.Generalheader.dump() + self.Bones.dump() + self.Animations.dump() + self.RawKeys.dump()
+		return data
+	
+	def AddBone(self, b):
+		#LOUD
+		#print "AddBone: " + b.Name
+		self.Bones.Data.append(b)
+		
+	def AddAnimation(self, a):
+		#LOUD
+		#print "AddAnimation: %s, TotalBones: %i, AnimRate: %f, NumRawFrames: %i, TrackTime: %f" % (a.Name, a.TotalBones, a.AnimRate, a.NumRawFrames, a.TrackTime)
+		self.Animations.Data.append(a)
+		
+	def AddRawKey(self, k):
+		#LOUD
+		#print "AddRawKey [%i]: Time: %f, Quat: x=%f, y=%f, z=%f, w=%f, Position: x=%f, y=%f, z=%f" % (len(self.RawKeys.Data), k.Time, k.Orientation.X, k.Orientation.Y, k.Orientation.Z, k.Orientation.W, k.Position.X, k.Position.Y, k.Position.Z)
+		self.RawKeys.Data.append(k)
+		
+	def UpdateHeaders(self):
+		self.Bones.UpdateHeader()
+		self.Animations.UpdateHeader()
+		self.RawKeys.UpdateHeader()
+		
+	def GetBoneByIndex(self, bone_index):
+		if bone_index >= 0 and len(self.Bones.Data) > bone_index:
+			return self.Bones.Data[bone_index]
+	
+	def IsEmpty(self):
+		return (len(self.Bones.Data) == 0 or len(self.Animations.Data) == 0)
+	
+	def StoreBone(self, b):
+		self.BoneLookup[b.Name] = [-1, b]
+					
+	def UseBone(self, bone_name):
+		if bone_name in self.BoneLookup:
+			bone_data = self.BoneLookup[bone_name]
+			
+			if bone_data[0] == -1:
+				bone_data[0] = len(self.Bones.Data)
+				self.AddBone(bone_data[1])
+				#self.Bones.Data.append(bone_data[1])
+			
+			return bone_data[0]
+			
+	def GetBoneByName(self, bone_name):
+		if bone_name in self.BoneLookup:
+			bone_data = self.BoneLookup[bone_name]
+			return bone_data[1]
+		
+	def GetBoneIndex(self, bone_name):
+		if bone_name in self.BoneLookup:
+			bone_data = self.BoneLookup[bone_name]
+			return bone_data[0]
+		
+	def dump(self):
+		self.UpdateHeaders()
+		data = self.GeneralHeader.dump() + self.Bones.dump() + self.Animations.dump() + self.RawKeys.dump()
+		return data
+		
+	def PrintOut(self):
+		print ('--- PSA FILE EXPORTED ---')
+		print ('bone count: %i' % len(self.Bones.Data))
+		print ('animation count: %i' % len(self.Animations.Data))
+		print ('rawkey count: %i' % len(self.RawKeys.Data))
+		print ('-------------------------')
+		
 ####################################    
 # helpers to create bone structs
 def make_vbone(name, parent_index, child_count, orientation_quat, position_vect):
-    bone = VBone()
-    bone.Name = name
-    bone.ParentIndex = parent_index
-    bone.NumChildren = child_count
-    bone.BonePos.Orientation = orientation_quat
-    bone.BonePos.Position.X = position_vect.x
-    bone.BonePos.Position.Y = position_vect.y
-    bone.BonePos.Position.Z = position_vect.z
-    
-    #these values seem to be ignored?
-    #bone.BonePos.Length = tail.length
-    #bone.BonePos.XSize = tail.x
-    #bone.BonePos.YSize = tail.y
-    #bone.BonePos.ZSize = tail.z
-
-    return bone
+	bone = VBone()
+	bone.Name = name
+	bone.ParentIndex = parent_index
+	bone.NumChildren = child_count
+	bone.BonePos.Orientation = orientation_quat
+	bone.BonePos.Position.X = position_vect.x
+	bone.BonePos.Position.Y = position_vect.y
+	bone.BonePos.Position.Z = position_vect.z
+	
+	#these values seem to be ignored?
+	#bone.BonePos.Length = tail.length
+	#bone.BonePos.XSize = tail.x
+	#bone.BonePos.YSize = tail.y
+	#bone.BonePos.ZSize = tail.z
+
+	return bone
 
 def make_namedbonebinary(name, parent_index, child_count, orientation_quat, position_vect, is_real):
-    bone = FNamedBoneBinary()
-    bone.Name = name
-    bone.ParentIndex = parent_index
-    bone.NumChildren = child_count
-    bone.BonePos.Orientation = orientation_quat
-    bone.BonePos.Position.X = position_vect.x
-    bone.BonePos.Position.Y = position_vect.y
-    bone.BonePos.Position.Z = position_vect.z
-    bone.IsRealBone = is_real
-    return bone    
-    
+	bone = FNamedBoneBinary()
+	bone.Name = name
+	bone.ParentIndex = parent_index
+	bone.NumChildren = child_count
+	bone.BonePos.Orientation = orientation_quat
+	bone.BonePos.Position.X = position_vect.x
+	bone.BonePos.Position.Y = position_vect.y
+	bone.BonePos.Position.Z = position_vect.z
+	bone.IsRealBone = is_real
+	return bone    
+	
 ##################################################
 #RG - check to make sure face isnt a line
 #The face has to be triangle not a line
 def is_1d_face(blender_face,mesh):
-    #ID Vertex of id point
-    v0 = blender_face.vertices[0]
-    v1 = blender_face.vertices[1]
-    v2 = blender_face.vertices[2]
-    
-    return (mesh.vertices[v0].co == mesh.vertices[v1].co or \
-    mesh.vertices[v1].co == mesh.vertices[v2].co or \
-    mesh.vertices[v2].co == mesh.vertices[v0].co)
-    return False
+	#ID Vertex of id point
+	v0 = blender_face.vertices[0]
+	v1 = blender_face.vertices[1]
+	v2 = blender_face.vertices[2]
+	
+	return (mesh.vertices[v0].co == mesh.vertices[v1].co or \
+	mesh.vertices[v1].co == mesh.vertices[v2].co or \
+	mesh.vertices[v2].co == mesh.vertices[v0].co)
+	return False
 
 ##################################################
 # http://en.wikibooks.org/wiki/Blender_3D:_Blending_Into_Python/Cookbook#Triangulate_NMesh
 
 #blender 2.50 format using the Operators/command convert the mesh to tri mesh
 def triangulateNMesh(object):
-    bneedtri = False
-    scene = bpy.context.scene
-    bpy.ops.object.mode_set(mode='OBJECT')
-    for i in scene.objects: i.select = False #deselect all objects
-    object.select = True
-    scene.objects.active = object #set the mesh object to current
-    bpy.ops.object.mode_set(mode='OBJECT')
-    print("Checking mesh if needs to convert quad to Tri...")
-    for face in object.data.faces:
-        if (len(face.vertices) > 3):
-            bneedtri = True
-            break
-    
-    bpy.ops.object.mode_set(mode='OBJECT')
-    if bneedtri == True:
-        print("Converting quad to tri mesh...")
-        me_da = object.data.copy() #copy data
-        me_ob = object.copy() #copy object
-        #note two copy two types else it will use the current data or mesh
-        me_ob.data = me_da
-        bpy.context.scene.objects.link(me_ob)#link the object to the scene #current object location
-        for i in scene.objects: i.select = False #deselect all objects
-        me_ob.select = True
-        scene.objects.active = me_ob #set the mesh object to current
-        bpy.ops.object.mode_set(mode='EDIT') #Operators
-        bpy.ops.mesh.select_all(action='SELECT')#select all the face/vertex/edge
-        bpy.ops.mesh.quads_convert_to_tris() #Operators
-        bpy.context.scene.update()
-        bpy.ops.object.mode_set(mode='OBJECT') # set it in object
-        bpy.context.scene.unrealtriangulatebool = True
-        print("Triangulate Mesh Done!")
-    else:
-        print("No need to convert tri mesh.")
-        me_ob = object
-    return me_ob
+	bneedtri = False
+	scene = bpy.context.scene
+	bpy.ops.object.mode_set(mode='OBJECT')
+	for i in scene.objects: i.select = False #deselect all objects
+	object.select = True
+	scene.objects.active = object #set the mesh object to current
+	bpy.ops.object.mode_set(mode='OBJECT')
+	print("Checking mesh if needs to convert quad to Tri...")
+	for face in object.data.faces:
+		if (len(face.vertices) > 3):
+			bneedtri = True
+			break
+	
+	bpy.ops.object.mode_set(mode='OBJECT')
+	if bneedtri == True:
+		print("Converting quad to tri mesh...")
+		me_da = object.data.copy() #copy data
+		me_ob = object.copy() #copy object
+		#note two copy two types else it will use the current data or mesh
+		me_ob.data = me_da
+		bpy.context.scene.objects.link(me_ob)#link the object to the scene #current object location
+		for i in scene.objects: i.select = False #deselect all objects
+		me_ob.select = True
+		scene.objects.active = me_ob #set the mesh object to current
+		bpy.ops.object.mode_set(mode='EDIT') #Operators
+		bpy.ops.mesh.select_all(action='SELECT')#select all the face/vertex/edge
+		bpy.ops.mesh.quads_convert_to_tris() #Operators
+		bpy.context.scene.update()
+		bpy.ops.object.mode_set(mode='OBJECT') # set it in object
+		bpy.context.scene.unrealtriangulatebool = True
+		print("Triangulate Mesh Done!")
+	else:
+		print("No need to convert tri mesh.")
+		me_ob = object
+	return me_ob
 
 #Blender Bone Index
 class BBone:
-    def __init__(self):
-        self.bone = ""
-        self.index = 0
+	def __init__(self):
+		self.bone = ""
+		self.index = 0
 bonedata = []
 BBCount = 0    
 #deal with mesh bones groups vertex point
 def BoneIndex(bone):
-    global BBCount, bonedata
-    #print("//==============")
-    #print(bone.name , "ID:",BBCount)
-    BB = BBone()
-    BB.bone = bone.name
-    BB.index = BBCount
-    bonedata.append(BB)
-    BBCount += 1
-    for current_child_bone in bone.children:
-        BoneIndex(current_child_bone)
+	global BBCount, bonedata
+	#print("//==============")
+	#print(bone.name , "ID:",BBCount)
+	BB = BBone()
+	BB.bone = bone.name
+	BB.index = BBCount
+	bonedata.append(BB)
+	BBCount += 1
+	for current_child_bone in bone.children:
+		BoneIndex(current_child_bone)
 
 def BoneIndexArmature(blender_armature):
-    global BBCount
-    #print("\n Buildng bone before mesh \n")
-    #objectbone = blender_armature.pose #Armature bone
-    #print(blender_armature)
-    objectbone = blender_armature[0].pose 
-    #print(dir(ArmatureData))
-    
-    for bone in objectbone.bones:
-        if(bone.parent is None):
-            BoneIndex(bone)
-            #BBCount += 1
-            break
-    
+	global BBCount
+	#print("\n Buildng bone before mesh \n")
+	#objectbone = blender_armature.pose #Armature bone
+	#print(blender_armature)
+	objectbone = blender_armature[0].pose 
+	#print(dir(ArmatureData))
+	
+	for bone in objectbone.bones:
+		if(bone.parent is None):
+			BoneIndex(bone)
+			#BBCount += 1
+			break
+	
 # Actual object parsing functions
 def parse_meshes(blender_meshes, psk_file):
-    #this is use to call the bone name and the index array for group index matches
-    global bonedata
-    #print("BONE DATA",len(bonedata))
-    print ("----- parsing meshes -----")
-    print("Number of Object Meshes:",len(blender_meshes))
-    for current_obj in blender_meshes: #number of mesh that should be one mesh here
-    
-        current_obj = triangulateNMesh(current_obj)
-        #print(dir(current_obj))
-        print("Mesh Name:",current_obj.name)
-        current_mesh = current_obj.data
-        
-        #if len(current_obj.materials) > 0:
-        #    object_mat = current_obj.materials[0]
-        object_material_index = current_obj.active_material_index
-    
-        points = ObjMap()
-        wedges = ObjMap()
-        
-        discarded_face_count = 0
-        print (" -- Dumping Mesh Faces -- LEN:", len(current_mesh.faces))
-        for current_face in current_mesh.faces:
-            #print ' -- Dumping UVs -- '
-            #print current_face.uv_textures
-            
-            if len(current_face.vertices) != 3:
-                raise RuntimeError("Non-triangular face (%i)" % len(current_face.vertices))
-            
-            #No Triangulate Yet
-            #            if len(current_face.vertices) != 3:
-            #                raise RuntimeError("Non-triangular face (%i)" % len(current_face.vertices))
-            #                #TODO: add two fake faces made of triangles?
-            
-            #RG - apparently blender sometimes has problems when you do quad to triangle 
-            #    conversion, and ends up creating faces that have only TWO points -
-            #     one of the points is simply in the vertex list for the face twice. 
-            #    This is bad, since we can't get a real face normal for a LINE, we need 
-            #    a plane for this. So, before we add the face to the list of real faces, 
-            #    ensure that the face is actually a plane, and not a line. If it is not 
-            #    planar, just discard it and notify the user in the console after we're
-            #    done dumping the rest of the faces
-            
-            if not is_1d_face(current_face,current_mesh):
-                #print("faces")
-                wedge_list = []
-                vect_list = []
-                
-                #get or create the current material
-                m = psk_file.GetMatByIndex(object_material_index)
-
-                face_index = current_face.index
-                has_UV = False
-                faceUV = None
-                
-                if len(current_mesh.uv_textures) > 0:
-                    has_UV = True    
-                    #print("face index: ",face_index)
-                    #faceUV = current_mesh.uv_textures.active.data[face_index]#UVs for current face
-                    #faceUV = current_mesh.uv_textures.active.data[0]#UVs for current face
-                    #print(face_index,"<[FACE NUMBER")
-                    uv_layer = current_mesh.uv_textures.active
-                    faceUV = uv_layer.data[face_index]
-                    #print("============================")
-                    #size(data) is number of texture faces. Each face has UVs
-                    #print("DATA face uv: ",len(faceUV.uv), " >> ",(faceUV.uv[0][0]))
-                
-                for i in range(3):
-                    vert_index = current_face.vertices[i]
-                    vert = current_mesh.vertices[vert_index]
-                    uv = []
-                    #assumes 3 UVs Per face (for now).
-                    if (has_UV):
-                        if len(faceUV.uv) != 3:
-                            print ("WARNING: Current face is missing UV coordinates - writing 0,0...")
-                            print ("WARNING: Face has more than 3 UVs - writing 0,0...")
-                            uv = [0.0, 0.0]
-                        else:
-                            #uv.append(faceUV.uv[i][0])
-                            #uv.append(faceUV.uv[i][1])
-                            uv = [faceUV.uv[i][0],faceUV.uv[i][1]] #OR bottom works better # 24 for cube
-                            #uv = list(faceUV.uv[i]) #30 just cube    
-                    else:
-                        print ("No UVs?")
-                        uv = [0.0, 0.0]
-                    #print("UV >",uv)
-                    #uv = [0.0, 0.0] #over ride uv that is not fixed
-                    #print(uv)
-                    #flip V coordinate because UEd requires it and DOESN'T flip it on its own like it
-                    #does with the mesh Y coordinates.
-                    #this is otherwise known as MAGIC-2
-                    uv[1] = 1.0 - uv[1]
-                    
-                    #deal with the min and max value
-                    #if value is over the set limit it will null the uv texture
-                    if (uv[0] > 1):
-                        uv[0] = 1
-                    if (uv[0] < 0):
-                        uv[0] = 0
-                    if (uv[1] > 1):
-                        uv[1] = 1
-                    if (uv[1] < 0):
-                        uv[1] = 0
-
-                    
-                    # RE - Append untransformed vector (for normal calc below)
-                    # TODO: convert to Blender.Mathutils
-                    vect_list.append(FVector(vert.co.x, vert.co.y, vert.co.z))
-                    
-                    # Transform position for export
-                    #vpos = vert.co * object_material_index
-                    vpos = vert.co * current_obj.matrix_local
-                    # Create the point
-                    p = VPoint()
-                    p.Point.X = vpos.x
-                    p.Point.Y = vpos.y
-                    p.Point.Z = vpos.z
-                    
-                    # Create the wedge
-                    w = VVertex()
-                    w.MatIndex = object_material_index
-                    w.PointIndex = points.get(p) # get index from map
-                    #Set UV TEXTURE
-                    w.U = uv[0]
-                    w.V = uv[1]
-                    index_wedge = wedges.get(w)
-                    wedge_list.append(index_wedge)
-                    
-                    #print results
-                    #print 'result PointIndex=%i, U=%f, V=%f, wedge_index=%i' % (
-                    #    w.PointIndex,
-                    #    w.U,
-                    #    w.V,
-                    #    wedge_index)
-                
-                # Determine face vertex order
-                # get normal from blender
-                no = current_face.normal
-                
-                # TODO: convert to Blender.Mathutils
-                # convert to FVector
-                norm = FVector(no[0], no[1], no[2])
-                
-                # Calculate the normal of the face in blender order
-                tnorm = vect_list[1].sub(vect_list[0]).cross(vect_list[2].sub(vect_list[1]))
-                
-                # RE - dot the normal from blender order against the blender normal
-                # this gives the product of the two vectors' lengths along the blender normal axis
-                # all that matters is the sign
-                dot = norm.dot(tnorm)
-
-                # print results
-                #print 'face norm: (%f,%f,%f), tnorm=(%f,%f,%f), dot=%f' % (
-                #    norm.X, norm.Y, norm.Z,
-                #    tnorm.X, tnorm.Y, tnorm.Z,
-                #    dot)
-
-                tri = VTriangle()
-                # RE - magic: if the dot product above > 0, order the vertices 2, 1, 0
-                #        if the dot product above < 0, order the vertices 0, 1, 2
-                #        if the dot product is 0, then blender's normal is coplanar with the face
-                #        and we cannot deduce which side of the face is the outside of the mesh
-                if (dot > 0):
-                    (tri.WedgeIndex2, tri.WedgeIndex1, tri.WedgeIndex0) = wedge_list
-                elif (dot < 0):
-                    (tri.WedgeIndex0, tri.WedgeIndex1, tri.WedgeIndex2) = wedge_list
-                else:
-                    dindex0 = current_face.vertices[0];
-                    dindex1 = current_face.vertices[1];
-                    dindex2 = current_face.vertices[2];
-                    raise RuntimeError("normal vector coplanar with face! points:", current_mesh.vertices[dindex0].co, current_mesh.vertices[dindex1].co, current_mesh.vertices[dindex2].co)
-                
-                tri.MatIndex = object_material_index
-                #print(tri)
-                psk_file.AddFace(tri)
-                
-            else:
-                discarded_face_count = discarded_face_count + 1
-                
-        print (" -- Dumping Mesh Points -- LEN:",len(points.dict))
-        for point in points.items():
-            psk_file.AddPoint(point)
-        print (" -- Dumping Mesh Wedge -- LEN:",len(wedges.dict))
-        for wedge in wedges.items():
-            psk_file.AddWedge(wedge)
-            
-        #RG - if we happend upon any non-planar faces above that we've discarded, 
-        #    just let the user know we discarded them here in case they want 
-        #    to investigate
-    
-        if discarded_face_count > 0: 
-            print ("INFO: Discarded %i non-planar faces." % (discarded_face_count))
-        
-        #RG - walk through the vertex groups and find the indexes into the PSK points array 
-        #for them, then store that index and the weight as a tuple in a new list of 
-        #verts for the group that we can look up later by bone name, since Blender matches
-        #verts to bones for influences by having the VertexGroup named the same thing as
-        #the bone
-
-        #vertex group.
-        for bonegroup in bonedata:
-            #print("bone gourp build:",bonegroup.bone)
-            vert_list = []
-            for current_vert in current_mesh.vertices:
-                #print("INDEX V:",current_vert.index)
-                vert_index = current_vert.index
-                for vgroup in current_vert.groups:#vertex groupd id
-                    vert_weight = vgroup.weight
-                    if(bonegroup.index == vgroup.group):
-                        p = VPoint()
-                        vpos = current_vert.co * current_obj.matrix_local
-                        p.Point.X = vpos.x
-                        p.Point.Y = vpos.y 
-                        p.Point.Z = vpos.z
-                        #print(current_vert.co)
-                        point_index = points.get(p) #point index
-                        v_item = (point_index, vert_weight)
-                        vert_list.append(v_item)
-            #bone name, [point id and wieght]
-            #print("Add Vertex Group:",bonegroup.bone, " No. Points:",len(vert_list))
-            psk_file.VertexGroups[bonegroup.bone] = vert_list
-        
-        #unrealtriangulatebool #this will remove the mesh from the scene
-        if (bpy.context.scene.unrealtriangulatebool == True):
-            print("Remove tmp Mesh [ " ,current_obj.name, " ] from scene >"  ,(bpy.context.scene.unrealtriangulatebool ))
-            bpy.ops.object.mode_set(mode='OBJECT') # set it in object
-            bpy.context.scene.objects.unlink(current_obj)
-        
+	#this is use to call the bone name and the index array for group index matches
+	global bonedata
+	#print("BONE DATA",len(bonedata))
+	print ("----- parsing meshes -----")
+	print("Number of Object Meshes:",len(blender_meshes))
+	for current_obj in blender_meshes: #number of mesh that should be one mesh here
+	
+		current_obj = triangulateNMesh(current_obj)
+		#print(dir(current_obj))
+		print("Mesh Name:",current_obj.name)
+		current_mesh = current_obj.data
+		
+		#if len(current_obj.materials) > 0:
+		#    object_mat = current_obj.materials[0]
+		object_material_index = current_obj.active_material_index
+	
+		points = ObjMap()
+		wedges = ObjMap()
+		
+		discarded_face_count = 0
+		print (" -- Dumping Mesh Faces -- LEN:", len(current_mesh.faces))
+		for current_face in current_mesh.faces:
+			#print ' -- Dumping UVs -- '
+			#print current_face.uv_textures
+			
+			if len(current_face.vertices) != 3:
+				raise RuntimeError("Non-triangular face (%i)" % len(current_face.vertices))
+			
+			#No Triangulate Yet
+			#            if len(current_face.vertices) != 3:
+			#                raise RuntimeError("Non-triangular face (%i)" % len(current_face.vertices))
+			#                #TODO: add two fake faces made of triangles?
+			
+			#RG - apparently blender sometimes has problems when you do quad to triangle 
+			#    conversion, and ends up creating faces that have only TWO points -
+			#     one of the points is simply in the vertex list for the face twice. 
+			#    This is bad, since we can't get a real face normal for a LINE, we need 
+			#    a plane for this. So, before we add the face to the list of real faces, 
+			#    ensure that the face is actually a plane, and not a line. If it is not 
+			#    planar, just discard it and notify the user in the console after we're
+			#    done dumping the rest of the faces
+			
+			if not is_1d_face(current_face,current_mesh):
+				#print("faces")
+				wedge_list = []
+				vect_list = []
+				
+				#get or create the current material
+				m = psk_file.GetMatByIndex(object_material_index)
+
+				face_index = current_face.index
+				has_UV = False
+				faceUV = None
+				
+				if len(current_mesh.uv_textures) > 0:
+					has_UV = True    
+					#print("face index: ",face_index)
+					#faceUV = current_mesh.uv_textures.active.data[face_index]#UVs for current face
+					#faceUV = current_mesh.uv_textures.active.data[0]#UVs for current face
+					#print(face_index,"<[FACE NUMBER")
+					uv_layer = current_mesh.uv_textures.active
+					faceUV = uv_layer.data[face_index]
+					#print("============================")
+					#size(data) is number of texture faces. Each face has UVs
+					#print("DATA face uv: ",len(faceUV.uv), " >> ",(faceUV.uv[0][0]))
+				
+				for i in range(3):
+					vert_index = current_face.vertices[i]
+					vert = current_mesh.vertices[vert_index]
+					uv = []
+					#assumes 3 UVs Per face (for now).
+					if (has_UV):
+						if len(faceUV.uv) != 3:
+							print ("WARNING: Current face is missing UV coordinates - writing 0,0...")
+							print ("WARNING: Face has more than 3 UVs - writing 0,0...")
+							uv = [0.0, 0.0]
+						else:
+							#uv.append(faceUV.uv[i][0])
+							#uv.append(faceUV.uv[i][1])
+							uv = [faceUV.uv[i][0],faceUV.uv[i][1]] #OR bottom works better # 24 for cube
+							#uv = list(faceUV.uv[i]) #30 just cube    
+					else:
+						print ("No UVs?")
+						uv = [0.0, 0.0]
+					#print("UV >",uv)
+					#uv = [0.0, 0.0] #over ride uv that is not fixed
+					#print(uv)
+					#flip V coordinate because UEd requires it and DOESN'T flip it on its own like it
+					#does with the mesh Y coordinates.
+					#this is otherwise known as MAGIC-2
+					uv[1] = 1.0 - uv[1]
+					
+					#deal with the min and max value
+					#if value is over the set limit it will null the uv texture
+					if (uv[0] > 1):
+						uv[0] = 1
+					if (uv[0] < 0):
+						uv[0] = 0
+					if (uv[1] > 1):
+						uv[1] = 1
+					if (uv[1] < 0):
+						uv[1] = 0
+
+					
+					# RE - Append untransformed vector (for normal calc below)
+					# TODO: convert to Blender.Mathutils
+					vect_list.append(FVector(vert.co.x, vert.co.y, vert.co.z))
+					
+					# Transform position for export
+					#vpos = vert.co * object_material_index
+					vpos = vert.co * current_obj.matrix_local
+					# Create the point
+					p = VPoint()
+					p.Point.X = vpos.x
+					p.Point.Y = vpos.y
+					p.Point.Z = vpos.z
+					
+					# Create the wedge
+					w = VVertex()
+					w.MatIndex = object_material_index
+					w.PointIndex = points.get(p) # get index from map
+					#Set UV TEXTURE
+					w.U = uv[0]
+					w.V = uv[1]
+					index_wedge = wedges.get(w)
+					wedge_list.append(index_wedge)
+					
+					#print results
+					#print 'result PointIndex=%i, U=%f, V=%f, wedge_index=%i' % (
+					#    w.PointIndex,
+					#    w.U,
+					#    w.V,
+					#    wedge_index)
+				
+				# Determine face vertex order
+				# get normal from blender
+				no = current_face.normal
+				
+				# TODO: convert to Blender.Mathutils
+				# convert to FVector
+				norm = FVector(no[0], no[1], no[2])
+				
+				# Calculate the normal of the face in blender order
+				tnorm = vect_list[1].sub(vect_list[0]).cross(vect_list[2].sub(vect_list[1]))
+				
+				# RE - dot the normal from blender order against the blender normal
+				# this gives the product of the two vectors' lengths along the blender normal axis
+				# all that matters is the sign
+				dot = norm.dot(tnorm)
+
+				# print results
+				#print 'face norm: (%f,%f,%f), tnorm=(%f,%f,%f), dot=%f' % (
+				#    norm.X, norm.Y, norm.Z,
+				#    tnorm.X, tnorm.Y, tnorm.Z,
+				#    dot)
+
+				tri = VTriangle()
+				# RE - magic: if the dot product above > 0, order the vertices 2, 1, 0
+				#        if the dot product above < 0, order the vertices 0, 1, 2
+				#        if the dot product is 0, then blender's normal is coplanar with the face
+				#        and we cannot deduce which side of the face is the outside of the mesh
+				if (dot > 0):
+					(tri.WedgeIndex2, tri.WedgeIndex1, tri.WedgeIndex0) = wedge_list
+				elif (dot < 0):
+					(tri.WedgeIndex0, tri.WedgeIndex1, tri.WedgeIndex2) = wedge_list
+				else:
+					dindex0 = current_face.vertices[0];
+					dindex1 = current_face.vertices[1];
+					dindex2 = current_face.vertices[2];
+					raise RuntimeError("normal vector coplanar with face! points:", current_mesh.vertices[dindex0].co, current_mesh.vertices[dindex1].co, current_mesh.vertices[dindex2].co)
+				
+				tri.MatIndex = object_material_index
+				#print(tri)
+				psk_file.AddFace(tri)
+				
+			else:
+				discarded_face_count = discarded_face_count + 1
+				
+		print (" -- Dumping Mesh Points -- LEN:",len(points.dict))
+		for point in points.items():
+			psk_file.AddPoint(point)
+		print (" -- Dumping Mesh Wedge -- LEN:",len(wedges.dict))
+		for wedge in wedges.items():
+			psk_file.AddWedge(wedge)
+			
+		#RG - if we happend upon any non-planar faces above that we've discarded, 
+		#    just let the user know we discarded them here in case they want 
+		#    to investigate
+	
+		if discarded_face_count > 0: 
+			print ("INFO: Discarded %i non-planar faces." % (discarded_face_count))
+		
+		#RG - walk through the vertex groups and find the indexes into the PSK points array 
+		#for them, then store that index and the weight as a tuple in a new list of 
+		#verts for the group that we can look up later by bone name, since Blender matches
+		#verts to bones for influences by having the VertexGroup named the same thing as
+		#the bone
+
+		#vertex group.
+		for bonegroup in bonedata:
+			#print("bone gourp build:",bonegroup.bone)
+			vert_list = []
+			for current_vert in current_mesh.vertices:
+				#print("INDEX V:",current_vert.index)
+				vert_index = current_vert.index
+				for vgroup in current_vert.groups:#vertex groupd id
+					vert_weight = vgroup.weight
+					if(bonegroup.index == vgroup.group):
+						p = VPoint()
+						vpos = current_vert.co * current_obj.matrix_local
+						p.Point.X = vpos.x
+						p.Point.Y = vpos.y 
+						p.Point.Z = vpos.z
+						#print(current_vert.co)
+						point_index = points.get(p) #point index
+						v_item = (point_index, vert_weight)
+						vert_list.append(v_item)
+			#bone name, [point id and wieght]
+			#print("Add Vertex Group:",bonegroup.bone, " No. Points:",len(vert_list))
+			psk_file.VertexGroups[bonegroup.bone] = vert_list
+		
+		#unrealtriangulatebool #this will remove the mesh from the scene
+		if (bpy.context.scene.unrealtriangulatebool == True):
+			print("Remove tmp Mesh [ " ,current_obj.name, " ] from scene >"  ,(bpy.context.scene.unrealtriangulatebool ))
+			bpy.ops.object.mode_set(mode='OBJECT') # set it in object
+			bpy.context.scene.objects.unlink(current_obj)
+		
 def make_fquat(bquat):
-    quat = FQuat()
-    
-    #flip handedness for UT = set x,y,z to negative (rotate in other direction)
-    quat.X = -bquat.x
-    quat.Y = -bquat.y
-    quat.Z = -bquat.z
-
-    quat.W = bquat.w
-    return quat
-    
+	quat = FQuat()
+	
+	#flip handedness for UT = set x,y,z to negative (rotate in other direction)
+	quat.X = -bquat.x
+	quat.Y = -bquat.y
+	quat.Z = -bquat.z
+
+	quat.W = bquat.w
+	return quat
+	
 def make_fquat_default(bquat):
-    quat = FQuat()
-    
-    quat.X = bquat.x
-    quat.Y = bquat.y
-    quat.Z = bquat.z
-    
-    quat.W = bquat.w
-    return quat
+	quat = FQuat()
+	
+	quat.X = bquat.x
+	quat.Y = bquat.y
+	quat.Z = bquat.z
+	
+	quat.W = bquat.w
+	return quat
 
 # =================================================================================================
 # TODO: remove this 1am hack
 nbone = 0
 def parse_bone(blender_bone, psk_file, psa_file, parent_id, is_root_bone, parent_matrix, parent_root):
-    global nbone     # look it's evil!
-    #print '-------------------- Dumping Bone ---------------------- '
-
-    #If bone does not have parent that mean it the root bone
-    if blender_bone.parent is None:
-        parent_root = blender_bone
-    
-    
-    child_count = len(blender_bone.children)
-    #child of parent
-    child_parent = blender_bone.parent
-    
-    if child_parent != None:
-        print ("--Bone Name:",blender_bone.name ," parent:" , blender_bone.parent.name, "ID:", nbone)
-    else:
-        print ("--Bone Name:",blender_bone.name ," parent: None" , "ID:", nbone)
-    
-    if child_parent != None:
-        quat_root = blender_bone.matrix
-        quat = make_fquat(quat_root.to_quat())
-        
-        quat_parent = child_parent.matrix.to_quat().inverse()
-        parent_head = child_parent.head * quat_parent
-        parent_tail = child_parent.tail * quat_parent
-        
-        set_position = (parent_tail - parent_head) + blender_bone.head
-    else:
-        # ROOT BONE
-        #This for root 
-        set_position = blender_bone.head * parent_matrix #ARMATURE OBJECT Locction
-        rot_mat = blender_bone.matrix * parent_matrix.rotation_part() #ARMATURE OBJECT Rotation
-        #print(dir(rot_mat))
-        
-        quat = make_fquat_default(rot_mat.to_quat())
-        
-    print ("[[======= FINAL POSITION:", set_position)
-    final_parent_id = parent_id
-    
-    #RG/RE -
-    #if we are not seperated by a small distance, create a dummy bone for the displacement
-    #this is only needed for root bones, since UT assumes a connected skeleton, and from here
-    #down the chain we just use "tail" as an endpoint
-    #if(head.length > 0.001 and is_root_bone == 1):
-    if(0):    
-        pb = make_vbone("dummy_" + blender_bone.name, parent_id, 1, FQuat(), tail)
-        psk_file.AddBone(pb)
-        pbb = make_namedbonebinary("dummy_" + blender_bone.name, parent_id, 1, FQuat(), tail, 0)
-        psa_file.StoreBone(pbb)
-        final_parent_id = nbone
-        nbone = nbone + 1
-        #tail = tail-head
-        
-    my_id = nbone
-    
-    pb = make_vbone(blender_bone.name, final_parent_id, child_count, quat, set_position)
-    psk_file.AddBone(pb)
-    pbb = make_namedbonebinary(blender_bone.name, final_parent_id, child_count, quat, set_position, 1)
-    psa_file.StoreBone(pbb)
-
-    nbone = nbone + 1
-    
-    #RG - dump influences for this bone - use the data we collected in the mesh dump phase
-    # to map our bones to vertex groups
-    #print("///////////////////////")
-    #print("set influence")
-    if blender_bone.name in psk_file.VertexGroups:
-        vertex_list = psk_file.VertexGroups[blender_bone.name]
-        #print("vertex list:", len(vertex_list), " of >" ,blender_bone.name )
-        for vertex_data in vertex_list:
-            #print("set influence vettex")
-            point_index = vertex_data[0]
-            vertex_weight = vertex_data[1]
-            influence = VRawBoneInfluence()
-            influence.Weight = vertex_weight
-            #influence.BoneIndex = my_id
-            influence.BoneIndex = my_id
-            influence.PointIndex = point_index
-            #print(influence)
-            #print ('Adding Bone Influence for [%s] = Point Index=%i, Weight=%f' % (blender_bone.name, point_index, vertex_weight))
-            #print("adding influence")
-            psk_file.AddInfluence(influence)
-    
-    #blender_bone.matrix_local
-    #recursively dump child bones
-    mainparent = parent_matrix
-    #if len(blender_bone.children) > 0:
-    for current_child_bone in blender_bone.children:
-        parse_bone(current_child_bone, psk_file, psa_file, my_id, 0, mainparent, parent_root)
+	global nbone     # look it's evil!
+	#print '-------------------- Dumping Bone ---------------------- '
+
+	#If bone does not have parent that mean it the root bone
+	if blender_bone.parent is None:
+		parent_root = blender_bone
+	
+	
+	child_count = len(blender_bone.children)
+	#child of parent
+	child_parent = blender_bone.parent
+	
+	if child_parent != None:
+		print ("--Bone Name:",blender_bone.name ," parent:" , blender_bone.parent.name, "ID:", nbone)
+	else:
+		print ("--Bone Name:",blender_bone.name ," parent: None" , "ID:", nbone)
+	
+	if child_parent != None:
+		quat_root = blender_bone.matrix
+		quat = make_fquat(quat_root.to_quat())
+		
+		quat_parent = child_parent.matrix.to_quat().inverse()
+		parent_head = child_parent.head * quat_parent
+		parent_tail = child_parent.tail * quat_parent
+		
+		set_position = (parent_tail - parent_head) + blender_bone.head
+	else:
+		# ROOT BONE
+		#This for root 
+		set_position = blender_bone.head * parent_matrix #ARMATURE OBJECT Locction
+		rot_mat = blender_bone.matrix * parent_matrix.rotation_part() #ARMATURE OBJECT Rotation
+		#print(dir(rot_mat))
+		
+		quat = make_fquat_default(rot_mat.to_quat())
+		
+	print ("[[======= FINAL POSITION:", set_position)
+	final_parent_id = parent_id
+	
+	#RG/RE -
+	#if we are not seperated by a small distance, create a dummy bone for the displacement
+	#this is only needed for root bones, since UT assumes a connected skeleton, and from here
+	#down the chain we just use "tail" as an endpoint
+	#if(head.length > 0.001 and is_root_bone == 1):
+	if(0):    
+		pb = make_vbone("dummy_" + blender_bone.name, parent_id, 1, FQuat(), tail)
+		psk_file.AddBone(pb)
+		pbb = make_namedbonebinary("dummy_" + blender_bone.name, parent_id, 1, FQuat(), tail, 0)
+		psa_file.StoreBone(pbb)
+		final_parent_id = nbone
+		nbone = nbone + 1
+		#tail = tail-head
+		
+	my_id = nbone
+	
+	pb = make_vbone(blender_bone.name, final_parent_id, child_count, quat, set_position)
+	psk_file.AddBone(pb)
+	pbb = make_namedbonebinary(blender_bone.name, final_parent_id, child_count, quat, set_position, 1)
+	psa_file.StoreBone(pbb)
+
+	nbone = nbone + 1
+	
+	#RG - dump influences for this bone - use the data we collected in the mesh dump phase
+	# to map our bones to vertex groups
+	#print("///////////////////////")
+	#print("set influence")
+	if blender_bone.name in psk_file.VertexGroups:
+		vertex_list = psk_file.VertexGroups[blender_bone.name]
+		#print("vertex list:", len(vertex_list), " of >" ,blender_bone.name )
+		for vertex_data in vertex_list:
+			#print("set influence vettex")
+			point_index = vertex_data[0]
+			vertex_weight = vertex_data[1]
+			influence = VRawBoneInfluence()
+			influence.Weight = vertex_weight
+			#influence.BoneIndex = my_id
+			influence.BoneIndex = my_id
+			influence.PointIndex = point_index
+			#print(influence)
+			#print ('Adding Bone Influence for [%s] = Point Index=%i, Weight=%f' % (blender_bone.name, point_index, vertex_weight))
+			#print("adding influence")
+			psk_file.AddInfluence(influence)
+	
+	#blender_bone.matrix_local
+	#recursively dump child bones
+	mainparent = parent_matrix
+	#if len(blender_bone.children) > 0:
+	for current_child_bone in blender_bone.children:
+		parse_bone(current_child_bone, psk_file, psa_file, my_id, 0, mainparent, parent_root)
 
 def parse_armature(blender_armature, psk_file, psa_file):
-    print ("----- parsing armature -----")
-    print ('blender_armature length: %i' % (len(blender_armature)))
-    
-    #magic 0 sized root bone for UT - this is where all armature dummy bones will attach
-    #dont increment nbone here because we initialize it to 1 (hackity hackity hack)
-
-    #count top level bones first. NOT EFFICIENT.
-    child_count = 0
-    for current_obj in blender_armature: 
-        current_armature = current_obj.data
-        bones = [x for x in current_armature.bones if not x.parent is None]
-        child_count += len(bones)
-
-    for current_obj in blender_armature:
-        print ("Current Armature Name: " + current_obj.name)
-        current_armature = current_obj.data
-        #armature_id = make_armature_bone(current_obj, psk_file, psa_file)
-        
-        #we dont want children here - only the top level bones of the armature itself
-        #we will recursively dump the child bones as we dump these bones
-        """
-        bones = [x for x in current_armature.bones if not x.parent is None]
-        #will ingore this part of the ocde
-        """
-        for current_bone in current_armature.bones: #list the bone. #note this will list all the bones.
-            if(current_bone.parent is None):
-                parse_bone(current_bone, psk_file, psa_file, 0, 0, current_obj.matrix_local, None)
-                break
+	print ("----- parsing armature -----")
+	print ('blender_armature length: %i' % (len(blender_armature)))
+	
+	#magic 0 sized root bone for UT - this is where all armature dummy bones will attach
+	#dont increment nbone here because we initialize it to 1 (hackity hackity hack)
+
+	#count top level bones first. NOT EFFICIENT.
+	child_count = 0
+	for current_obj in blender_armature: 
+		current_armature = current_obj.data
+		bones = [x for x in current_armature.bones if not x.parent is None]
+		child_count += len(bones)
+
+	for current_obj in blender_armature:
+		print ("Current Armature Name: " + current_obj.name)
+		current_armature = current_obj.data
+		#armature_id = make_armature_bone(current_obj, psk_file, psa_file)
+		
+		#we dont want children here - only the top level bones of the armature itself
+		#we will recursively dump the child bones as we dump these bones
+		"""
+		bones = [x for x in current_armature.bones if not x.parent is None]
+		#will ingore this part of the ocde
+		"""
+		for current_bone in current_armature.bones: #list the bone. #note this will list all the bones.
+			if(current_bone.parent is None):
+				parse_bone(current_bone, psk_file, psa_file, 0, 0, current_obj.matrix_local, None)
+				break
 
 # get blender objects by type        
 def get_blender_objects(objects, intype):
-    return [x for x in objects if x.type == intype]
-            
+	return [x for x in objects if x.type == intype]
+			
 #strips current extension (if any) from filename and replaces it with extension passed in
 def make_filename_ext(filename, extension):
-    new_filename = ''
-    extension_index = filename.find('.')
-    
-    if extension_index == -1:
-        new_filename = filename + extension
-    else:
-        new_filename = filename[0:extension_index] + extension
-        
-    return new_filename
+	new_filename = ''
+	extension_index = filename.find('.')
+	
+	if extension_index == -1:
+		new_filename = filename + extension
+	else:
+		new_filename = filename[0:extension_index] + extension
+		
+	return new_filename
 
 # returns the quaternion Grassman product a*b
 # this is the same as the rotation a(b(x)) 
 # (ie. the same as B*A if A and B are matrices representing 
 # the rotations described by quaternions a and b)
 def grassman(a, b):    
-    return mathutils.Quaternion(
-        a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z,
-        a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y,
-        a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x,
-        a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w)
-        
+	return mathutils.Quaternion(
+		a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z,
+		a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y,
+		a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x,
+		a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w)
+		
 def parse_animation(blender_scene, blender_armatures, psa_file):
-    #to do list:
-    #need to list the action sets
-    #need to check if there animation
-    #need to check if animation is has one frame then exit it
-    print ('\n----- parsing animation -----')
-    ##print(dir(blender_scene))
-    
-    #print(dir(blender_armatures))
-    
-    render_data = blender_scene.render
-    bHaveAction = True
-    
-    anim_rate = render_data.fps
-    
-    #print("dir:",dir(blender_scene))
-    #print(dir(bpy.data.actions))
-    #print("dir:",dir(bpy.data.actions[0]))
-    
-    
-    print("==== Blender Settings ====")
-    print ('Scene: %s Start Frame: %i, End Frame: %i' % (blender_scene.name, blender_scene.frame_start, blender_scene.frame_end))
-    print ('Frames Per Sec: %i' % anim_rate)
-    print ("Default FPS: 24" )
-    
-    cur_frame_index = 0
-    
-    #print(dir(bpy.data.actions))
-    #print(dir(bpy.context.scene.background_set))
-    
-    #list of armature objects
-    for arm in blender_armatures:
-        #check if there animation data from armature or something
-        #print(dir(arm.animation_data))
-        #print("[["+dir(arm.animation_data.action))
-        if not arm.animation_data:
-            print("======================================")
-            print("Check Animation Data: None")
-            print("Armature has no animation, skipping...")
-            print("======================================")
-            break
-            
-        if not arm.animation_data.action:
-            print("======================================")
-            print("Check Action: None")
-            print("Armature has no animation, skipping...")
-            print("======================================")
-            break
-        act = arm.animation_data.action
-        #print(dir(act))
-        action_name = act.name
-        
-        if not len(act.fcurves):
-            print("//===========================================================")
-            print("// None bone pose set keys for this action set... skipping...")
-            print("//===========================================================")
-            bHaveAction = False
-            
-        #this deal with action export control
-        if bHaveAction == True:
-            print("")
-            print("==== Action Set ====")
-            print("Action Name:",action_name)
-            #look for min and max frame that current set keys
-            framemin, framemax = act.frame_range
-            #print("max frame:",framemax)
-            start_frame = int(framemin)
-            end_frame = int(framemax)
-            scene_frames = range(start_frame, end_frame+1)
-            frame_count = len(scene_frames)
-            #===================================================
-            anim = AnimInfoBinary()
-            anim.Name = action_name
-            anim.Group = "" #what is group?
-            anim.NumRawFrames = frame_count
-            anim.AnimRate = anim_rate
-            anim.FirstRawFrame = cur_frame_index
-            #===================================================
-            count_previous_keys = len(psa_file.RawKeys.Data)
-            print("Frame Key Set Count:",frame_count, "Total Frame:",frame_count)
-            #print("init action bones...")
-            unique_bone_indexes = {}
-            # bone lookup table
-            bones_lookup =  {}
-        
-            #build bone node for animation keys needed to be set
-            for bone in arm.data.bones:
-                bones_lookup[bone.name] = bone
-            #print("bone name:",bone.name)
-            frame_count = len(scene_frames)
-            #print ('Frame Count: %i' % frame_count)
-            pose_data = arm.pose
-        
-            #these must be ordered in the order the bones will show up in the PSA file!
-            ordered_bones = {}
-            ordered_bones = sorted([(psa_file.UseBone(x.name), x) for x in pose_data.bones], key=operator.itemgetter(0))
-            
-            #############################
-            # ORDERED FRAME, BONE
-            #for frame in scene_frames:
-            
-            for i in range(frame_count):
-                frame = scene_frames[i]
-                #LOUD
-                #print ("==== outputting frame %i ===" % frame)
-                
-                if frame_count > i+1:
-                    next_frame = scene_frames[i+1]
-                    #print "This Frame: %i, Next Frame: %i" % (frame, next_frame)
-                else:
-                    next_frame = -1
-                    #print "This Frame: %i, Next Frame: NONE" % frame
-                
-                #frame start from 1 as number one from blender
-                blender_scene.frame_set(frame)
-                
-                cur_frame_index = cur_frame_index + 1
-                for bone_data in ordered_bones:
-                    bone_index = bone_data[0]
-                    pose_bone = bone_data[1]
-                    #print("[=====POSE NAME:",pose_bone.name)
-                    
-                    #print("LENG >>.",len(bones_lookup))
-                    blender_bone = bones_lookup[pose_bone.name]
-                    
-                    #just need the total unique bones used, later for this AnimInfoBinary
-                    unique_bone_indexes[bone_index] = bone_index
-                    #LOUD
-                    #print ("-------------------", pose_bone.name)
-                    head = pose_bone.head
-                    
-                    posebonemat = mathutils.Matrix(pose_bone.matrix)
-                    parent_pose = pose_bone.parent
-                    if parent_pose != None:
-                        parentposemat = mathutils.Matrix(parent_pose.matrix)
-                        #blender 2.4X it been flip around with new 2.50 (mat1 * mat2) should now be (mat2 * mat1)
-                        posebonemat = parentposemat.invert() * posebonemat
-                    head = posebonemat.translation_part()
-                    quat = posebonemat.to_quat().normalize()
-                    vkey = VQuatAnimKey()
-                    vkey.Position.X = head.x
-                    vkey.Position.Y = head.y
-                    vkey.Position.Z = head.z
-                    
-                    if parent_pose != None:
-                        quat = make_fquat(quat)
-                    else:
-                        quat = make_fquat_default(quat)
-                    
-                    vkey.Orientation = quat
-                    #print("Head:",head)
-                    #print("Orientation",quat)
-                    
-                    #time from now till next frame = diff / framesPerSec
-                    if next_frame >= 0:
-                        diff = next_frame - frame
-                    else:
-                        diff = 1.0
-                    
-                    #print ("Diff = ", diff)
-                    vkey.Time = float(diff)/float(anim_rate)
-                    
-                    psa_file.AddRawKey(vkey)
-                    
-            #done looping frames
-            #done looping armatures
-            #continue adding animInfoBinary counts here
-        
-            anim.TotalBones = len(unique_bone_indexes)
-            print("Bones Count:",anim.TotalBones)
-            anim.TrackTime = float(frame_count) / anim.AnimRate
-            print("Time Track Frame:",anim.TrackTime)
-            psa_file.AddAnimation(anim)
-            print("==== Finish Action Build(s) ====")
-        
+	#to do list:
+	#need to list the action sets
+	#need to check if there animation
+	#need to check if animation is has one frame then exit it
+	print ('\n----- parsing animation -----')
+	##print(dir(blender_scene))
+	
+	#print(dir(blender_armatures))
+	
+	render_data = blender_scene.render
+	bHaveAction = True
+	
+	anim_rate = render_data.fps
+	
+	print("==== Blender Settings ====")
+	print ('Scene: %s Start Frame: %i, End Frame: %i' % (blender_scene.name, blender_scene.frame_start, blender_scene.frame_end))
+	print ('Frames Per Sec: %i' % anim_rate)
+	print ("Default FPS: 24" )
+	
+	cur_frame_index = 0
+	
+	if bpy.context.scene.unrealactionexportall :#if exporting all actions is ture then go do some work.
+		print("Exporting all action:",bpy.context.scene.unrealactionexportall)
+		print("[==== Action list Start====]")
+		
+		actionlist = []
+		
+		print("Number of Action set(s):",len(bpy.data.actions))
+		
+		for action in bpy.data.actions:#current number action sets
+			print("========>>>>>")
+			print("Action Name:",action.name)
+			actionlist.append(action.name)
+			print("Groups:")
+			for bone in action.groups:
+				print("> Name: ",bone.name)
+				#print(dir(bone))
+			
+		print("[==== Action list End ====]")
+		
+		amatureobject = None #this is the armature set to none
+		bonenames = [] #bone name of the armature bones list
+		
+		for arm in blender_armatures:
+			amatureobject = arm
+			
+		print("\n[==== Armature Object ====]")
+		if amatureobject != None:
+			print("Name:",amatureobject.name)
+			print("Number of bones:", len(amatureobject.pose.bones))
+			for bone in amatureobject.pose.bones:
+				bonenames.append(bone.name)
+		print("[=========================]")
+		
+		for ActionNLA in bpy.data.actions:
+		
+			nobone = 0
+			baction = True
+			print("\nChecking actions matching groups with bone names...")
+			#Check if the bone names matches the action groups names
+			for group in ActionNLA.groups:
+				for abone in bonenames:
+					#print("name:>>",abone)
+					if abone == group.name:
+						nobone += 1
+						break
+			#if action groups matches the bones length and names matching the gourps do something
+			if (len(ActionNLA.groups) == len(bonenames)) and (nobone == len(ActionNLA.groups)):
+				print("Action Set found for this Armature Object: Action set Name: ",ActionNLA.name)
+				baction = True
+			else:
+				print("Action Set does not match for this Armature Object! , Action set Name: " ,ActionNLA.name)
+				baction = False
+			
+			if baction == True:
+				arm = amatureobject #set armature object
+				if not arm.animation_data:
+					print("======================================")
+					print("Check Animation Data: None")
+					print("Armature has no animation, skipping...")
+					print("======================================")
+					break
+					
+				if not arm.animation_data.action:
+					print("======================================")
+					print("Check Action: None")
+					print("Armature has no animation, skipping...")
+					print("======================================")
+					break
+				arm.animation_data.action = ActionNLA
+				act = arm.animation_data.action
+				action_name = act.name
+				
+				if not len(act.fcurves):
+					print("//===========================================================")
+					print("// None bone pose set keys for this action set... skipping...")
+					print("//===========================================================")
+					bHaveAction = False
+					
+				#this deal with action export control
+				if bHaveAction == True:
+					print("")
+					print("==== Action Set ====")
+					print("Action Name:",action_name)
+					#look for min and max frame that current set keys
+					framemin, framemax = act.frame_range
+					#print("max frame:",framemax)
+					start_frame = int(framemin)
+					end_frame = int(framemax)
+					scene_frames = range(start_frame, end_frame+1)
+					frame_count = len(scene_frames)
+					#===================================================
+					anim = AnimInfoBinary()
+					anim.Name = action_name
+					anim.Group = "" #what is group?
+					anim.NumRawFrames = frame_count
+					anim.AnimRate = anim_rate
+					anim.FirstRawFrame = cur_frame_index
+					#===================================================
+					count_previous_keys = len(psa_file.RawKeys.Data)
+					print("Frame Key Set Count:",frame_count, "Total Frame:",frame_count)
+					#print("init action bones...")
+					unique_bone_indexes = {}
+					# bone lookup table
+					bones_lookup =  {}
+				
+					#build bone node for animation keys needed to be set
+					for bone in arm.data.bones:
+						bones_lookup[bone.name] = bone
+					#print("bone name:",bone.name)
+					frame_count = len(scene_frames)
+					#print ('Frame Count: %i' % frame_count)
+					pose_data = arm.pose
+				
+					#these must be ordered in the order the bones will show up in the PSA file!
+					ordered_bones = {}
+					ordered_bones = sorted([(psa_file.UseBone(x.name), x) for x in pose_data.bones], key=operator.itemgetter(0))
+					
+					#############################
+					# ORDERED FRAME, BONE
+					#for frame in scene_frames:
+					
+					for i in range(frame_count):
+						frame = scene_frames[i]
+						#LOUD
+						#print ("==== outputting frame %i ===" % frame)
+						
+						if frame_count > i+1:
+							next_frame = scene_frames[i+1]
+							#print "This Frame: %i, Next Frame: %i" % (frame, next_frame)
+						else:
+							next_frame = -1
+							#print "This Frame: %i, Next Frame: NONE" % frame
+						
+						#frame start from 1 as number one from blender
+						blender_scene.frame_set(frame)
+						
+						cur_frame_index = cur_frame_index + 1
+						for bone_data in ordered_bones:
+							bone_index = bone_data[0]
+							pose_bone = bone_data[1]
+							#print("[=====POSE NAME:",pose_bone.name)
+							
+							#print("LENG >>.",len(bones_lookup))
+							blender_bone = bones_lookup[pose_bone.name]
+							
+							#just need the total unique bones used, later for this AnimInfoBinary
+							unique_bone_indexes[bone_index] = bone_index
+							#LOUD
+							#print ("-------------------", pose_bone.name)
+							head = pose_bone.head
+							
+							posebonemat = mathutils.Matrix(pose_bone.matrix)
+							parent_pose = pose_bone.parent
+							if parent_pose != None:
+								parentposemat = mathutils.Matrix(parent_pose.matrix)
+								#blender 2.4X it been flip around with new 2.50 (mat1 * mat2) should now be (mat2 * mat1)
+								posebonemat = parentposemat.invert() * posebonemat
+							head = posebonemat.translation_part()
+							quat = posebonemat.to_quat().normalize()
+							vkey = VQuatAnimKey()
+							vkey.Position.X = head.x
+							vkey.Position.Y = head.y
+							vkey.Position.Z = head.z
+							
+							if parent_pose != None:
+								quat = make_fquat(quat)
+							else:
+								quat = make_fquat_default(quat)
+							
+							vkey.Orientation = quat
+							#print("Head:",head)
+							#print("Orientation",quat)
+							
+							#time from now till next frame = diff / framesPerSec
+							if next_frame >= 0:
+								diff = next_frame - frame
+							else:
+								diff = 1.0
+							
+							#print ("Diff = ", diff)
+							vkey.Time = float(diff)/float(anim_rate)
+							
+							psa_file.AddRawKey(vkey)
+							
+					#done looping frames
+					#done looping armatures
+					#continue adding animInfoBinary counts here
+				
+					anim.TotalBones = len(unique_bone_indexes)
+					print("Bones Count:",anim.TotalBones)
+					anim.TrackTime = float(frame_count) / anim.AnimRate
+					print("Time Track Frame:",anim.TrackTime)
+					psa_file.AddAnimation(anim)
+		print("==== Finish Action Build(s) ====")
+	else:
+		print("Exporting one action:",bpy.context.scene.unrealactionexportall)
+		#list of armature objects
+		for arm in blender_armatures:
+			#check if there animation data from armature or something
+			
+			if not arm.animation_data:
+				print("======================================")
+				print("Check Animation Data: None")
+				print("Armature has no animation, skipping...")
+				print("======================================")
+				break
+				
+			if not arm.animation_data.action:
+				print("======================================")
+				print("Check Action: None")
+				print("Armature has no animation, skipping...")
+				print("======================================")
+				break
+			act = arm.animation_data.action
+			#print(dir(act))
+			action_name = act.name
+			
+			if not len(act.fcurves):
+				print("//===========================================================")
+				print("// None bone pose set keys for this action set... skipping...")
+				print("//===========================================================")
+				bHaveAction = False
+				
+			#this deal with action export control
+			if bHaveAction == True:
+				print("")
+				print("==== Action Set ====")
+				print("Action Name:",action_name)
+				#look for min and max frame that current set keys
+				framemin, framemax = act.frame_range
+				#print("max frame:",framemax)
+				start_frame = int(framemin)
+				end_frame = int(framemax)
+				scene_frames = range(start_frame, end_frame+1)
+				frame_count = len(scene_frames)
+				#===================================================
+				anim = AnimInfoBinary()
+				anim.Name = action_name
+				anim.Group = "" #what is group?
+				anim.NumRawFrames = frame_count
+				anim.AnimRate = anim_rate
+				anim.FirstRawFrame = cur_frame_index
+				#===================================================
+				count_previous_keys = len(psa_file.RawKeys.Data)
+				print("Frame Key Set Count:",frame_count, "Total Frame:",frame_count)
+				#print("init action bones...")
+				unique_bone_indexes = {}
+				# bone lookup table
+				bones_lookup =  {}
+			
+				#build bone node for animation keys needed to be set
+				for bone in arm.data.bones:
+					bones_lookup[bone.name] = bone
+				#print("bone name:",bone.name)
+				frame_count = len(scene_frames)
+				#print ('Frame Count: %i' % frame_count)
+				pose_data = arm.pose
+			
+				#these must be ordered in the order the bones will show up in the PSA file!
+				ordered_bones = {}
+				ordered_bones = sorted([(psa_file.UseBone(x.name), x) for x in pose_data.bones], key=operator.itemgetter(0))
+				
+				#############################
+				# ORDERED FRAME, BONE
+				#for frame in scene_frames:
+				
+				for i in range(frame_count):
+					frame = scene_frames[i]
+					#LOUD
+					#print ("==== outputting frame %i ===" % frame)
+					
+					if frame_count > i+1:
+						next_frame = scene_frames[i+1]
+						#print "This Frame: %i, Next Frame: %i" % (frame, next_frame)
+					else:
+						next_frame = -1
+						#print "This Frame: %i, Next Frame: NONE" % frame
+					
+					#frame start from 1 as number one from blender
+					blender_scene.frame_set(frame)
+					
+					cur_frame_index = cur_frame_index + 1
+					for bone_data in ordered_bones:
+						bone_index = bone_data[0]
+						pose_bone = bone_data[1]
+						#print("[=====POSE NAME:",pose_bone.name)
+						
+						#print("LENG >>.",len(bones_lookup))
+						blender_bone = bones_lookup[pose_bone.name]
+						
+						#just need the total unique bones used, later for this AnimInfoBinary
+						unique_bone_indexes[bone_index] = bone_index
+						#LOUD
+						#print ("-------------------", pose_bone.name)
+						head = pose_bone.head
+						
+						posebonemat = mathutils.Matrix(pose_bone.matrix)
+						parent_pose = pose_bone.parent
+						if parent_pose != None:
+							parentposemat = mathutils.Matrix(parent_pose.matrix)
+							#blender 2.4X it been flip around with new 2.50 (mat1 * mat2) should now be (mat2 * mat1)
+							posebonemat = parentposemat.invert() * posebonemat
+						head = posebonemat.translation_part()
+						quat = posebonemat.to_quat().normalize()
+						vkey = VQuatAnimKey()
+						vkey.Position.X = head.x
+						vkey.Position.Y = head.y
+						vkey.Position.Z = head.z
+						
+						if parent_pose != None:
+							quat = make_fquat(quat)
+						else:
+							quat = make_fquat_default(quat)
+						
+						vkey.Orientation = quat
+						#print("Head:",head)
+						#print("Orientation",quat)
+						
+						#time from now till next frame = diff / framesPerSec
+						if next_frame >= 0:
+							diff = next_frame - frame
+						else:
+							diff = 1.0
+						
+						#print ("Diff = ", diff)
+						vkey.Time = float(diff)/float(anim_rate)
+						
+						psa_file.AddRawKey(vkey)
+						
+				#done looping frames
+				#done looping armatures
+				#continue adding animInfoBinary counts here
+			
+				anim.TotalBones = len(unique_bone_indexes)
+				print("Bones Count:",anim.TotalBones)
+				anim.TrackTime = float(frame_count) / anim.AnimRate
+				print("Time Track Frame:",anim.TrackTime)
+				psa_file.AddAnimation(anim)
+				print("==== Finish Action Build(s) ====")
+	
 exportmessage = "Export Finish"        
-        
+		
 def fs_callback(filename, context, user_setting):
-    #this deal with repeat export and the reset settings
-    global bonedata, BBCount, nbone, exportmessage
-    bonedata = []#clear array
-    BBCount = 0
-    nbone = 0
-    
-    start_time = time.clock()
-    
-    print ("========EXPORTING TO UNREAL SKELETAL MESH FORMATS========\r\n")
-    print("Blender Version:", bpy.app.version_string)
-    
-    psk = PSKFile()
-    psa = PSAFile()
-    
-    #sanity check - this should already have the extension, but just in case, we'll give it one if it doesn't
-    psk_filename = make_filename_ext(filename, '.psk')
-    
-    #make the psa filename
-    psa_filename = make_filename_ext(filename, '.psa')
-    
-    print ('PSK File: ' +  psk_filename)
-    print ('PSA File: ' +  psa_filename)
-    
-    barmature = True
-    bmesh = True
-    blender_meshes = []
-    blender_armature = []
-    selectmesh = []
-    selectarmature = []
-    
-    current_scene = context.scene
-    cur_frame = current_scene.frame_current #store current frame before we start walking them during animation parse
-    objects = current_scene.objects
-    
-    print("Checking object count...")
-    for next_obj in objects:
-        if next_obj.type == 'MESH':
-            blender_meshes.append(next_obj)
-            if (next_obj.select):
-                #print("mesh object select")
-                selectmesh.append(next_obj)
-        if next_obj.type == 'ARMATURE':
-            blender_armature.append(next_obj)
-            if (next_obj.select):
-                #print("armature object select")
-                selectarmature.append(next_obj)
-    
-    print("Mesh Count:",len(blender_meshes)," Armature Count:",len(blender_armature))
-    print("====================================")
-    print("Checking Mesh Condtion(s):")
-    if len(blender_meshes) == 1:
-        print(" - One Mesh Scene")
-    elif (len(blender_meshes) > 1) and (len(selectmesh) == 1):
-        print(" - One Mesh [Select]")
-    else:
-        print(" - Too Many Meshes!")
-        print(" - Select One Mesh Object!")
-        bmesh = False
-    print("====================================")
-    print("Checking Armature Condtion(s):")
-    if len(blender_armature) == 1:
-        print(" - One Armature Scene")
-    elif (len(blender_armature) > 1) and (len(selectarmature) == 1):
-        print(" - One Armature [Select]")
-    else:
-        print(" - Too Armature Meshes!")
-        print(" - Select One Armature Object Only!")
-        barmature = False
-    
-    if     (bmesh == False) or (barmature == False):
-        exportmessage = "Export Fail! Check Log."
-        print("=================================")
-        print("= Export Fail!                  =")
-        print("=================================")
-    else:
-        exportmessage = "Export Finish!"
-        #need to build a temp bone index for mesh group vertex
-        BoneIndexArmature(blender_armature)
-
-        try:
-            #######################
-            # STEP 1: MESH DUMP
-            # we build the vertexes, wedges, and faces in here, as well as a vertexgroup lookup table
-            # for the armature parse
-            print("//===============================")
-            print("// STEP 1")
-            print("//===============================")
-            parse_meshes(blender_meshes, psk)
-        except:
-            context.scene.frame_set(cur_frame) #set frame back to original frame
-            print ("Exception during Mesh Parse")
-            raise
-        
-        try:
-            #######################
-            # STEP 2: ARMATURE DUMP
-            # IMPORTANT: do this AFTER parsing meshes - we need to use the vertex group data from 
-            # the mesh parse in here to generate bone influences
-            print("//===============================")
-            print("// STEP 2")
-            print("//===============================")
-            parse_armature(blender_armature, psk, psa) 
-            
-        except:
-            context.scene.frame_set(cur_frame) #set frame back to original frame
-            print ("Exception during Armature Parse")
-            raise
-
-        try:
-            #######################
-            # STEP 3: ANIMATION DUMP
-            # IMPORTANT: do AFTER parsing bones - we need to do bone lookups in here during animation frames
-            print("//===============================")
-            print("// STEP 3")
-            print("//===============================")
-            parse_animation(current_scene, blender_armature, psa) 
-            
-        except:
-            context.scene.frame_set(cur_frame) #set frame back to original frame
-            print ("Exception during Animation Parse")
-            raise
-
-        # reset current frame
-        
-        context.scene.frame_set(cur_frame) #set frame back to original frame
-        
-        ##########################
-        # FILE WRITE
-        print("//===========================================")
-        print("// bExportPsk:",bpy.context.scene.unrealexportpsk," bExportPsa:",bpy.context.scene.unrealexportpsa)
-        print("//===========================================")
-        if bpy.context.scene.unrealexportpsk == True:
-            print("Writing Skeleton Mesh Data...")
-            #RG - dump psk file
-            psk.PrintOut()
-            file = open(psk_filename, "wb") 
-            file.write(psk.dump())
-            file.close() 
-            print ("Successfully Exported File: " + psk_filename)
-        if bpy.context.scene.unrealexportpsa == True:
-            print("Writing Animaiton Data...")
-            #RG - dump psa file
-            if not psa.IsEmpty():
-                psa.PrintOut()
-                file = open(psa_filename, "wb") 
-                file.write(psa.dump())
-                file.close() 
-                print ("Successfully Exported File: " + psa_filename)
-            else:
-                print ("No Animations (.psa file) to Export")
-
-        print ('PSK/PSA Export Script finished in %.2f seconds' % (time.clock() - start_time))
-        
-        #MSG BOX EXPORT COMPLETE
-        #...
-
-        #DONE
-        print ("PSK/PSA Export Complete")
+	#this deal with repeat export and the reset settings
+	global bonedata, BBCount, nbone, exportmessage
+	bonedata = []#clear array
+	BBCount = 0
+	nbone = 0
+	
+	start_time = time.clock()
+	
+	print ("========EXPORTING TO UNREAL SKELETAL MESH FORMATS========\r\n")
+	print("Blender Version:", bpy.app.version_string)
+	
+	psk = PSKFile()
+	psa = PSAFile()
+	
+	#sanity check - this should already have the extension, but just in case, we'll give it one if it doesn't
+	psk_filename = make_filename_ext(filename, '.psk')
+	
+	#make the psa filename
+	psa_filename = make_filename_ext(filename, '.psa')
+	
+	print ('PSK File: ' +  psk_filename)
+	print ('PSA File: ' +  psa_filename)
+	
+	barmature = True
+	bmesh = True
+	blender_meshes = []
+	blender_armature = []
+	selectmesh = []
+	selectarmature = []
+	
+	current_scene = context.scene
+	cur_frame = current_scene.frame_current #store current frame before we start walking them during animation parse
+	objects = current_scene.objects
+	
+	print("Checking object count...")
+	for next_obj in objects:
+		if next_obj.type == 'MESH':
+			blender_meshes.append(next_obj)
+			if (next_obj.select):
+				#print("mesh object select")
+				selectmesh.append(next_obj)
+		if next_obj.type == 'ARMATURE':
+			blender_armature.append(next_obj)
+			if (next_obj.select):
+				#print("armature object select")
+				selectarmature.append(next_obj)
+	
+	print("Mesh Count:",len(blender_meshes)," Armature Count:",len(blender_armature))
+	print("====================================")
+	print("Checking Mesh Condtion(s):")
+	if len(blender_meshes) == 1:
+		print(" - One Mesh Scene")
+	elif (len(blender_meshes) > 1) and (len(selectmesh) == 1):
+		print(" - One Mesh [Select]")
+	else:
+		print(" - Too Many Meshes!")
+		print(" - Select One Mesh Object!")
+		bmesh = False
+	print("====================================")
+	print("Checking Armature Condtion(s):")
+	if len(blender_armature) == 1:
+		print(" - One Armature Scene")
+	elif (len(blender_armature) > 1) and (len(selectarmature) == 1):
+		print(" - One Armature [Select]")
+	else:
+		print(" - Too Armature Meshes!")
+		print(" - Select One Armature Object Only!")
+		barmature = False
+	
+	if     (bmesh == False) or (barmature == False):
+		exportmessage = "Export Fail! Check Log."
+		print("=================================")
+		print("= Export Fail!                  =")
+		print("=================================")
+	else:
+		exportmessage = "Export Finish!"
+		#need to build a temp bone index for mesh group vertex
+		BoneIndexArmature(blender_armature)
+
+		try:
+			#######################
+			# STEP 1: MESH DUMP
+			# we build the vertexes, wedges, and faces in here, as well as a vertexgroup lookup table
+			# for the armature parse
+			print("//===============================")
+			print("// STEP 1")
+			print("//===============================")
+			parse_meshes(blender_meshes, psk)
+		except:
+			context.scene.frame_set(cur_frame) #set frame back to original frame
+			print ("Exception during Mesh Parse")
+			raise
+		
+		try:
+			#######################
+			# STEP 2: ARMATURE DUMP
+			# IMPORTANT: do this AFTER parsing meshes - we need to use the vertex group data from 
+			# the mesh parse in here to generate bone influences
+			print("//===============================")
+			print("// STEP 2")
+			print("//===============================")
+			parse_armature(blender_armature, psk, psa) 
+			
+		except:
+			context.scene.frame_set(cur_frame) #set frame back to original frame
+			print ("Exception during Armature Parse")
+			raise
+
+		try:
+			#######################
+			# STEP 3: ANIMATION DUMP
+			# IMPORTANT: do AFTER parsing bones - we need to do bone lookups in here during animation frames
+			print("//===============================")
+			print("// STEP 3")
+			print("//===============================")
+			parse_animation(current_scene, blender_armature, psa) 
+			
+		except:
+			context.scene.frame_set(cur_frame) #set frame back to original frame
+			print ("Exception during Animation Parse")
+			raise
+
+		# reset current frame
+		
+		context.scene.frame_set(cur_frame) #set frame back to original frame
+		
+		##########################
+		# FILE WRITE
+		print("//===========================================")
+		print("// bExportPsk:",bpy.context.scene.unrealexportpsk," bExportPsa:",bpy.context.scene.unrealexportpsa)
+		print("//===========================================")
+		if bpy.context.scene.unrealexportpsk == True:
+			print("Writing Skeleton Mesh Data...")
+			#RG - dump psk file
+			psk.PrintOut()
+			file = open(psk_filename, "wb") 
+			file.write(psk.dump())
+			file.close() 
+			print ("Successfully Exported File: " + psk_filename)
+		if bpy.context.scene.unrealexportpsa == True:
+			print("Writing Animaiton Data...")
+			#RG - dump psa file
+			if not psa.IsEmpty():
+				psa.PrintOut()
+				file = open(psa_filename, "wb") 
+				file.write(psa.dump())
+				file.close() 
+				print ("Successfully Exported File: " + psa_filename)
+			else:
+				print ("No Animations (.psa file) to Export")
+
+		print ('PSK/PSA Export Script finished in %.2f seconds' % (time.clock() - start_time))
+		print( "Current Script version: ",bl_addon_info['version'])
+		#MSG BOX EXPORT COMPLETE
+		#...
+
+		#DONE
+		print ("PSK/PSA Export Complete")
 
 def write_data(path, context, user_setting):
-    print("//============================")
-    print("// running psk/psa export...")
-    print("//============================")
-    fs_callback(path, context, user_setting)
-    pass
+	print("//============================")
+	print("// running psk/psa export...")
+	print("//============================")
+	fs_callback(path, context, user_setting)
+	pass
 
 from bpy.props import *
 
@@ -1433,161 +1620,159 @@ exporttypedata.append(("1","PSA","Export PSA"))
 exporttypedata.append(("2","ALL","Export ALL"))
 
 bpy.types.Scene.unrealfpsrate = IntProperty(
-    name="fps rate",
-    description="Set the frame per second (fps) for unreal.",
-    default=24,min=1,max=100)
-    
+	name="fps rate",
+	description="Set the frame per second (fps) for unreal.",
+	default=24,min=1,max=100)
+	
 bpy.types.Scene.unrealexport_settings = EnumProperty(
-    name="Export:",
-    description="Select a export settings (psk/psa/all)...",
-    items = exporttypedata, default = '0')
-        
+	name="Export:",
+	description="Select a export settings (psk/psa/all)...",
+	items = exporttypedata, default = '0')
+		
 bpy.types.Scene.unrealtriangulatebool = BoolProperty(
-    name="Triangulate Mesh",
-    description="Convert Quad to Tri Mesh Boolean...",
-    default=False)
-    
+	name="Triangulate Mesh",
+	description="Convert Quad to Tri Mesh Boolean...",
+	default=False)
+	
 bpy.types.Scene.unrealactionexportall = BoolProperty(
-    name="All Actions",
-    description="This let you export all actions from current armature.[Not Build Yet]",
-    default=False)    
-    
+	name="All Actions",
+	description="This let you export all the actions from current armature that matches bone name in action groups names.",
+	default=False)    
+	
 bpy.types.Scene.unrealexportpsk = BoolProperty(
-    name="bool export psa",
-    description="bool for exporting this psk format",
-    default=False)
-    
+	name="bool export psa",
+	description="bool for exporting this psk format",
+	default=False)
+	
 bpy.types.Scene.unrealexportpsa = BoolProperty(
-    name="bool export psa",
-    description="bool for exporting this psa format",
-    default=False)
+	name="bool export psa",
+	description="bool for exporting this psa format",
+	default=False)
 
 class ExportUDKAnimData(bpy.types.Operator):
-    global exportmessage
-    '''Export Skeleton Mesh / Animation Data file(s)'''
-    bl_idname = "export.udk_anim_data" # this is important since its how bpy.ops.export.udk_anim_data is constructed
-    bl_label = "Export PSK/PSA"
-    __doc__ = "One mesh and one armature else select one mesh or armature to be exported."
-
-    # List of operator properties, the attributes will be assigned
-    # to the class instance from the operator settings before calling.
-
-    filepath = StringProperty(name="File Path", description="Filepath used for exporting the PSA file", maxlen= 1024, default= "")
-    use_setting = BoolProperty(name="No Options Yet", description="No Options Yet", default= True)
-    pskexportbool = BoolProperty(name="Export PSK", description="Export Skeletal Mesh", default= True)
-    psaexportbool = BoolProperty(name="Export PSA", description="Export Action Set (Animation Data)", default= True)
-    actionexportall = BoolProperty(name="All Actions", description="This will export all the actions that matches the current armature.", default=False)
-
-    @classmethod
-    def poll(cls, context):
-        return context.active_object != None
-
-    def execute(self, context):
-        #check if  skeleton mesh is needed to be exported
-        if (self.pskexportbool):
-            bpy.context.scene.unrealexportpsk = True
-        else:
-            bpy.context.scene.unrealexportpsk = False
-        #check if  animation data is needed to be exported
-        if (self.psaexportbool):
-            bpy.context.scene.unrealexportpsa = True
-        else:
-            bpy.context.scene.unrealexportpsa = False
-            
-        write_data(self.filepath, context, self.use_setting)
-        
-        self.report({'WARNING', 'INFO'}, exportmessage)
-        return {'FINISHED'}
-        
-    def invoke(self, context, event):
-        wm = context.window_manager
-        wm.add_fileselect(self)
-        return {'RUNNING_MODAL'}
+	global exportmessage
+	'''Export Skeleton Mesh / Animation Data file(s)'''
+	bl_idname = "export.udk_anim_data" # this is important since its how bpy.ops.export.udk_anim_data is constructed
+	bl_label = "Export PSK/PSA"
+	__doc__ = "One mesh and one armature else select one mesh or armature to be exported."
+
+	# List of operator properties, the attributes will be assigned
+	# to the class instance from the operator settings before calling.
+
+	filepath = StringProperty(name="File Path", description="Filepath used for exporting the PSA file", maxlen= 1024, default= "")
+	use_setting = BoolProperty(name="No Options Yet", description="No Options Yet", default= True)
+	pskexportbool = BoolProperty(name="Export PSK", description="Export Skeletal Mesh", default= True)
+	psaexportbool = BoolProperty(name="Export PSA", description="Export Action Set (Animation Data)", default= True)
+	actionexportall = BoolProperty(name="All Actions", description="This will export all the actions that matches the current armature.", default=False)
+
+	@classmethod
+	def poll(cls, context):
+		return context.active_object != None
+
+	def execute(self, context):
+		#check if  skeleton mesh is needed to be exported
+		if (self.pskexportbool):
+			bpy.context.scene.unrealexportpsk = True
+		else:
+			bpy.context.scene.unrealexportpsk = False
+		#check if  animation data is needed to be exported
+		if (self.psaexportbool):
+			bpy.context.scene.unrealexportpsa = True
+		else:
+			bpy.context.scene.unrealexportpsa = False
+			
+		write_data(self.filepath, context, self.use_setting)
+		
+		self.report({'WARNING', 'INFO'}, exportmessage)
+		return {'FINISHED'}
+		
+	def invoke(self, context, event):
+		wm = context.window_manager
+		wm.add_fileselect(self)
+		return {'RUNNING_MODAL'}
 
 
 class VIEW3D_PT_unrealtools_objectmode(bpy.types.Panel):
-    bl_space_type = "VIEW_3D"
-    bl_region_type = "TOOLS"
-    bl_label = "Unreal Tools"
-    
-    @classmethod
-    def poll(cls, context):
-        return context.active_object
-
-    def draw(self, context):
-        layout = self.layout
-        #layout.label(text="Unreal Tools")
-        rd = context.scene
-        #drop box
-        layout.prop(rd, "unrealexport_settings",expand=True)
-        #layout.prop(rd, "unrealexport_settings")
-        #button
-        layout.operator("object.UnrealExport")
-        #FPS #it use the real data from your scene
-        layout.prop(rd.render, "fps")
-        
-        layout.prop(rd, "unrealactionexportall")
-        #row = layout.row()
-        #row.label(text="Action Set(s)(not build)")
-        #for action in  bpy.data.actions:
-            #print(dir( action))
-            #print(action.frame_range)
-            #row = layout.row()
-            #row.prop(action, "name")
-            
-            #print(dir(action.groups[0]))
-            #for g in action.groups:#those are bones
-                #print("group...")
-                #print(dir(g))
-                #print("////////////")
-                #print((g.name))
-                #print("////////////")
-            
-            #row.label(text="Active:" + action.select)
-        btrimesh = False
-        
+	bl_space_type = "VIEW_3D"
+	bl_region_type = "TOOLS"
+	bl_label = "Unreal Tools"
+	
+	@classmethod
+	def poll(cls, context):
+		return context.active_object
+
+	def draw(self, context):
+		layout = self.layout
+		#layout.label(text="Unreal Tools")
+		rd = context.scene
+		#drop box
+		layout.prop(rd, "unrealexport_settings",expand=True)
+		#layout.prop(rd, "unrealexport_settings")
+		#button
+		layout.operator("object.UnrealExport")
+		#FPS #it use the real data from your scene
+		layout.prop(rd.render, "fps")
+		
+		layout.prop(rd, "unrealactionexportall")
+		#row = layout.row()
+		#row.label(text="Action Set(s)(not build)")
+		#for action in  bpy.data.actions:
+			#print(dir( action))
+			#print(action.frame_range)
+			#row = layout.row()
+			#row.prop(action, "name")
+			
+			#print(dir(action.groups[0]))
+			#for g in action.groups:#those are bones
+				#print("group...")
+				#print(dir(g))
+				#print("////////////")
+				#print((g.name))
+				#print("////////////")
+			
+			#row.label(text="Active:" + action.select)
+		btrimesh = False
+		
 class OBJECT_OT_UnrealExport(bpy.types.Operator):
-    global exportmessage
-    bl_idname = "OBJECT_OT_UnrealExport"
-    bl_label = "Unreal Export"
-    __doc__ = "Select export setting for .psk/.psa or both."
-    
-    def invoke(self, context, event):
-        #path = StringProperty(name="File Path", description="File path used for exporting the PSA file", maxlen= 1024, default= "")
-        print("Init Export Script:")
-        if(int(bpy.context.scene.unrealexport_settings) == 0):
-            bpy.context.scene.unrealexportpsk = True
-            bpy.context.scene.unrealexportpsa = False
-            print("Exporting PSK...")
-        if(int(bpy.context.scene.unrealexport_settings) == 1):
-            bpy.context.scene.unrealexportpsk = False
-            bpy.context.scene.unrealexportpsa = True
-            print("Exporting PSA...")
-        if(int(bpy.context.scene.unrealexport_settings) == 2):
-            bpy.context.scene.unrealexportpsk = True
-            bpy.context.scene.unrealexportpsa = True
-            print("Exporting ALL...")
-
-        default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
-        fs_callback(default_path, bpy.context, False)
-        
-        #self.report({'WARNING', 'INFO'}, exportmessage)
-        self.report({'INFO'}, exportmessage)
-        return{'FINISHED'}    
-
+	global exportmessage
+	bl_idname = "OBJECT_OT_UnrealExport"
+	bl_label = "Unreal Export"
+	__doc__ = "Select export setting for .psk/.psa or both."
+	
+	def invoke(self, context, event):
+		#path = StringProperty(name="File Path", description="File path used for exporting the PSA file", maxlen= 1024, default= "")
+		print("Init Export Script:")
+		if(int(bpy.context.scene.unrealexport_settings) == 0):
+			bpy.context.scene.unrealexportpsk = True
+			bpy.context.scene.unrealexportpsa = False
+			print("Exporting PSK...")
+		if(int(bpy.context.scene.unrealexport_settings) == 1):
+			bpy.context.scene.unrealexportpsk = False
+			bpy.context.scene.unrealexportpsa = True
+			print("Exporting PSA...")
+		if(int(bpy.context.scene.unrealexport_settings) == 2):
+			bpy.context.scene.unrealexportpsk = True
+			bpy.context.scene.unrealexportpsa = True
+			print("Exporting ALL...")
+
+		default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
+		fs_callback(default_path, bpy.context, False)
+		
+		#self.report({'WARNING', 'INFO'}, exportmessage)
+		self.report({'INFO'}, exportmessage)
+		return{'FINISHED'}    
 
 def menu_func(self, context):
-    bpy.context.scene.unrealexportpsk = True
-    bpy.context.scene.unrealexportpsa = True
-    default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
-    self.layout.operator("export.udk_anim_data", text="Skeleton Mesh / Animation Data (.psk/.psa)").filepath = default_path
-
+	bpy.context.scene.unrealexportpsk = True
+	bpy.context.scene.unrealexportpsa = True
+	default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
+	self.layout.operator("export.udk_anim_data", text="Skeleton Mesh / Animation Data (.psk/.psa)").filepath = default_path
 
 def register():
-    bpy.types.INFO_MT_file_export.append(menu_func)
+	bpy.types.INFO_MT_file_export.append(menu_func)
 
 def unregister():
-    bpy.types.INFO_MT_file_export.remove(menu_func)
+	bpy.types.INFO_MT_file_export.remove(menu_func)
 
 if __name__ == "__main__":
-    register()
+	register()