diff --git a/io_import_scene_mhx.py b/io_import_scene_mhx.py
index 982df04a990953054a862ff18da038e177ceb316..5b3aeab4440b848242b4eafd15bf58b23c996e29 100644
--- a/io_import_scene_mhx.py
+++ b/io_import_scene_mhx.py
@@ -1,36 +1,38 @@
 """ 
-**Project Name:**	  MakeHuman
+**Project Name:**      MakeHuman
 
 **Product Home Page:** http://www.makehuman.org/
 
-**Code Home Page:**	http://code.google.com/p/makehuman/
+**Code Home Page:**    http://code.google.com/p/makehuman/
 
-**Authors:**		   Thomas Larsson
+**Authors:**           Thomas Larsson
 
-**Copyright(c):**	  MakeHuman Team 2001-2010
+**Copyright(c):**      MakeHuman Team 2001-2010
 
-**Licensing:**		 GPL3 (see also http://sites.google.com/site/makehumandocs/licensing)
+**Licensing:**         GPL3 (see also http://sites.google.com/site/makehumandocs/licensing)
 
 **Coding Standards:**  See http://sites.google.com/site/makehumandocs/developers-guide
 
 Abstract
 MHX (MakeHuman eXchange format) importer for Blender 2.5x.
-Version 1.0
+Version 1.0.3
 
 """
 
 bl_addon_info = {
-	'name': 'Import: MakeHuman (.mhx)',
-	'author': 'Thomas Larsson',
-	'version': '1.0',
-	'blender': (2, 5, 4),
-    "api": 31913,
-	"location": "File > Import",
-	"description": "Import files in the MakeHuman eXchange format (.mhx)",
-	"warning": "",
-	"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/File_I-O/Make_Human",
-	"tracker_url": "https://projects.blender.org/tracker/index.php?func=detail&aid=21872&group_id=153&atid=469",
-	"category": "Import/Export"}
+    'name': 'Import: MakeHuman (.mhx)',
+    'author': 'Thomas Larsson',
+    'version': (1, 0, 3),
+    'blender': (2, 5, 5),
+    'api': 33590,
+    'location': "File > Import",
+    'description': 'Import files in the MakeHuman eXchange format (.mhx)',
+    'warning': '',
+    'wiki_url': 'http://wiki.blender.org/index.php/Extensions:2.5/Py/'\
+        'Scripts/File_I-O/Make_Human',
+    'tracker_url': 'https://projects.blender.org/tracker/index.php?'\
+        'func=detail&aid=21872&group_id=153&atid=469',
+    'category': 'Import/Export'}
 
 """
 Place this file in the .blender/scripts/addons dir
@@ -40,7 +42,8 @@ Access from the File > Import menu.
 
 MAJOR_VERSION = 1
 MINOR_VERSION = 0
-BLENDER_VERSION = (2, 54, 0)
+SUB_VERSION = 3
+BLENDER_VERSION = (2, 55, 1)
 
 #
 #
@@ -51,7 +54,8 @@ import os
 import time
 import mathutils
 from mathutils import *
-import string
+#import geometry
+#import string
 
 MHX249 = False
 Blender24 = False
@@ -78,7 +82,7 @@ theTempDatum = None
 todo = []
 
 #
-#	toggle flags
+#    toggle flags
 #
 
 T_EnforceVersion = 0x01
@@ -104,14 +108,14 @@ T_MHX = 0x8000
 toggle = T_EnforceVersion + T_Replace + T_Mesh + T_Armature + T_Face + T_Shape + T_Proxy + T_Clothes
 
 #
-#	setFlagsAndFloats(rigFlags):
+#    setFlagsAndFloats(rigFlags):
 #
-#	Global floats
+#    Global floats
 #fFingerPanel = 0.0
 #fFingerIK = 0.0
 fNoStretch = 0.0
 
-#	rigLeg and rigArm flags
+#    rigLeg and rigArm flags
 T_Toes = 0x0001
 #T_GoboFoot = 0x0002
 
@@ -130,251 +134,251 @@ T_Toes = 0x0001
 #rigArm = 0
 
 def setFlagsAndFloats():
-	'''
-	global toggle, rigLeg, rigArm
+    '''
+    global toggle, rigLeg, rigArm
 
-	(footRig, fingerRig) = rigFlags
-	rigLeg = 0
-	if footRig == 'Reverse foot': 
-		rigLeg |= T_InvFoot
-		if toggle & T_PoleTar:
-			rigLeg |= T_InvFootPT
-		else:
-			rigLeg |= T_InvFootNoPT
-	elif footRig == 'Gobo': rigLeg |= T_GoboFoot		
+    (footRig, fingerRig) = rigFlags
+    rigLeg = 0
+    if footRig == 'Reverse foot': 
+        rigLeg |= T_InvFoot
+        if toggle & T_PoleTar:
+            rigLeg |= T_InvFootPT
+        else:
+            rigLeg |= T_InvFootNoPT
+    elif footRig == 'Gobo': rigLeg |= T_GoboFoot        
 
-	rigArm = 0
-	if fingerRig == 'Panel': rigArm |= T_FingerPanel
-	elif fingerRig == 'Rotation': rigArm |= T_FingerRot
-	elif fingerRig == 'IK': rigArm |= T_FingerIK
+    rigArm = 0
+    if fingerRig == 'Panel': rigArm |= T_FingerPanel
+    elif fingerRig == 'Rotation': rigArm |= T_FingerRot
+    elif fingerRig == 'IK': rigArm |= T_FingerIK
 
-	toggle |= T_Panel
-	'''
-	global fNoStretch
-	if toggle&T_Stretch: fNoStretch == 0.0
-	else: fNoStretch = 1.0
+    toggle |= T_Panel
+    '''
+    global fNoStretch
+    if toggle&T_Stretch: fNoStretch == 0.0
+    else: fNoStretch = 1.0
 
-	return
+    return
 
 
 #
-#	Dictionaries
+#    Dictionaries
 #
 
 loadedData = {
-	'NONE' : {},
-
-	'Object' : {},
-	'Mesh' : {},
-	'Armature' : {},
-	'Lamp' : {},
-	'Camera' : {},
-	'Lattice' : {},
-	'Curve' : {},
-	'Text' : {},
-
-	'Material' : {},
-	'Image' : {},
-	'MaterialTextureSlot' : {},
-	'Texture' : {},
-	
-	'Bone' : {},
-	'BoneGroup' : {},
-	'Rigify' : {},
-
-	'Action' : {},
-	'Group' : {},
-
-	'MeshTextureFaceLayer' : {},
-	'MeshColorLayer' : {},
-	'VertexGroup' : {},
-	'ShapeKey' : {},
-	'ParticleSystem' : {},
-
-	'ObjectConstraints' : {},
-	'ObjectModifiers' : {},
-	'MaterialSlot' : {},
+    'NONE' : {},
+
+    'Object' : {},
+    'Mesh' : {},
+    'Armature' : {},
+    'Lamp' : {},
+    'Camera' : {},
+    'Lattice' : {},
+    'Curve' : {},
+    'Text' : {},
+
+    'Material' : {},
+    'Image' : {},
+    'MaterialTextureSlot' : {},
+    'Texture' : {},
+    
+    'Bone' : {},
+    'BoneGroup' : {},
+    'Rigify' : {},
+
+    'Action' : {},
+    'Group' : {},
+
+    'MeshTextureFaceLayer' : {},
+    'MeshColorLayer' : {},
+    'VertexGroup' : {},
+    'ShapeKey' : {},
+    'ParticleSystem' : {},
+
+    'ObjectConstraints' : {},
+    'ObjectModifiers' : {},
+    'MaterialSlot' : {},
 }
 
 Plural = {
-	'Object' : 'objects',
-	'Mesh' : 'meshes',
-	'Lattice' : 'lattices',
-	'Curve' : 'curves',
-	'Text' : 'texts',
-	'Group' : 'groups',
-	'Empty' : 'empties',
-	'Armature' : 'armatures',
-	'Bone' : 'bones',
-	'BoneGroup' : 'bone_groups',
-	'Pose' : 'poses',
-	'PoseBone' : 'pose_bones',
-	'Material' : 'materials',
-	'Texture' : 'textures',
-	'Image' : 'images',
-	'Camera' : 'cameras',
-	'Lamp' : 'lamps',
-	'World' : 'worlds',
+    'Object' : 'objects',
+    'Mesh' : 'meshes',
+    'Lattice' : 'lattices',
+    'Curve' : 'curves',
+    'Text' : 'texts',
+    'Group' : 'groups',
+    'Empty' : 'empties',
+    'Armature' : 'armatures',
+    'Bone' : 'bones',
+    'BoneGroup' : 'bone_groups',
+    'Pose' : 'poses',
+    'PoseBone' : 'pose_bones',
+    'Material' : 'materials',
+    'Texture' : 'textures',
+    'Image' : 'images',
+    'Camera' : 'cameras',
+    'Lamp' : 'lamps',
+    'World' : 'worlds',
 }
 
 #
-#	checkBlenderVersion()
+#    checkBlenderVersion()
 #
 
 def checkBlenderVersion():
-	print("Found Blender", bpy.app.version)
-	(A, B, C) = bpy.app.version
-	(a, b, c) = BLENDER_VERSION
-	if a <= A: return
-	if b <= B: return
-	if c <= C: return
-	msg = (
+    print("Found Blender", bpy.app.version)
+    (A, B, C) = bpy.app.version
+    (a, b, c) = BLENDER_VERSION
+    if a <= A: return
+    if b <= B: return
+    if c <= C: return
+    msg = (
 "This version of the MHX importer only works with Blender (%d, %d, %d) or later. " % (a, b, c) +
 "Download a more recent Blender from www.blender.org or www.graphicall.org.\n"
-	)
-	raise NameError(msg)
-	return
+    )
+    raise NameError(msg)
+    return
 
 #
-#	readMhxFile(filePath, scale):
+#    readMhxFile(filePath, scale):
 #
 
 def readMhxFile(filePath, scale):
-	global todo, nErrors, theScale, defaultScale, One, toggle
-
-	checkBlenderVersion()	
-	
-	theScale = scale
-	defaultScale = scale
-	One = 1.0/theScale
-
-	fileName = os.path.expanduser(filePath)
-	(shortName, ext) = os.path.splitext(fileName)
-	if ext.lower() != ".mhx":
-		print("Error: Not a mhx file: " + fileName)
-		return
-	print( "Opening MHX file "+ fileName )
-	time1 = time.clock()
-
-	ignore = False
-	stack = []
-	tokens = []
-	key = "toplevel"
-	level = 0
-	nErrors = 0
-	comment = 0
-	nesting = 0
-
-	setFlagsAndFloats()
-
-	file= open(fileName, "rU")
-	print( "Tokenizing" )
-	lineNo = 0
-	for line in file: 
-		# print(line)
-		lineSplit= line.split()
-		lineNo += 1
-		if len(lineSplit) == 0:
-			pass
-		elif lineSplit[0][0] == '#':
-			if lineSplit[0] == '#if':
-				if comment == nesting:
-					try:
-						res = eval(lineSplit[1])
-					except:
-						res = False
-					if res:
-						comment += 1
-				nesting += 1
-			elif lineSplit[0] == '#else':
-				if comment == nesting-1:
-					comment += 1
-				elif comment == nesting:
-					comment -= 1
-			elif lineSplit[0] == '#endif':
-				if comment == nesting:
-					comment -= 1
-				nesting -= 1
-		elif comment < nesting:
-			pass
-		elif lineSplit[0] == 'end':
-			try:
-				sub = tokens
-				tokens = stack.pop()
-				if tokens:
-					tokens[-1][2] = sub
-				level -= 1
-			except:
-				print( "Tokenizer error at or before line %d" % lineNo )
-				print( line )
-				dummy = stack.pop()
-		elif lineSplit[-1] == ';':
-			if lineSplit[0] == '\\':
-				key = lineSplit[1]
-				tokens.append([key,lineSplit[2:-1],[]])
-			else:
-				key = lineSplit[0]
-				tokens.append([key,lineSplit[1:-1],[]])
-		else:
-			key = lineSplit[0]
-			tokens.append([key,lineSplit[1:],[]])
-			stack.append(tokens)
-			level += 1
-			tokens = []
-	file.close()
-
-	if level != 0:
-		raise NameError("Tokenizer out of kilter %d" % level)	
-	clearScene()
-	print( "Parsing" )
-	parse(tokens)
-	
-	for (expr, glbals, lcals) in todo:
-		try:
-			print("Doing %s" % expr)
-			exec(expr, glbals, lcals)
-		except:
-			msg = "Failed: "+expr
-			print( msg )
-			nErrors += 1
-			#raise NameError(msg)
-
-	print("Postprocess")
-	postProcess()
-	print("HideLayers")
-	hideLayers()
-	time2 = time.clock()
-	print("toggle = %x" % toggle)
-	msg = "File %s loaded in %g s" % (fileName, time2-time1)
-	if nErrors:
-		msg += " but there where %d errors. " % (nErrors)
-	print(msg)
-	return
-
-#
-#	getObject(name, var, glbals, lcals):
+    global todo, nErrors, theScale, defaultScale, One, toggle
+
+    checkBlenderVersion()    
+    
+    theScale = scale
+    defaultScale = scale
+    One = 1.0/theScale
+
+    fileName = os.path.expanduser(filePath)
+    (shortName, ext) = os.path.splitext(fileName)
+    if ext.lower() != ".mhx":
+        print("Error: Not a mhx file: " + fileName)
+        return
+    print( "Opening MHX file "+ fileName )
+    time1 = time.clock()
+
+    ignore = False
+    stack = []
+    tokens = []
+    key = "toplevel"
+    level = 0
+    nErrors = 0
+    comment = 0
+    nesting = 0
+
+    setFlagsAndFloats()
+
+    file= open(fileName, "rU")
+    print( "Tokenizing" )
+    lineNo = 0
+    for line in file: 
+        # print(line)
+        lineSplit= line.split()
+        lineNo += 1
+        if len(lineSplit) == 0:
+            pass
+        elif lineSplit[0][0] == '#':
+            if lineSplit[0] == '#if':
+                if comment == nesting:
+                    try:
+                        res = eval(lineSplit[1])
+                    except:
+                        res = False
+                    if res:
+                        comment += 1
+                nesting += 1
+            elif lineSplit[0] == '#else':
+                if comment == nesting-1:
+                    comment += 1
+                elif comment == nesting:
+                    comment -= 1
+            elif lineSplit[0] == '#endif':
+                if comment == nesting:
+                    comment -= 1
+                nesting -= 1
+        elif comment < nesting:
+            pass
+        elif lineSplit[0] == 'end':
+            try:
+                sub = tokens
+                tokens = stack.pop()
+                if tokens:
+                    tokens[-1][2] = sub
+                level -= 1
+            except:
+                print( "Tokenizer error at or before line %d" % lineNo )
+                print( line )
+                dummy = stack.pop()
+        elif lineSplit[-1] == ';':
+            if lineSplit[0] == '\\':
+                key = lineSplit[1]
+                tokens.append([key,lineSplit[2:-1],[]])
+            else:
+                key = lineSplit[0]
+                tokens.append([key,lineSplit[1:-1],[]])
+        else:
+            key = lineSplit[0]
+            tokens.append([key,lineSplit[1:],[]])
+            stack.append(tokens)
+            level += 1
+            tokens = []
+    file.close()
+
+    if level != 0:
+        raise NameError("Tokenizer out of kilter %d" % level)    
+    clearScene()
+    print( "Parsing" )
+    parse(tokens)
+    
+    for (expr, glbals, lcals) in todo:
+        try:
+            print("Doing %s" % expr)
+            exec(expr, glbals, lcals)
+        except:
+            msg = "Failed: "+expr
+            print( msg )
+            nErrors += 1
+            #raise NameError(msg)
+
+    print("Postprocess")
+    postProcess()
+    print("HideLayers")
+    hideLayers()
+    time2 = time.clock()
+    print("toggle = %x" % toggle)
+    msg = "File %s loaded in %g s" % (fileName, time2-time1)
+    if nErrors:
+        msg += " but there where %d errors. " % (nErrors)
+    print(msg)
+    return
+
+#
+#    getObject(name, var, glbals, lcals):
 #
 
 def getObject(name, var, glbals, lcals):
-	try:
-		ob = loadedData['Object'][name]
-	except:
-		if name != "None":
-			pushOnTodoList(None, "ob = loadedData['Object'][name]" % globals(), locals())
-		ob = None
-	return ob
+    try:
+        ob = loadedData['Object'][name]
+    except:
+        if name != "None":
+            pushOnTodoList(None, "ob = loadedData['Object'][name]" % globals(), locals())
+        ob = None
+    return ob
 
 #
-#	checkMhxVersion(major, minor):
+#    checkMhxVersion(major, minor):
 #
 
 def checkMhxVersion(major, minor):
-	global warnedVersion
-	if  major != MAJOR_VERSION or minor != MINOR_VERSION:
-		if warnedVersion:
-			return
-		else:
-			msg = (
+    global warnedVersion
+    if  major != MAJOR_VERSION or minor != MINOR_VERSION:
+        if warnedVersion:
+            return
+        else:
+            msg = (
 "Wrong MHX version\n" +
 "Expected MHX %d.%d but the loaded file has version MHX %d.%d\n" % (MAJOR_VERSION, MINOR_VERSION, major, minor) +
 "You can disable this error message by deselecting the Enforce version option when importing. " +
@@ -382,2074 +386,2086 @@ def checkMhxVersion(major, minor):
 "The current version of the import script is located in the importers/mhx/blender25x folder and is called import_scene_mhx.py. " +
 "The version distributed with Blender builds from www.graphicall.org may be out of date.\n"
 )
-		if toggle & T_EnforceVersion:
-			raise NameError(msg)
-		else:
-			print(msg)
-			warnedVersion = True
-	return
+        if toggle & T_EnforceVersion:
+            raise NameError(msg)
+        else:
+            print(msg)
+            warnedVersion = True
+    return
 
 #
-#	parse(tokens):
+#    parse(tokens):
 #
 
 ifResult = False
 
 def parse(tokens):
-	global MHX249, ifResult, theScale, defaultScale, One
-	
-	for (key, val, sub) in tokens:	
-		# print("Parse %s" % key)
-		data = None
-		if key == 'MHX':
-			checkMhxVersion(int(val[0]), int(val[1]))
-		elif key == 'MHX249':
-			MHX249 = eval(val[0])
-			print("Blender 2.49 compatibility mode is %s\n" % MHX249)
-		elif MHX249:
-			pass
-		elif key == 'print':
-			msg = concatList(val)
-			print(msg)
-		elif key == 'warn':
-			msg = concatList(val)
-			print(msg)
-		elif key == 'error':
-			msg = concatList(val)
-			raise NameError(msg)	
-		elif key == 'NoScale':
-			if eval(val[0]):
-				theScale = 1.0
-			else:
-				theScale = defaultScale		
-			One = 1.0/theScale
-		elif key == "Object":
-			parseObject(val, sub)
-		elif key == "Mesh":
-			data = parseMesh(val, sub)
-		elif key == "Armature":
-			data = parseArmature(val, sub)
-		elif key == "Pose":
-			data = parsePose(val, sub)
-		elif key == "Action":
-			data = parseAction(val, sub)
-		elif key == "Material":
-			data = parseMaterial(val, sub)
-		elif key == "Texture":
-			data = parseTexture(val, sub)
-		elif key == "Image":
-			data = parseImage(val, sub)
-		elif key == "Curve":
-			data = parseCurve(val, sub)
-		elif key == "TextCurve":
-			data = parseTextCurve(val, sub)
-		elif key == "Lattice":
-			data = parseLattice(val, sub)
-		elif key == "Group":
-			data = parseGroup(val, sub)
-		elif key == "Lamp":
-			data = parseLamp(val, sub)
-		elif key == "World":
-			data = parseWorld(val, sub)
-		elif key == "Scene":
-			data = parseScene(val, sub)
-		elif key == "Process":
-			parseProcess(val, sub)
-		elif key == 'AnimationData':
-			try:
-				ob = loadedData['Object'][val[0]]
-			except:
-				ob = None
-			if ob:
-				bpy.context.scene.objects.active = ob
-				parseAnimationData(ob, val, sub)
-		elif key == 'ShapeKeys':
-			try:
-				ob = loadedData['Object'][val[0]]
-			except:
-				ob = None
-			if ob:
-				bpy.context.scene.objects.active = ob
-				parseShapeKeys(ob, ob.data, val, sub)
-		else:
-			data = parseDefaultType(key, val, sub)				
-
-		if data and key != 'Mesh':
-			print( data )
-	return
-
-#
-#	parseDefaultType(typ, args, tokens):
+    global MHX249, ifResult, theScale, defaultScale, One
+    
+    for (key, val, sub) in tokens:    
+        # print("Parse %s" % key)
+        data = None
+        if key == 'MHX':
+            checkMhxVersion(int(val[0]), int(val[1]))
+        elif key == 'MHX249':
+            MHX249 = eval(val[0])
+            print("Blender 2.49 compatibility mode is %s\n" % MHX249)
+        elif MHX249:
+            pass
+        elif key == 'print':
+            msg = concatList(val)
+            print(msg)
+        elif key == 'warn':
+            msg = concatList(val)
+            print(msg)
+        elif key == 'error':
+            msg = concatList(val)
+            raise NameError(msg)    
+        elif key == 'NoScale':
+            if eval(val[0]):
+                theScale = 1.0
+            else:
+                theScale = defaultScale        
+            One = 1.0/theScale
+        elif key == "Object":
+            parseObject(val, sub)
+        elif key == "Mesh":
+            data = parseMesh(val, sub)
+        elif key == "Armature":
+            data = parseArmature(val, sub)
+        elif key == "Pose":
+            data = parsePose(val, sub)
+        elif key == "Action":
+            data = parseAction(val, sub)
+        elif key == "Material":
+            data = parseMaterial(val, sub)
+        elif key == "Texture":
+            data = parseTexture(val, sub)
+        elif key == "Image":
+            data = parseImage(val, sub)
+        elif key == "Curve":
+            data = parseCurve(val, sub)
+        elif key == "TextCurve":
+            data = parseTextCurve(val, sub)
+        elif key == "Lattice":
+            data = parseLattice(val, sub)
+        elif key == "Group":
+            data = parseGroup(val, sub)
+        elif key == "Lamp":
+            data = parseLamp(val, sub)
+        elif key == "World":
+            data = parseWorld(val, sub)
+        elif key == "Scene":
+            data = parseScene(val, sub)
+        elif key == "Process":
+            parseProcess(val, sub)
+        elif key == 'AnimationData':
+            try:
+                ob = loadedData['Object'][val[0]]
+            except:
+                ob = None
+            if ob:
+                bpy.context.scene.objects.active = ob
+                parseAnimationData(ob, val, sub)
+        elif key == 'MaterialAnimationData':
+            try:
+                ob = loadedData['Object'][val[0]]
+            except:
+                ob = None
+            if ob:
+                bpy.context.scene.objects.active = ob
+                mat = ob.data.materials[int(val[2])]
+                print("matanim", ob, mat)
+                parseAnimationData(mat, val, sub)
+        elif key == 'ShapeKeys':
+            try:
+                ob = loadedData['Object'][val[0]]
+            except:
+                raise NameError("ShapeKeys object %s does not exist" % val[0])
+            if ob:
+                bpy.context.scene.objects.active = ob
+                parseShapeKeys(ob, ob.data, val, sub)
+        else:
+            data = parseDefaultType(key, val, sub)                
+
+        if data and key != 'Mesh':
+            print( data )
+    return
+
+#
+#    parseDefaultType(typ, args, tokens):
 #
 
 def parseDefaultType(typ, args, tokens):
-	global todo
+    global todo
 
-	name = args[0]
-	data = None
-	expr = "bpy.data.%s.new('%s')" % (Plural[typ], name)
-	print(expr)
-	data = eval(expr)
-	print("  ok", data)
+    name = args[0]
+    data = None
+    expr = "bpy.data.%s.new('%s')" % (Plural[typ], name)
+    print(expr)
+    data = eval(expr)
+    print("  ok", data)
 
-	bpyType = typ.capitalize()
-	print(bpyType, name, data)
-	loadedData[bpyType][name] = data
-	if data == None:
-		return None
+    bpyType = typ.capitalize()
+    print(bpyType, name, data)
+    loadedData[bpyType][name] = data
+    if data == None:
+        return None
 
-	for (key, val, sub) in tokens:
-		#print("%s %s" % (key, val))
-		defaultKey(key, val, sub, 'data', [], globals(), locals())
-	print("Done ", data)
-	return data
-	
+    for (key, val, sub) in tokens:
+        #print("%s %s" % (key, val))
+        defaultKey(key, val, sub, 'data', [], globals(), locals())
+    print("Done ", data)
+    return data
+    
 #
-#	concatList(elts)
+#    concatList(elts)
 #
 
 def concatList(elts):
-	string = ""
-	for elt in elts:
-		string += " %s" % elt
-	return string
+    string = ""
+    for elt in elts:
+        string += " %s" % elt
+    return string
 
 #
-#	parseAction(args, tokens):
-#	parseFCurve(fcu, args, tokens):
-#	parseKeyFramePoint(pt, args, tokens):
+#    parseAction(args, tokens):
+#    parseFCurve(fcu, args, tokens):
+#    parseKeyFramePoint(pt, args, tokens):
 #
 
 def parseAction(args, tokens):
-	name = args[0]
-	if invalid(args[1]):
-		return
-
-	ob = bpy.context.object
-	bpy.ops.object.mode_set(mode='POSE')
-	if ob.animation_data:
-		ob.animation_data.action = None
-	created = {}
-	for (key, val, sub) in tokens:
-		if key == 'FCurve':
-			prepareActionFCurve(ob, created, val, sub)
-		
-	act = ob.animation_data.action
-	loadedData['Action'][name] = act
-	if act == None:
-		print("Ignoring action %s" % name)
-		return act
-	act.name = name
-	print("Action", name, act, ob)
-	
-	for (key, val, sub) in tokens:
-		if key == 'FCurve':
-			fcu = parseActionFCurve(act, ob, val, sub)
-		else:
-			defaultKey(key, val, sub, 'act', [], globals(), locals())
-	ob.animation_data.action = None
-	bpy.ops.object.mode_set(mode='OBJECT')
-	return act
-
-def prepareActionFCurve(ob, created, args, tokens):			
-	dataPath = args[0]
-	index = args[1]
-	(expr, channel) = channelFromDataPath(dataPath, index)
-	try:
-		if channel in created[expr]:
-			return
-		else:
-			created[expr].append(channel)
-	except:
-		created[expr] = [channel]
-
-	times = []
-	for (key, val, sub) in tokens:
-		if key == 'kp':
-			times.append(int(val[0]))
-
-	try:
-		data = eval(expr)
-	except:
-		print("Ignoring illegal expression: %s" % expr)
-		return
-
-	n = 0
-	for t in times:
-		#bpy.context.scene.current_frame = t
-		bpy.ops.anim.change_frame(frame = t)
-		try:
-			data.keyframe_insert(channel)
-			n += 1
-		except:
-			pass
-			#print("failed", data, expr, channel)
-	if n != len(times):
-		print("Mismatch", n, len(times), expr, channel)
-	return
+    name = args[0]
+    if invalid(args[1]):
+        return
+
+    ob = bpy.context.object
+    bpy.ops.object.mode_set(mode='POSE')
+    if ob.animation_data:
+        ob.animation_data.action = None
+    created = {}
+    for (key, val, sub) in tokens:
+        if key == 'FCurve':
+            prepareActionFCurve(ob, created, val, sub)
+        
+    act = ob.animation_data.action
+    loadedData['Action'][name] = act
+    if act == None:
+        print("Ignoring action %s" % name)
+        return act
+    act.name = name
+    print("Action", name, act, ob)
+    
+    for (key, val, sub) in tokens:
+        if key == 'FCurve':
+            fcu = parseActionFCurve(act, ob, val, sub)
+        else:
+            defaultKey(key, val, sub, 'act', [], globals(), locals())
+    ob.animation_data.action = None
+    bpy.ops.object.mode_set(mode='OBJECT')
+    return act
+
+def prepareActionFCurve(ob, created, args, tokens):            
+    dataPath = args[0]
+    index = args[1]
+    (expr, channel) = channelFromDataPath(dataPath, index)
+    try:
+        if channel in created[expr]:
+            return
+        else:
+            created[expr].append(channel)
+    except:
+        created[expr] = [channel]
+
+    times = []
+    for (key, val, sub) in tokens:
+        if key == 'kp':
+            times.append(int(val[0]))
+
+    try:
+        data = eval(expr)
+    except:
+        print("Ignoring illegal expression: %s" % expr)
+        return
+
+    n = 0
+    for t in times:
+        #bpy.context.scene.current_frame = t
+        bpy.ops.anim.change_frame(frame = t)
+        try:
+            data.keyframe_insert(channel)
+            n += 1
+        except:
+            pass
+            #print("failed", data, expr, channel)
+    if n != len(times):
+        print("Mismatch", n, len(times), expr, channel)
+    return
 
 def channelFromDataPath(dataPath, index):
-	words = dataPath.split(']')
-	if len(words) == 1:
-		# location
-		expr = "ob"
-		channel = dataPath
-	elif len(words) == 2:
-		# pose.bones["tongue"].location
-		expr = "ob.%s]" % (words[0])
-		cwords = words[1].split('.')
-		channel = cwords[1]
-	elif len(words) == 3:
-		# pose.bones["brow.R"]["mad"]
-		expr = "ob.%s]" % (words[0])
-		cwords = words[1].split('"')
-		channel = cwords[1]
-	# print(expr, channel, index)
-	return (expr, channel)
+    words = dataPath.split(']')
+    if len(words) == 1:
+        # location
+        expr = "ob"
+        channel = dataPath
+    elif len(words) == 2:
+        # pose.bones["tongue"].location
+        expr = "ob.%s]" % (words[0])
+        cwords = words[1].split('.')
+        channel = cwords[1]
+    elif len(words) == 3:
+        # pose.bones["brow.R"]["mad"]
+        expr = "ob.%s]" % (words[0])
+        cwords = words[1].split('"')
+        channel = cwords[1]
+    # print(expr, channel, index)
+    return (expr, channel)
 
 def parseActionFCurve(act, ob, args, tokens):
-	dataPath = args[0]
-	index = args[1]
-	(expr, channel) = channelFromDataPath(dataPath, index)
-	index = int(args[1])
-
-	success = False
-	for fcu in act.fcurves:
-		(expr1, channel1) = channelFromDataPath(fcu.data_path, fcu.array_index)
-		if expr1 == expr and channel1 == channel and fcu.array_index == index:
-			success = True
-			break
-	if not success:
-		return None
-
-	n = 0
-	for (key, val, sub) in tokens:
-		if key == 'kp':
-			try:
-				pt = fcu.keyframe_points[n]
-				pt.interpolation = 'LINEAR'
-				pt = parseKeyFramePoint(pt, val, sub)
-				n += 1
-			except:
-				pass
-				#print(tokens)
-				#raise NameError("kp", fcu, n, len(fcu.keyframe_points), val)
-		else:
-			defaultKey(key, val, sub, 'fcu', [], globals(), locals())
-	return fcu
+    dataPath = args[0]
+    index = args[1]
+    (expr, channel) = channelFromDataPath(dataPath, index)
+    index = int(args[1])
+
+    success = False
+    for fcu in act.fcurves:
+        (expr1, channel1) = channelFromDataPath(fcu.data_path, fcu.array_index)
+        if expr1 == expr and channel1 == channel and fcu.array_index == index:
+            success = True
+            break
+    if not success:
+        return None
+
+    n = 0
+    for (key, val, sub) in tokens:
+        if key == 'kp':
+            try:
+                pt = fcu.keyframe_points[n]
+                pt.interpolation = 'LINEAR'
+                pt = parseKeyFramePoint(pt, val, sub)
+                n += 1
+            except:
+                pass
+                #print(tokens)
+                #raise NameError("kp", fcu, n, len(fcu.keyframe_points), val)
+        else:
+            defaultKey(key, val, sub, 'fcu', [], globals(), locals())
+    return fcu
 
 def parseKeyFramePoint(pt, args, tokens):
-	pt.co = (float(args[0]), float(args[1]))
-	if len(args) > 2:
-		pt.handle1 = (float(args[2]), float(args[3]))
-		pt.handle2 = (float(args[3]), float(args[5]))
-	return pt
+    pt.co = (float(args[0]), float(args[1]))
+    if len(args) > 2:
+        pt.handle1 = (float(args[2]), float(args[3]))
+        pt.handle2 = (float(args[3]), float(args[5]))
+    return pt
 
 #
-#	parseAnimationData(rna, args, tokens):
-#	parseDriver(drv, args, tokens):
-#	parseDriverVariable(var, args, tokens):
+#    parseAnimationData(rna, args, tokens):
+#    parseDriver(drv, args, tokens):
+#    parseDriverVariable(var, args, tokens):
 #
 
 def parseAnimationData(rna, args, tokens):
-	if not eval(args[1]):
-		return
-	if rna.animation_data == None:	
-		rna.animation_data_create()
-	adata = rna.animation_data
-	for (key, val, sub) in tokens:
-		if key == 'FCurve':
-			fcu = parseAnimDataFCurve(adata, rna, val, sub)
-		else:
-			defaultKey(key, val, sub, 'adata', [], globals(), locals())
-	return adata
+    if not eval(args[1]):
+        return
+    if rna.animation_data == None:    
+        rna.animation_data_create()
+    adata = rna.animation_data
+    for (key, val, sub) in tokens:
+        if key == 'FCurve':
+            fcu = parseAnimDataFCurve(adata, rna, val, sub)
+        else:
+            defaultKey(key, val, sub, 'adata', [], globals(), locals())
+    return adata
 
 def parseAnimDataFCurve(adata, rna, args, tokens):
-	if invalid(args[2]):
-		return
-	dataPath = args[0]
-	index = int(args[1])
-	# print("parseAnimDataFCurve", adata, dataPath, index)
-	for (key, val, sub) in tokens:
-		if key == 'Driver':
-			fcu = parseDriver(adata, dataPath, index, rna, val, sub)
-		elif key == 'FModifier':
-			parseFModifier(fcu, val, sub)
-		else:
-			defaultKey(key, val, sub, 'fcu', [], globals(), locals())
-	return fcu
+    if invalid(args[2]):
+        return
+    dataPath = args[0]
+    index = int(args[1])
+    # print("parseAnimDataFCurve", adata, dataPath, index)
+    n = 1
+    for (key, val, sub) in tokens:
+        if key == 'Driver':
+            fcu = parseDriver(adata, dataPath, index, rna, val, sub)
+            fmod = fcu.modifiers[0]
+            fcu.modifiers.remove(fmod)
+        elif key == 'FModifier':
+            parseFModifier(fcu, val, sub)
+        elif key == 'kp':
+            pt = fcu.keyframe_points.add(n, 0)
+            pt.interpolation = 'LINEAR'
+            pt = parseKeyFramePoint(pt, val, sub)
+            n += 1
+        else:
+            defaultKey(key, val, sub, 'fcu', [], globals(), locals())
+    return fcu
 
 """
-		fcurve = con.driver_add("influence", 0)
-		driver = fcurve.driver
-		driver.type = 'AVERAGE'
+        fcurve = con.driver_add("influence", 0)
+        driver = fcurve.driver
+        driver.type = 'AVERAGE'
 """
 def parseDriver(adata, dataPath, index, rna, args, tokens):
-	if dataPath[-1] == ']':
-		words = dataPath.split(']')
-		expr = "rna." + words[0] + ']'
-		pwords = words[1].split('"')
-		prop = pwords[1]
-		# print("prop", expr, prop)
-		bone = eval(expr)
-		return None
-	else:
-		words = dataPath.split('.')
-		channel = words[-1]
-		expr = "rna"
-		for n in range(len(words)-1):
-			expr += "." + words[n]
-		expr += ".driver_add('%s', index)" % channel
-	
-	# print("expr", rna, expr)
-	fcu = eval(expr)
-	drv = fcu.driver
-	drv.type = args[0]
-	for (key, val, sub) in tokens:
-		if key == 'DriverVariable':
-			var = parseDriverVariable(drv, rna, val, sub)
-		else:
-			defaultKey(key, val, sub, 'drv', [], globals(), locals())
-	return fcu
+    if dataPath[-1] == ']':
+        words = dataPath.split(']')
+        expr = "rna." + words[0] + ']'
+        pwords = words[1].split('"')
+        prop = pwords[1]
+        # print("prop", expr, prop)
+        bone = eval(expr)
+        return None
+    else:
+        words = dataPath.split('.')
+        channel = words[-1]
+        expr = "rna"
+        for n in range(len(words)-1):
+            expr += "." + words[n]
+        expr += ".driver_add('%s', index)" % channel
+    
+    #print("expr", rna, expr)
+    fcu = eval(expr)
+    drv = fcu.driver
+    drv.type = args[0]
+    for (key, val, sub) in tokens:
+        if key == 'DriverVariable':
+            var = parseDriverVariable(drv, rna, val, sub)
+        else:
+            defaultKey(key, val, sub, 'drv', [], globals(), locals())
+    return fcu
 
 def parseDriverVariable(drv, rna, args, tokens):
-	var = drv.variables.new()
-	var.name = args[0]
-	var.type = args[1]
-	nTarget = 0
-	# print("var", var, var.name, var.type)
-	for (key, val, sub) in tokens:
-		if key == 'Target':
-			parseDriverTarget(var, nTarget, rna, val, sub)
-			nTarget += 1
-		else:
-			defaultKey(key, val, sub, 'var', [], globals(), locals())
-	return var
+    var = drv.variables.new()
+    var.name = args[0]
+    var.type = args[1]
+    nTarget = 0
+    # print("var", var, var.name, var.type)
+    for (key, val, sub) in tokens:
+        if key == 'Target':
+            parseDriverTarget(var, nTarget, rna, val, sub)
+            nTarget += 1
+        else:
+            defaultKey(key, val, sub, 'var', [], globals(), locals())
+    return var
 
 def parseFModifier(fcu, args, tokens):
-	#fmod = fcu.modifiers.new()
-	fmod = fcu.modifiers[0]
-	#fmod.type = args[0]
-	#print("fmod", fmod, fmod.type)
-	for (key, val, sub) in tokens:
-		defaultKey(key, val, sub, 'fmod', [], globals(), locals())
-	return fmod
+    fmod = fcu.modifiers.new(args[0])
+    #fmod = fcu.modifiers[0]
+    for (key, val, sub) in tokens:
+        defaultKey(key, val, sub, 'fmod', [], globals(), locals())
+    return fmod
 
 """
-		var = driver.variables.new()
-		var.name = target_bone
-		var.targets[0].id_type = 'OBJECT'
-		var.targets[0].id = obj
-		var.targets[0].rna_path = driver_path
+        var = driver.variables.new()
+        var.name = target_bone
+        var.targets[0].id_type = 'OBJECT'
+        var.targets[0].id = obj
+        var.targets[0].rna_path = driver_path
 """
 def parseDriverTarget(var, nTarget, rna, args, tokens):
-	targ = var.targets[nTarget]
-	targ.id = loadedData['Object'][args[0]]
-	for (key, val, sub) in tokens:
-		defaultKey(key, val, sub, 'targ', [], globals(), locals())
-	return targ
+    targ = var.targets[nTarget]
+    targ.id = loadedData['Object'][args[0]]
+    for (key, val, sub) in tokens:
+        defaultKey(key, val, sub, 'targ', [], globals(), locals())
+    return targ
 
-	
+    
 #
-#	parseMaterial(args, ext, tokens):
-#	parseMTex(mat, args, tokens):
-#	parseTexture(args, tokens):
+#    parseMaterial(args, ext, tokens):
+#    parseMTex(mat, args, tokens):
+#    parseTexture(args, tokens):
 #
 
 def parseMaterial(args, tokens):
-	global todo
-	name = args[0]
-	mat = bpy.data.materials.new(name)
-	if mat == None:
-		return None
-	loadedData['Material'][name] = mat
-	for (key, val, sub) in tokens:
-		if key == 'MTex':
-			parseMTex(mat, val, sub)
-		elif key == 'Ramp':
-			parseRamp(mat, val, sub)
-		elif key == 'RaytraceTransparency':
-			parseDefault(mat.raytrace_transparency, sub, {}, [])
-		elif key == 'Halo':
-			parseDefault(mat.halo, sub, {}, [])
-		elif key == 'SSS':
-			parseDefault(mat.subsurface_scattering, sub, {}, [])
-		elif key == 'Strand':
-			parseDefault(mat.strand, sub, {}, [])
-		elif key == 'NodeTree':
-			mat.use_nodes = True
-			parseNodeTree(mat.node_tree, val, sub)
-		else:
-			exclude = ['specular_intensity', 'tangent_shading']
-			defaultKey(key, val, sub, 'mat', [], globals(), locals())
-	
-	return mat
+    global todo
+    name = args[0]
+    mat = bpy.data.materials.new(name)
+    if mat == None:
+        return None
+    loadedData['Material'][name] = mat
+    for (key, val, sub) in tokens:
+        if key == 'MTex':
+            parseMTex(mat, val, sub)
+        elif key == 'Ramp':
+            parseRamp(mat, val, sub)
+        elif key == 'RaytraceTransparency':
+            parseDefault(mat.raytrace_transparency, sub, {}, [])
+        elif key == 'Halo':
+            parseDefault(mat.halo, sub, {}, [])
+        elif key == 'SSS':
+            parseDefault(mat.subsurface_scattering, sub, {}, [])
+        elif key == 'Strand':
+            parseDefault(mat.strand, sub, {}, [])
+        elif key == 'NodeTree':
+            mat.use_nodes = True
+            parseNodeTree(mat.node_tree, val, sub)
+        else:
+            exclude = ['specular_intensity', 'tangent_shading']
+            defaultKey(key, val, sub, 'mat', [], globals(), locals())
+    
+    return mat
 
 def parseMTex(mat, args, tokens):
-	global todo
-	index = int(args[0])
-	texname = args[1]
-	texco = args[2]
-	mapto = args[3]
-	tex = loadedData['Texture'][texname]
-	mtex = mat.texture_slots.add()
-	mtex.texture_coords = texco
-	mtex.texture = tex
+    global todo
+    index = int(args[0])
+    texname = args[1]
+    texco = args[2]
+    mapto = args[3]
+    tex = loadedData['Texture'][texname]
+    mtex = mat.texture_slots.add()
+    mtex.texture_coords = texco
+    mtex.texture = tex
 
-	for (key, val, sub) in tokens:
-		defaultKey(key, val, sub, "mtex", [], globals(), locals())
+    for (key, val, sub) in tokens:
+        defaultKey(key, val, sub, "mtex", [], globals(), locals())
 
-	return mtex
+    return mtex
 
 def parseTexture(args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing texture %s" % args )
-	name = args[0]
-	tex = bpy.data.textures.new(name=name, type=args[1])
-	loadedData['Texture'][name] = tex
-	
-	for (key, val, sub) in tokens:
-		if key == 'Image':
-			try:
-				imgName = val[0]
-				img = loadedData['Image'][imgName]
-				tex.image = img
-			except:
-				msg = "Unable to load image '%s'" % val[0]
-		elif key == 'Ramp':
-			parseRamp(tex, val, sub)
-		elif key == 'NodeTree':
-			tex.use_nodes = True
-			parseNodeTree(tex.node_tree, val, sub)
-		else:
-			defaultKey(key, val,  sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
-
-	return tex
+    global todo
+    if verbosity > 2:
+        print( "Parsing texture %s" % args )
+    name = args[0]
+    tex = bpy.data.textures.new(name=name, type=args[1])
+    loadedData['Texture'][name] = tex
+    
+    for (key, val, sub) in tokens:
+        if key == 'Image':
+            try:
+                imgName = val[0]
+                img = loadedData['Image'][imgName]
+                tex.image = img
+            except:
+                msg = "Unable to load image '%s'" % val[0]
+        elif key == 'Ramp':
+            parseRamp(tex, val, sub)
+        elif key == 'NodeTree':
+            tex.use_nodes = True
+            parseNodeTree(tex.node_tree, val, sub)
+        else:
+            defaultKey(key, val,  sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
+
+    return tex
 
 def parseRamp(data, args, tokens):
-	nvar = "data.%s" % args[0]
-	use = "data.use_%s = True" % args[0]
-	exec(use)
-	ramp = eval(nvar)
-	elts = ramp.elements
-	n = 0
-	for (key, val, sub) in tokens:
-		# print("Ramp", key, val)
-		if key == 'Element':
-			elts[n].color = eval(val[0])
-			elts[n].position = eval(val[1])
-			n += 1
-		else:
-			defaultKey(key, val,  sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
-	
+    nvar = "data.%s" % args[0]
+    use = "data.use_%s = True" % args[0]
+    exec(use)
+    ramp = eval(nvar)
+    elts = ramp.elements
+    n = 0
+    for (key, val, sub) in tokens:
+        # print("Ramp", key, val)
+        if key == 'Element':
+            elts[n].color = eval(val[0])
+            elts[n].position = eval(val[1])
+            n += 1
+        else:
+            defaultKey(key, val,  sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
+    
 def parseSSS(mat, args, tokens):
-	sss = mat.subsurface_scattering
-	for (key, val, sub) in tokens:
-		defaultKey(key, val, sub, "sss", [], globals(), locals())
+    sss = mat.subsurface_scattering
+    for (key, val, sub) in tokens:
+        defaultKey(key, val, sub, "sss", [], globals(), locals())
 
 def parseStrand(mat, args, tokens):
-	strand = mat.strand
-	for (key, val, sub) in tokens:
-		defaultKey(key, val, sub, "strand", [], globals(), locals())
+    strand = mat.strand
+    for (key, val, sub) in tokens:
+        defaultKey(key, val, sub, "strand", [], globals(), locals())
 
 #
-#	parseNodeTree(tree, args, tokens):
-#	parseNode(node, args, tokens):
-#	parseSocket(socket, args, tokens):
+#    parseNodeTree(tree, args, tokens):
+#    parseNode(node, args, tokens):
+#    parseSocket(socket, args, tokens):
 #
 
 def parseNodeTree(tree, args, tokens):
-	return
-	print("Tree", tree, args)
-	print(list(tree.nodes))
-	tree.name = args[0]
-	for (key, val, sub) in tokens:
-		if key == 'Node':
-			parseNodes(tree.nodes, val, sub)
-		else:
-			defaultKey(key, val, sub, "tree", [], globals(), locals())
+    return
+    print("Tree", tree, args)
+    print(list(tree.nodes))
+    tree.name = args[0]
+    for (key, val, sub) in tokens:
+        if key == 'Node':
+            parseNodes(tree.nodes, val, sub)
+        else:
+            defaultKey(key, val, sub, "tree", [], globals(), locals())
 
 def parseNodes(nodes, args, tokens):
-	print("Nodes", nodes, args)
-	print(list(nodes))
-	node.name = args[0]
-	for (key, val, sub) in tokens:
-		if key == 'Inputs':
-			parseSocket(node.inputs, val, sub)
-		elif key == 'Outputs':
-			parseSocket(node.outputs, val, sub)
-		else:
-			defaultKey(key, val, sub, "node", [], globals(), locals())
+    print("Nodes", nodes, args)
+    print(list(nodes))
+    node.name = args[0]
+    for (key, val, sub) in tokens:
+        if key == 'Inputs':
+            parseSocket(node.inputs, val, sub)
+        elif key == 'Outputs':
+            parseSocket(node.outputs, val, sub)
+        else:
+            defaultKey(key, val, sub, "node", [], globals(), locals())
 
 def parseNode(node, args, tokens):
-	print("Node", node, args)
-	print(list(node.inputs), list(node.outputs))
-	node.name = args[0]
-	for (key, val, sub) in tokens:
-		if key == 'Inputs':
-			parseSocket(node.inputs, val, sub)
-		elif key == 'Outputs':
-			parseSocket(node.outputs, val, sub)
-		else:
-			defaultKey(key, val, sub, "node", [], globals(), locals())
+    print("Node", node, args)
+    print(list(node.inputs), list(node.outputs))
+    node.name = args[0]
+    for (key, val, sub) in tokens:
+        if key == 'Inputs':
+            parseSocket(node.inputs, val, sub)
+        elif key == 'Outputs':
+            parseSocket(node.outputs, val, sub)
+        else:
+            defaultKey(key, val, sub, "node", [], globals(), locals())
 
 def parseSocket(socket, args, tokens):
-	print("Socket", socket, args)
-	socket.name = args[0]
-	for (key, val, sub) in tokens:
-		if key == 'Node':
-			parseNode(tree.nodes, val, sub)
-		else:
-			defaultKey(key, val, sub, "tree", [], globals(), locals())
+    print("Socket", socket, args)
+    socket.name = args[0]
+    for (key, val, sub) in tokens:
+        if key == 'Node':
+            parseNode(tree.nodes, val, sub)
+        else:
+            defaultKey(key, val, sub, "tree", [], globals(), locals())
 
 
 
 #
-#	doLoadImage(filepath):
-#	loadImage(filepath):
-#	parseImage(args, tokens):
+#    doLoadImage(filepath):
+#    loadImage(filepath):
+#    parseImage(args, tokens):
 #
 
-def doLoadImage(filepath):		
-	path1 = os.path.expanduser(filepath)
-	file1 = os.path.realpath(path1)
-	if os.path.isfile(file1):
-		print( "Found file "+file1 )
-		try:
-			img = bpy.data.images.load(file1)
-			return img
-		except:
-			print( "Cannot read image" )
-			return None
-	else:
-		print( "No file "+file1 )
-		return None
+def doLoadImage(filepath):        
+    path1 = os.path.expanduser(filepath)
+    file1 = os.path.realpath(path1)
+    if os.path.isfile(file1):
+        print( "Found file "+file1 )
+        try:
+            img = bpy.data.images.load(file1)
+            return img
+        except:
+            print( "Cannot read image" )
+            return None
+    else:
+        print( "No file "+file1 )
+        return None
 
 
 def loadImage(filepath):
-	global TexDir, warnedTextureDir, loadedData
-
-	texDir = os.path.expanduser(TexDir)
-	path1 = os.path.expanduser(filepath)
-	file1 = os.path.realpath(path1)
-	(path, filename) = os.path.split(file1)
-	(name, ext) = os.path.splitext(filename)
-	print( "Loading ", filepath, " = ", filename )
-
-	# img = doLoadImage(texDir+"/"+name+".png")
-	# if img:
-	#	return img
-
-	img = doLoadImage(texDir+"/"+filename)
-	if img:
-		return img
-
-	# img = doLoadImage(path+"/"+name+".png")
-	# if img:
-	#	return img
-
-	img = doLoadImage(path+"/"+filename)
-	if img:
-		return img
-
-	if warnedTextureDir:
-		return None
-	warnedTextureDir = True
-	return None
-	TexDir = Draw.PupStrInput("TexDir? ", path, 100)
-
-	texDir = os.path.expanduser(TexDir)
-	img =  doLoadImage(texDir+"/"+name+".png")
-	if img:
-		return img
-
-	img = doLoadImage(TexDir+"/"+filename)
-	return img
-	
+    global TexDir, warnedTextureDir, loadedData
+
+    texDir = os.path.expanduser(TexDir)
+    path1 = os.path.expanduser(filepath)
+    file1 = os.path.realpath(path1)
+    (path, filename) = os.path.split(file1)
+    (name, ext) = os.path.splitext(filename)
+    print( "Loading ", filepath, " = ", filename )
+
+    # img = doLoadImage(texDir+"/"+name+".png")
+    # if img:
+    #    return img
+
+    img = doLoadImage(texDir+"/"+filename)
+    if img:
+        return img
+
+    # img = doLoadImage(path+"/"+name+".png")
+    # if img:
+    #    return img
+
+    img = doLoadImage(path+"/"+filename)
+    if img:
+        return img
+
+    if warnedTextureDir:
+        return None
+    warnedTextureDir = True
+    return None
+    TexDir = Draw.PupStrInput("TexDir? ", path, 100)
+
+    texDir = os.path.expanduser(TexDir)
+    img =  doLoadImage(texDir+"/"+name+".png")
+    if img:
+        return img
+
+    img = doLoadImage(TexDir+"/"+filename)
+    return img
+    
 def parseImage(args, tokens):
-	global todo
-	imgName = args[0]
-	img = None
-	for (key, val, sub) in tokens:
-		if key == 'Filename':
-			filename = val[0]
-			for n in range(1,len(val)):
-				filename += " " + val[n]
-			img = loadImage(filename)
-			if img == None:
-				return None
-			img.name = imgName
-		else:
-			defaultKey(key, val,  sub, "img", ['depth', 'dirty', 'has_data', 'size', 'type'], globals(), locals())
-	print ("Image %s" % img )
-	loadedData['Image'][imgName] = img
-	return img
-
-#
-#	parseObject(args, tokens):
-#	createObject(type, name, data, datName):
-#	setObjectAndData(args, typ):
-#
-	
+    global todo
+    imgName = args[0]
+    img = None
+    for (key, val, sub) in tokens:
+        if key == 'Filename':
+            filename = val[0]
+            for n in range(1,len(val)):
+                filename += " " + val[n]
+            img = loadImage(filename)
+            if img == None:
+                return None
+            img.name = imgName
+        else:
+            defaultKey(key, val,  sub, "img", ['depth', 'dirty', 'has_data', 'size', 'type'], globals(), locals())
+    print ("Image %s" % img )
+    loadedData['Image'][imgName] = img
+    return img
+
+#
+#    parseObject(args, tokens):
+#    createObject(type, name, data, datName):
+#    setObjectAndData(args, typ):
+#
+    
 def parseObject(args, tokens):
-	if verbosity > 2:
-		print( "Parsing object %s" % args )
-	name = args[0]
-	typ = args[1]
-	datName = args[2]
-
-	if typ == 'EMPTY':
-		print("EMPTY")
-		ob = bpy.data.objects.new(name, None)
-		loadedData['Object'][name] = ob
-		linkObject(ob, None)
-	else:
-		try:
-			data = loadedData[typ.capitalize()][datName]	
-		except:
-			raise NameError("Failed to find data: %s %s %s" % (name, typ, datName))
-			return
-
-	try:
-		ob = loadedData['Object'][name]
-		bpy.context.scene.objects.active = ob
-		#print("Found data", ob)
-	except:
-		ob = None
-
-	if ob == None:
-		print("Create", name, data, datName)
-		ob = createObject(typ, name, data, datName)
-		print("created", ob)
-		linkObject(ob, data)
-
-	for (key, val, sub) in tokens:
-		if key == 'Modifier':
-			parseModifier(ob, val, sub)
-		elif key == 'Constraint':
-			parseConstraint(ob.constraints, val, sub)
-		elif key == 'AnimationData':
-			parseAnimationData(ob, val, sub)
-		elif key == 'ParticleSystem':
-			parseParticleSystem(ob, val, sub)
-		elif key == 'FieldSettings':
-			parseDefault(ob.field, sub, {}, [])
-		else:
-			defaultKey(key, val, sub, "ob", ['type', 'data'], globals(), locals())
-
-	# Needed for updating layers
-	if bpy.context.object == ob:
-		pass
-		'''
-		if ob.data in ['MESH', 'ARMATURE']:
-			print(ob, ob.data)
-			bpy.ops.object.mode_set(mode='EDIT')
-			bpy.ops.object.mode_set(mode='OBJECT')
-		'''
-	else:
-		print("Context", ob, bpy.context.object, bpy.context.scene.objects.active)
-	return
+    if verbosity > 2:
+        print( "Parsing object %s" % args )
+    name = args[0]
+    typ = args[1]
+    datName = args[2]
+
+    if typ == 'EMPTY':
+        ob = bpy.data.objects.new(name, None)
+        loadedData['Object'][name] = ob
+        linkObject(ob, None)
+    else:
+        try:
+            data = loadedData[typ.capitalize()][datName]    
+        except:
+            raise NameError("Failed to find data: %s %s %s" % (name, typ, datName))
+            return
+
+    try:
+        ob = loadedData['Object'][name]
+        bpy.context.scene.objects.active = ob
+        #print("Found data", ob)
+    except:
+        ob = None
+
+    if ob == None:
+        print("Create", name, data, datName)
+        ob = createObject(typ, name, data, datName)
+        print("created", ob)
+        linkObject(ob, data)
+
+    for (key, val, sub) in tokens:
+        if key == 'Modifier':
+            parseModifier(ob, val, sub)
+        elif key == 'Constraint':
+            parseConstraint(ob.constraints, val, sub)
+        elif key == 'AnimationData':
+            parseAnimationData(ob, val, sub)
+        elif key == 'ParticleSystem':
+            parseParticleSystem(ob, val, sub)
+        elif key == 'FieldSettings':
+            parseDefault(ob.field, sub, {}, [])
+        else:
+            defaultKey(key, val, sub, "ob", ['type', 'data'], globals(), locals())
+
+    # Needed for updating layers
+    if bpy.context.object == ob:
+        pass
+        '''
+        if ob.data in ['MESH', 'ARMATURE']:
+            print(ob, ob.data)
+            bpy.ops.object.mode_set(mode='EDIT')
+            bpy.ops.object.mode_set(mode='OBJECT')
+        '''
+    else:
+        print("Context", ob, bpy.context.object, bpy.context.scene.objects.active)
+    return
 
 def createObject(typ, name, data, datName):
-	# print( "Creating object %s %s %s" % (typ, name, data) )	
-	ob = bpy.data.objects.new(name, data)
-	if data:
-		loadedData[typ.capitalize()][datName] = data
-	loadedData['Object'][name] = ob
-	return ob
-	
+    # print( "Creating object %s %s %s" % (typ, name, data) )    
+    ob = bpy.data.objects.new(name, data)
+    if data:
+        loadedData[typ.capitalize()][datName] = data
+    loadedData['Object'][name] = ob
+    return ob
+    
 def linkObject(ob, data):
-	#print("Data", data, ob.data)
-	if data and ob.data == None:
-		ob.data = data
-		print("Data linked", ob, ob.data)
-	scn = bpy.context.scene
-	scn.objects.link(ob)
-	scn.objects.active = ob
-	#print("Linked object", ob)
-	#print("Scene", scn)
-	#print("Active", scn.objects.active)
-	#print("Context", bpy.context.object)
-	return ob
+    #print("Data", data, ob.data)
+    if data and ob.data == None:
+        ob.data = data
+        print("Data linked", ob, ob.data)
+    scn = bpy.context.scene
+    scn.objects.link(ob)
+    scn.objects.active = ob
+    #print("Linked object", ob)
+    #print("Scene", scn)
+    #print("Active", scn.objects.active)
+    #print("Context", bpy.context.object)
+    return ob
 
 def setObjectAndData(args, typ):
-	datName = args[0]
-	obName = args[1]
-	#bpy.ops.object.add(type=typ)
-	ob = bpy.context.object
-	ob.name = obName
-	ob.data.name = datName
-	loadedData[typ][datName] = ob.data
-	loadedData['Object'][obName] = ob
-	return ob.data
+    datName = args[0]
+    obName = args[1]
+    #bpy.ops.object.add(type=typ)
+    ob = bpy.context.object
+    ob.name = obName
+    ob.data.name = datName
+    loadedData[typ][datName] = ob.data
+    loadedData['Object'][obName] = ob
+    return ob.data
 
 
 #
-#	parseModifier(ob, args, tokens):
+#    parseModifier(ob, args, tokens):
 #
 
 def parseModifier(ob, args, tokens):
-	name = args[0]
-	typ = args[1]
-	if typ == 'PARTICLE_SYSTEM':
-		return None
-	mod = ob.modifiers.new(name, typ)
-	for (key, val, sub) in tokens:
-		defaultKey(key, val, sub, 'mod', [], globals(), locals())
-	return mod
+    name = args[0]
+    typ = args[1]
+    if typ == 'PARTICLE_SYSTEM':
+        return None
+    mod = ob.modifiers.new(name, typ)
+    for (key, val, sub) in tokens:
+        defaultKey(key, val, sub, 'mod', [], globals(), locals())
+    return mod
 
 #
-#	parseParticleSystem(ob, args, tokens):
-#	parseParticles(particles, args, tokens):
-#	parseParticle(par, args, tokens):
+#    parseParticleSystem(ob, args, tokens):
+#    parseParticles(particles, args, tokens):
+#    parseParticle(par, args, tokens):
 #
 
 def parseParticleSystem(ob, args, tokens):
-	print(ob, bpy.context.object)
-	pss = ob.particle_systems
-	print(pss, pss.values())
-	name = args[0]
-	typ = args[1]
-	#psys = pss.new(name, typ)
-	bpy.ops.object.particle_system_add()
-	print(pss, pss.values())
-	psys = pss[-1]
-	psys.name = name
-	psys.settings.type = typ
-	loadedData['ParticleSystem'][name] = psys
-	print("Psys", psys)
-
-	for (key, val, sub) in tokens:
-		if key == 'Particles':
-			parseParticles(psys, val, sub)
-		else:
-			defaultKey(key, val, sub, 'psys', [], globals(), locals())
-	return psys
+    print(ob, bpy.context.object)
+    pss = ob.particle_systems
+    print(pss, pss.values())
+    name = args[0]
+    typ = args[1]
+    #psys = pss.new(name, typ)
+    bpy.ops.object.particle_system_add()
+    print(pss, pss.values())
+    psys = pss[-1]
+    psys.name = name
+    psys.settings.type = typ
+    loadedData['ParticleSystem'][name] = psys
+    print("Psys", psys)
+
+    for (key, val, sub) in tokens:
+        if key == 'Particles':
+            parseParticles(psys, val, sub)
+        else:
+            defaultKey(key, val, sub, 'psys', [], globals(), locals())
+    return psys
 
 def parseParticles(psys, args, tokens):
-	particles = psys.particles
-	bpy.ops.particle.particle_edit_toggle()
-	n = 0
-	for (key, val, sub) in tokens:
-		if key == 'Particle':
-			parseParticle(particles[n], val, sub)
-			n += 1
-		else:
-			for par in particles:
-				defaultKey(key, val, sub, 'par', [], globals(), locals())
-	bpy.ops.particle.particle_edit_toggle()
-	return particles
+    particles = psys.particles
+    bpy.ops.particle.particle_edit_toggle()
+    n = 0
+    for (key, val, sub) in tokens:
+        if key == 'Particle':
+            parseParticle(particles[n], val, sub)
+            n += 1
+        else:
+            for par in particles:
+                defaultKey(key, val, sub, 'par', [], globals(), locals())
+    bpy.ops.particle.particle_edit_toggle()
+    return particles
 
 def parseParticle(par, args, tokens):
-	n = 0
-	for (key, val, sub) in tokens:
-		if key == 'h':
-			h = par.hair[n]
-			h.location = eval(val[0])
-			h.time = int(val[1])
-			h.weight = float(val[2])
-			n += 1
-		elif key == 'location':
-			par.location = eval(val[0])
-	return
+    n = 0
+    for (key, val, sub) in tokens:
+        if key == 'h':
+            h = par.hair[n]
+            h.location = eval(val[0])
+            h.time = int(val[1])
+            h.weight = float(val[2])
+            n += 1
+        elif key == 'location':
+            par.location = eval(val[0])
+    return
 
 #
-#	unpackList(list_of_tuples):
+#    unpackList(list_of_tuples):
 #
 
 def unpackList(list_of_tuples):
-	l = []
-	for t in list_of_tuples:
-		l.extend(t)
-	return l
+    l = []
+    for t in list_of_tuples:
+        l.extend(t)
+    return l
 
 
 #
 
-#	parseMesh (args, tokens):
+#    parseMesh (args, tokens):
 #
 
 def parseMesh (args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing mesh %s" % args )
-
-	mename = args[0]
-	obname = args[1]
-	me = bpy.data.meshes.new(mename)
-	ob = createObject('MESH', obname, me, mename)
-
-	verts = []
-	edges = []
-	faces = []
-	vertsTex = []
-	texFaces = []
-
-	for (key, val, sub) in tokens:
-		if key == 'Verts':
-			verts = parseVerts(sub)
-		elif key == 'Edges':
-			edges = parseEdges(sub)
-		elif key == 'Faces':
-			faces = parseFaces(sub)
-
-	if faces:
-		me.from_pydata(verts, [], faces)
-	else:
-		me.from_pydata(verts, edges, [])
-	me.update()
-	linkObject(ob, me)
-		
-	mats = []
-	for (key, val, sub) in tokens:
-		if key == 'Verts' or key == 'Edges' or key == 'Faces':
-			pass
-		elif key == 'MeshTextureFaceLayer':
-			parseUvTexture(val, sub, me)
-		elif key == 'MeshColorLayer':
-			parseVertColorLayer(val, sub, me)
-		elif key == 'VertexGroup':
-			parseVertexGroup(ob, me, val, sub)
-		elif key == 'ShapeKeys':
-			parseShapeKeys(ob, me, val, sub)
-		elif key == 'Material':
-			try:				
-				mat = loadedData['Material'][val[0]]
-			except:
-				mat = None
-			if mat:
-				me.materials.append(mat)
-		else:
-			defaultKey(key, val,  sub, "me", [], globals(), locals())
-
-	for (key, val, sub) in tokens:
-		if key == 'Faces':
-			parseFaces2(sub, me)
-
-	for n,mat in enumerate(list(me.materials)):
-		print(n, mat)
-	return me
-
-#
-#	parseVerts(tokens):
-#	parseEdges(tokens):
-#	parseFaces(tokens):
-#	parseFaces2(tokens, me):		
+    global todo
+    if verbosity > 2:
+        print( "Parsing mesh %s" % args )
+
+    mename = args[0]
+    obname = args[1]
+    me = bpy.data.meshes.new(mename)
+    ob = createObject('MESH', obname, me, mename)
+
+    verts = []
+    edges = []
+    faces = []
+    vertsTex = []
+    texFaces = []
+
+    for (key, val, sub) in tokens:
+        if key == 'Verts':
+            verts = parseVerts(sub)
+        elif key == 'Edges':
+            edges = parseEdges(sub)
+        elif key == 'Faces':
+            faces = parseFaces(sub)
+
+    if faces:
+        me.from_pydata(verts, [], faces)
+    else:
+        me.from_pydata(verts, edges, [])
+    me.update()
+    linkObject(ob, me)
+        
+    mats = []
+    for (key, val, sub) in tokens:
+        if key == 'Verts' or key == 'Edges' or key == 'Faces':
+            pass
+        elif key == 'MeshTextureFaceLayer':
+            parseUvTexture(val, sub, me)
+        elif key == 'MeshColorLayer':
+            parseVertColorLayer(val, sub, me)
+        elif key == 'VertexGroup':
+            parseVertexGroup(ob, me, val, sub)
+        elif key == 'ShapeKeys':
+            parseShapeKeys(ob, me, val, sub)
+        elif key == 'Material':
+            try:                
+                mat = loadedData['Material'][val[0]]
+            except:
+                mat = None
+            if mat:
+                me.materials.append(mat)
+        else:
+            defaultKey(key, val,  sub, "me", [], globals(), locals())
+
+    for (key, val, sub) in tokens:
+        if key == 'Faces':
+            parseFaces2(sub, me)
+
+    for n,mat in enumerate(list(me.materials)):
+        print(n, mat)
+    return me
+
+#
+#    parseVerts(tokens):
+#    parseEdges(tokens):
+#    parseFaces(tokens):
+#    parseFaces2(tokens, me):        
 #
 
 def parseVerts(tokens):
-	verts = []
-	for (key, val, sub) in tokens:
-		if key == 'v':
-			verts.append( (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2])) )
-	return verts
+    verts = []
+    for (key, val, sub) in tokens:
+        if key == 'v':
+            verts.append( (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2])) )
+    return verts
 
 def parseEdges(tokens):
-	edges = []
-	for (key, val, sub) in tokens:
-		if key == 'e':
-			edges.append((int(val[0]), int(val[1])))
-	return edges
-	
-def parseFaces(tokens):	
-	faces = []
-	for (key, val, sub) in tokens:
-		if key == 'f':
-			if len(val) == 3:
-				face = [int(val[0]), int(val[1]), int(val[2])]
-			elif len(val) == 4:
-				face = [int(val[0]), int(val[1]), int(val[2]), int(val[3])]
-			faces.append(face)
-	return faces
-
-def parseFaces2(tokens, me):	
-	n = 0
-	for (key, val, sub) in tokens:
-		if key == 'ft':
-			f = me.faces[n]
-			f.material_index = int(val[0])
-			f.use_smooth = int(val[1])
-			n += 1
-		elif key == 'mn':
-			fn = int(val[0])
-			mn = int(val[1])
-			f = me.faces[fn]
-			f.material_index = mn
-		elif key == 'ftall':
-			mat = int(val[0])
-			smooth = int(val[1])
-			for f in me.faces:
-				f.material_index = mat
-				f.use_smooth = smooth
-	return
-
-
-#
-#	parseUvTexture(args, tokens, me):
-#	parseUvTexData(args, tokens, uvdata):
+    edges = []
+    for (key, val, sub) in tokens:
+        if key == 'e':
+            edges.append((int(val[0]), int(val[1])))
+    return edges
+    
+def parseFaces(tokens):    
+    faces = []
+    for (key, val, sub) in tokens:
+        if key == 'f':
+            if len(val) == 3:
+                face = [int(val[0]), int(val[1]), int(val[2])]
+            elif len(val) == 4:
+                face = [int(val[0]), int(val[1]), int(val[2]), int(val[3])]
+            faces.append(face)
+    return faces
+
+def parseFaces2(tokens, me):    
+    n = 0
+    for (key, val, sub) in tokens:
+        if key == 'ft':
+            f = me.faces[n]
+            f.material_index = int(val[0])
+            f.use_smooth = int(val[1])
+            n += 1
+        elif key == 'mn':
+            fn = int(val[0])
+            mn = int(val[1])
+            f = me.faces[fn]
+            f.material_index = mn
+        elif key == 'ftall':
+            mat = int(val[0])
+            smooth = int(val[1])
+            for f in me.faces:
+                f.material_index = mat
+                f.use_smooth = smooth
+    return
+
+
+#
+#    parseUvTexture(args, tokens, me):
+#    parseUvTexData(args, tokens, uvdata):
 #
 
 def parseUvTexture(args, tokens, me):
-	name = args[0]
-	me.uv_textures.new(name = name)
-	uvtex = me.uv_textures[-1]
-	loadedData['MeshTextureFaceLayer'][name] = uvtex
-	for (key, val, sub) in tokens:
-		if key == 'Data':
-			parseUvTexData(val, sub, uvtex.data)
-		else:
-			defaultKey(key, val,  sub, "uvtex", [], globals(), locals())
-	return
+    name = args[0]
+    me.uv_textures.new(name = name)
+    uvtex = me.uv_textures[-1]
+    loadedData['MeshTextureFaceLayer'][name] = uvtex
+    for (key, val, sub) in tokens:
+        if key == 'Data':
+            parseUvTexData(val, sub, uvtex.data)
+        else:
+            defaultKey(key, val,  sub, "uvtex", [], globals(), locals())
+    return
 
 def parseUvTexData(args, tokens, data):
-	n = 0
-	for (key, val, sub) in tokens:
-		if key == 'vt':
-			data[n].uv1 = (float(val[0]), float(val[1]))
-			data[n].uv2 = (float(val[2]), float(val[3]))
-			data[n].uv3 = (float(val[4]), float(val[5]))
-			if len(val) > 6:
-				data[n].uv4 = (float(val[6]), float(val[7]))
-			n += 1	
-		else:
-			pass
-			#for i in range(n):
-			#	defaultKey(key, val,  sub, "data[i]", [], globals(), locals())
-	return
-
-#
-#	parseVertColorLayer(args, tokens, me):
-#	parseVertColorData(args, tokens, data):
+    n = 0
+    for (key, val, sub) in tokens:
+        if key == 'vt':
+            data[n].uv1 = (float(val[0]), float(val[1]))
+            data[n].uv2 = (float(val[2]), float(val[3]))
+            data[n].uv3 = (float(val[4]), float(val[5]))
+            if len(val) > 6:
+                data[n].uv4 = (float(val[6]), float(val[7]))
+            n += 1    
+        else:
+            pass
+            #for i in range(n):
+            #    defaultKey(key, val,  sub, "data[i]", [], globals(), locals())
+    return
+
+#
+#    parseVertColorLayer(args, tokens, me):
+#    parseVertColorData(args, tokens, data):
 #
 
 def parseVertColorLayer(args, tokens, me):
-	name = args[0]
-	print("VertColorLayer", name)
-	vcol = me.vertex_colors.new(name)
-	#vcol.name = name
-	loadedData['MeshColorLayer'][name] = vcol
-	for (key, val, sub) in tokens:
-		if key == 'Data':
-			parseVertColorData(val, sub, vcol.data)
-		else:
-			defaultKey(key, val,  sub, "vcol", [], globals(), locals())
-	return
+    name = args[0]
+    print("VertColorLayer", name)
+    vcol = me.vertex_colors.new(name)
+    loadedData['MeshColorLayer'][name] = vcol
+    for (key, val, sub) in tokens:
+        if key == 'Data':
+            parseVertColorData(val, sub, vcol.data)
+        else:
+            defaultKey(key, val,  sub, "vcol", [], globals(), locals())
+    return
 
 def parseVertColorData(args, tokens, data):
-	n = 0
-	for (key, val, sub) in tokens:
-		if key == 'cv':
-			data[n].color1 = eval(val[0])
-			data[n].color2 = eval(val[1])
-			data[n].color3 = eval(val[2])
-			data[n].color4 = eval(val[3])
-			n += 1	
-	return
+    n = 0
+    for (key, val, sub) in tokens:
+        if key == 'cv':
+            data[n].color1 = eval(val[0])
+            data[n].color2 = eval(val[1])
+            data[n].color3 = eval(val[2])
+            data[n].color4 = eval(val[3])
+            n += 1    
+    return
 
 
 #
-#	parseVertexGroup(ob, me, args, tokens):
+#    parseVertexGroup(ob, me, args, tokens):
 #
 
 def parseVertexGroup(ob, me, args, tokens):
-	global toggle
-	if verbosity > 2:
-		print( "Parsing vertgroup %s" % args )
-	grpName = args[0]
-	try:
-		res = eval(args[1])
-	except:
-		res = True
-	if not res:
-		return
-
-	if (toggle & T_Armature) or (grpName in ['Eye_L', 'Eye_R', 'Gums', 'Head', 'Jaw', 'Left', 'Middle', 'Right', 'Scalp']):
-		group = ob.vertex_groups.new(grpName)
-		loadedData['VertexGroup'][grpName] = group
-		for (key, val, sub) in tokens:
-			if key == 'wv':
-				ob.vertex_groups.assign( [int(val[0])], group, float(val[1]), 'REPLACE' )
-				#ob.add_vertex_to_group( int(val[0]), group, float(val[1]), 'REPLACE')
-	return
-
-
-#
-#	parseShapeKeys(ob, me, args, tokens):
-#	parseShapeKey(ob, me, args, tokens):
-#	addShapeKey(ob, name, vgroup, tokens):
-#	doShape(name):
+    global toggle
+    if verbosity > 2:
+        print( "Parsing vertgroup %s" % args )
+    grpName = args[0]
+    try:
+        res = eval(args[1])
+    except:
+        res = True
+    if not res:
+        return
+
+    if (toggle & T_Armature) or (grpName in ['Eye_L', 'Eye_R', 'Gums', 'Head', 'Jaw', 'Left', 'Middle', 'Right', 'Scalp']):
+        group = ob.vertex_groups.new(grpName)
+        loadedData['VertexGroup'][grpName] = group
+        for (key, val, sub) in tokens:
+            if key == 'wv':
+                ob.vertex_groups.assign( [int(val[0])], group, float(val[1]), 'REPLACE' )
+    return
+
+
+#
+#    parseShapeKeys(ob, me, args, tokens):
+#    parseShapeKey(ob, me, args, tokens):
+#    addShapeKey(ob, name, vgroup, tokens):
+#    doShape(name):
 #
 
 def doShape(name):
-	if (toggle & T_Shape+T_Face) and (name == 'Basis'):
-		return True
-	else:
-		return (toggle & T_Face)
+    if (toggle & T_Shape+T_Face) and (name == 'Basis'):
+        return True
+    else:
+        return (toggle & T_Face)
 
 def parseShapeKeys(ob, me, args, tokens):
-	if bpy.context.object == None:
-		return
-	for (key, val, sub) in tokens:
-		if key == 'ShapeKey':
-			parseShapeKey(ob, me, val, sub)
-		elif key == 'AnimationData':
-			if me.shape_keys:
-				parseAnimationData(me.shape_keys, val, sub)
-	ob.active_shape_key_index = 0
-	return
+    for (key, val, sub) in tokens:
+        if key == 'ShapeKey':
+            parseShapeKey(ob, me, val, sub)
+        elif key == 'AnimationData':
+            if me.shape_keys:
+                parseAnimationData(me.shape_keys, val, sub)
+    ob.active_shape_key_index = 0
+    return
 
 
 def parseShapeKey(ob, me, args, tokens):
-	if verbosity > 0:
-		print( "Parsing ob %s shape %s" % (bpy.context.object, args[0] ))
-	name = args[0]
-	lr = args[1]
-	if invalid(args[2]):
-		return
-
-	if lr == 'Sym' or toggle & T_Symm:
-		addShapeKey(ob, name, None, tokens)
-	elif lr == 'LR':
-		addShapeKey(ob, name+'_L', 'Left', tokens)
-		addShapeKey(ob, name+'_R', 'Right', tokens)
-	else:
-		raise NameError("ShapeKey L/R %s" % lr)
-	return
+    if verbosity > 2:
+        print( "Parsing ob %s shape %s" % (bpy.context.object, args[0] ))
+    name = args[0]
+    lr = args[1]
+    if invalid(args[2]):
+        return
+
+    if lr == 'Sym' or toggle & T_Symm:
+        addShapeKey(ob, name, None, tokens)
+    elif lr == 'LR':
+        addShapeKey(ob, name+'_L', 'Left', tokens)
+        addShapeKey(ob, name+'_R', 'Right', tokens)
+    else:
+        raise NameError("ShapeKey L/R %s" % lr)
+    return
 
 def addShapeKey(ob, name, vgroup, tokens):
-	bpy.ops.object.shape_key_add(False)
-	skey = ob.active_shape_key
-	if name != 'Basis':
-		skey.relative_key = loadedData['ShapeKey']['Basis']
-	skey.name = name
-	if vgroup:
-		skey.vertex_group = vgroup
-	loadedData['ShapeKey'][name] = skey
+    skey = ob.shape_key_add(name=name, from_mix=False)
+    if name != 'Basis':
+        skey.relative_key = loadedData['ShapeKey']['Basis']
+    skey.name = name
+    if vgroup:
+        skey.vertex_group = vgroup
+    loadedData['ShapeKey'][name] = skey
 
-	for (key, val, sub) in tokens:
-		if key == 'sv':
-			index = int(val[0])
-			pt = skey.data[index].co
-			pt[0] += theScale*float(val[1])
-			pt[1] += theScale*float(val[2])
-			pt[2] += theScale*float(val[3])
-		else:
-			defaultKey(key, val,  sub, "skey", [], globals(), locals())
+    for (key, val, sub) in tokens:
+        if key == 'sv':
+            index = int(val[0])
+            pt = skey.data[index].co
+            pt[0] += theScale*float(val[1])
+            pt[1] += theScale*float(val[2])
+            pt[2] += theScale*float(val[3])
+        else:
+            defaultKey(key, val,  sub, "skey", [], globals(), locals())
 
-	return	
+    return    
 
-	
+    
 #
-#	parseArmature (obName, args, tokens)
+#    parseArmature (obName, args, tokens)
 #
 
 def parseArmature (args, tokens):
-	global toggle
-	if verbosity > 2:
-		print( "Parsing armature %s" % args )
-	
-	amtname = args[0]
-	obname = args[1]
-	mode = args[2]
-	
-	if mode == 'Rigify':
-		toggle |= T_Rigify
-		return parseRigify(amtname, obname, tokens)
-
-	toggle &= ~T_Rigify
-	amt = bpy.data.armatures.new(amtname)
-	ob = createObject('ARMATURE', obname, amt, amtname)	
-
-	linkObject(ob, amt)
-	print("Linked")
-
-	bpy.ops.object.mode_set(mode='OBJECT')
-	bpy.ops.object.mode_set(mode='EDIT')
-
-	heads = {}
-	tails = {}
-	for (key, val, sub) in tokens:
-		if key == 'Bone':
-			bname = val[0]
-			if not invalid(val[1]):
-				bone = amt.edit_bones.new(bname)
-				parseBone(bone, amt, sub, heads, tails)
-				loadedData['Bone'][bname] = bone
-		else:
-			defaultKey(key, val,  sub, "amt", ['MetaRig'], globals(), locals())
-	bpy.ops.object.mode_set(mode='OBJECT')
-	return amt
-
-#
-#	parseRigify(amtname, obname, tokens):		
-#
-
-def parseRigify(amtname, obname, tokens):		
-	(key,val,sub) = tokens[0]
-	if key != 'MetaRig':
-		raise NameError("Expected MetaRig")
-	typ = val[0]
-	if typ == "human":
-		bpy.ops.object.armature_human_advanced_add()
-	else:
-		bpy.ops.pose.metarig_sample_add(type = typ)
-	ob = bpy.context.scene.objects.active
-	amt = ob.data
-	loadedData['Rigify'][obname] = ob
-	loadedData['Armature'][amtname] = amt
-	loadedData['Object'][obname] = ob
-	print("Rigify object", ob, amt)
-
-	bpy.ops.object.mode_set(mode='OBJECT')
-	bpy.ops.object.mode_set(mode='EDIT')
-
-	heads = {}
-	tails = {}
-	for (bname, bone) in amt.edit_bones.items():
-		heads[bname] = 10*theScale*bone.head
-		tails[bname] = 10*theScale*bone.tail
-
-	for (key, val, sub) in tokens:
-		if key == 'Bone':
-			bname = val[0]
-			print("Bone", bname)
-			try:
-				bone = amt.edit_bones[bname]
-			except:
-				print("Did not find bone %s" % bname)
-				bone = None
-			print(" -> ", bone)
-			if bone:
-				parseBone(bone, amt, sub, heads, tails)
-		else:
-			defaultKey(key, val,  sub, "amt", ['MetaRig'], globals(), locals())
-	bpy.ops.object.mode_set(mode='OBJECT')
-	return amt
-		
-#
-#	parseBone(bone, amt, tokens, heads, tails):
+    global toggle
+    if verbosity > 2:
+        print( "Parsing armature %s" % args )
+    
+    amtname = args[0]
+    obname = args[1]
+    mode = args[2]
+    
+    if mode == 'Rigify':
+        toggle |= T_Rigify
+        return parseRigify(amtname, obname, tokens)
+
+    toggle &= ~T_Rigify
+    amt = bpy.data.armatures.new(amtname)
+    ob = createObject('ARMATURE', obname, amt, amtname)    
+
+    linkObject(ob, amt)
+    print("Linked")
+
+    bpy.ops.object.mode_set(mode='OBJECT')
+    bpy.ops.object.mode_set(mode='EDIT')
+
+    heads = {}
+    tails = {}
+    for (key, val, sub) in tokens:
+        if key == 'Bone':
+            bname = val[0]
+            if not invalid(val[1]):
+                bone = amt.edit_bones.new(bname)
+                parseBone(bone, amt, sub, heads, tails)
+                loadedData['Bone'][bname] = bone
+        else:
+            defaultKey(key, val,  sub, "amt", ['MetaRig'], globals(), locals())
+    bpy.ops.object.mode_set(mode='OBJECT')
+    return amt
+
+#
+#    parseRigify(amtname, obname, tokens):        
+#
+
+def parseRigify(amtname, obname, tokens):        
+    (key,val,sub) = tokens[0]
+    if key != 'MetaRig':
+        raise NameError("Expected MetaRig")
+    typ = val[0]
+    if typ == "human":
+        bpy.ops.object.armature_human_advanced_add()
+    else:
+        bpy.ops.pose.metarig_sample_add(type = typ)
+    ob = bpy.context.scene.objects.active
+    amt = ob.data
+    loadedData['Rigify'][obname] = ob
+    loadedData['Armature'][amtname] = amt
+    loadedData['Object'][obname] = ob
+    print("Rigify object", ob, amt)
+
+    bpy.ops.object.mode_set(mode='OBJECT')
+    bpy.ops.object.mode_set(mode='EDIT')
+
+    heads = {}
+    tails = {}
+    for (bname, bone) in amt.edit_bones.items():
+        heads[bname] = 10*theScale*bone.head
+        tails[bname] = 10*theScale*bone.tail
+
+    for (key, val, sub) in tokens:
+        if key == 'Bone':
+            bname = val[0]
+            print("Bone", bname)
+            try:
+                bone = amt.edit_bones[bname]
+            except:
+                print("Did not find bone %s" % bname)
+                bone = None
+            print(" -> ", bone)
+            if bone:
+                parseBone(bone, amt, sub, heads, tails)
+        else:
+            defaultKey(key, val,  sub, "amt", ['MetaRig'], globals(), locals())
+    bpy.ops.object.mode_set(mode='OBJECT')
+    return amt
+        
+#
+#    parseBone(bone, amt, tokens, heads, tails):
 #
 
 def parseBone(bone, amt, tokens, heads, tails):
-	global todo
+    global todo
 
-	for (key, val, sub) in tokens:
-		if key == "head":
-			bone.head = (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2]))
-		elif key == "tail":
-			bone.tail = (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2]))
-		#elif key == 'restrict_select':
-		#	pass
-		elif key == 'hide' and val[0] == 'True':
-			name = bone.name
-			'''
-			#bpy.ops.object.mode_set(mode='OBJECT')
-			pbone = amt.bones[name]
-			pbone.hide = True
-			print("Hide", pbone, pbone.hide)
-			#bpy.ops.object.mode_set(mode='EDIT')			
-			'''
-		else:
-			defaultKey(key, val,  sub, "bone", [], globals(), locals())
+    for (key, val, sub) in tokens:
+        if key == "head":
+            bone.head = (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2]))
+        elif key == "tail":
+            bone.tail = (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2]))
+        #elif key == 'restrict_select':
+        #    pass
+        elif key == 'hide' and val[0] == 'True':
+            name = bone.name
+            '''
+            #bpy.ops.object.mode_set(mode='OBJECT')
+            pbone = amt.bones[name]
+            pbone.hide = True
+            print("Hide", pbone, pbone.hide)
+            #bpy.ops.object.mode_set(mode='EDIT')            
+            '''
+        else:
+            defaultKey(key, val,  sub, "bone", [], globals(), locals())
 
-	return bone
+    return bone
 
 #
-#	parsePose (args, tokens):
+#    parsePose (args, tokens):
 #
 
 def parsePose (args, tokens):
-	global todo
-	if toggle & T_Rigify:
-		return
-	name = args[0]
-	ob = loadedData['Object'][name]
-	bpy.context.scene.objects.active = ob
-	bpy.ops.object.mode_set(mode='POSE')
-	pbones = ob.pose.bones	
-	nGrps = 0
-	for (key, val, sub) in tokens:
-		if key == 'Posebone':
-			parsePoseBone(pbones, ob, val, sub)
-		elif key == 'BoneGroup':
-			parseBoneGroup(ob.pose, nGrps, val, sub)
-			nGrps += 1
-		elif key == 'SetProp':
-			bone = val[0]
-			prop = val[1]
-			value = eval(val[2])
-			pb = pbones[bone]
-			print("Setting", pb, prop, val)
-			pb[prop] = value
-			print("Prop set", pb[prop])
-		else:
-			defaultKey(key, val,  sub, "ob.pose", [], globals(), locals())
-	bpy.ops.object.mode_set(mode='OBJECT')
-	return ob
-
-
-#
-#	parsePoseBone(pbones, args, tokens):
-#	parseArray(data, exts, args):
+    global todo
+    if toggle & T_Rigify:
+        return
+    name = args[0]
+    ob = loadedData['Object'][name]
+    bpy.context.scene.objects.active = ob
+    bpy.ops.object.mode_set(mode='POSE')
+    pbones = ob.pose.bones    
+    nGrps = 0
+    for (key, val, sub) in tokens:
+        if key == 'Posebone':
+            parsePoseBone(pbones, ob, val, sub)
+        elif key == 'BoneGroup':
+            parseBoneGroup(ob.pose, nGrps, val, sub)
+            nGrps += 1
+        elif key == 'SetProp':
+            bone = val[0]
+            prop = val[1]
+            value = eval(val[2])
+            pb = pbones[bone]
+            print("Setting", pb, prop, val)
+            pb[prop] = value
+            print("Prop set", pb[prop])
+        else:
+            defaultKey(key, val,  sub, "ob.pose", [], globals(), locals())
+    bpy.ops.object.mode_set(mode='OBJECT')
+    return ob
+
+
+#
+#    parsePoseBone(pbones, args, tokens):
+#    parseArray(data, exts, args):
 #
 
 def parseBoneGroup(pose, nGrps, args, tokens):
-	global todo
-	print( "Parsing bonegroup %s" % args )
-	name = args[0]
-	bpy.ops.pose.group_add()
-	print(dir(pose.bone_groups))
-	bg = pose.bone_groups.active
-	print("Created", bg)
-	loadedData['BoneGroup'][name] = bg
-	for (key, val, sub) in tokens:
-		print(key,val)
-		defaultKey(key, val,  sub, "bg", [], globals(), locals())
-	return
+    global todo
+    print( "Parsing bonegroup %s" % args )
+    name = args[0]
+    bpy.ops.pose.group_add()
+    print(dir(pose.bone_groups))
+    bg = pose.bone_groups.active
+    print("Created", bg)
+    loadedData['BoneGroup'][name] = bg
+    for (key, val, sub) in tokens:
+        defaultKey(key, val,  sub, "bg", [], globals(), locals())
+    return
 
 def parsePoseBone(pbones, ob, args, tokens):
-	global todo
-	if invalid(args[1]):
-		return
-	name = args[0]
-	pb = pbones[name]
-	amt = ob.data
-
-	# Make posebone active - don't know how to do this in pose mode
-	bpy.ops.object.mode_set(mode='OBJECT')
-	amt.bones.active = amt.bones[name]
-	bpy.ops.object.mode_set(mode='POSE')
-
-	for (key, val, sub) in tokens:
-		if key == 'Constraint':
-			cns = parseConstraint(pb.constraints, val, sub)
-		elif key == 'bpyops':
-			bpy.ops.object.mode_set(mode='OBJECT')
-			amt.bones.active = amt.bones[name]
-			ob.constraints.active = cns			
-			expr = "bpy.ops.%s" % val[0]
-			# print(expr)
-			exec(expr)
-			bpy.ops.object.mode_set(mode='POSE')
-		elif key == 'ik_dof':
-			parseArray(pb, ["ik_dof_x", "ik_dof_y", "ik_dof_z"], val)
-		elif key == 'ik_limit':
-			parseArray(pb, ["ik_limit_x", "ik_limit_y", "ik_limit_z"], val)
-		elif key == 'ik_max':
-			parseArray(pb, ["ik_max_x", "ik_max_y", "ik_max_z"], val)
-		elif key == 'ik_min':
-			parseArray(pb, ["ik_min_x", "ik_min_y", "ik_min_z"], val)
-		elif key == 'ik_stiffness':
-			parseArray(pb, ["ik_stiffness_x", "ik_stiffness_y", "ik_stiffness_z"], val)
-		elif key == 'hide':
-			#bpy.ops.object.mode_set(mode='OBJECT')
-			amt.bones[name].hide = eval(val[0])
-			#bpy.ops.object.mode_set(mode='POSE')
-			
-		else:
-			defaultKey(key, val,  sub, "pb", [], globals(), locals())
-	#print("pb %s done" % name)
-	return
+    global todo
+    if invalid(args[1]):
+        return
+    name = args[0]
+    pb = pbones[name]
+    amt = ob.data
+
+    # Make posebone active - don't know how to do this in pose mode
+    bpy.ops.object.mode_set(mode='OBJECT')
+    amt.bones.active = amt.bones[name]
+    bpy.ops.object.mode_set(mode='POSE')
+
+    for (key, val, sub) in tokens:
+        if key == 'Constraint':
+            cns = parseConstraint(pb.constraints, val, sub)
+        elif key == 'bpyops':
+            bpy.ops.object.mode_set(mode='OBJECT')
+            amt.bones.active = amt.bones[name]
+            ob.constraints.active = cns            
+            expr = "bpy.ops.%s" % val[0]
+            # print(expr)
+            exec(expr)
+            bpy.ops.object.mode_set(mode='POSE')
+        elif key == 'ik_dof':
+            parseArray(pb, ["ik_dof_x", "ik_dof_y", "ik_dof_z"], val)
+        elif key == 'ik_limit':
+            parseArray(pb, ["ik_limit_x", "ik_limit_y", "ik_limit_z"], val)
+        elif key == 'ik_max':
+            parseArray(pb, ["ik_max_x", "ik_max_y", "ik_max_z"], val)
+        elif key == 'ik_min':
+            parseArray(pb, ["ik_min_x", "ik_min_y", "ik_min_z"], val)
+        elif key == 'ik_stiffness':
+            parseArray(pb, ["ik_stiffness_x", "ik_stiffness_y", "ik_stiffness_z"], val)
+        elif key == 'hide':
+            #bpy.ops.object.mode_set(mode='OBJECT')
+            amt.bones[name].hide = eval(val[0])
+            #bpy.ops.object.mode_set(mode='POSE')
+            
+        else:
+            defaultKey(key, val,  sub, "pb", [], globals(), locals())
+    #print("pb %s done" % name)
+    return
 
 def parseArray(data, exts, args):
-	n = 1
-	for ext in exts:
-		expr = "data.%s = %s" % (ext, args[n])
-		# print(expr)
-		exec(expr)
-		n += 1
-	return
-		
+    n = 1
+    for ext in exts:
+        expr = "data.%s = %s" % (ext, args[n])
+        # print(expr)
+        exec(expr)
+        n += 1
+    return
+        
 #
-#	parseConstraint(constraints, args, tokens)
+#    parseConstraint(constraints, args, tokens)
 #
 
 def parseConstraint(constraints, args, tokens):
-	if invalid(args[2]):
-		return None
-	cns = constraints.new(args[1])
-	#bpy.ops.pose.constraint_add(type=args[1])
-	#cns = pb.constraints[-1]
+    if invalid(args[2]):
+        return None
+    cns = constraints.new(args[1])
+    #bpy.ops.pose.constraint_add(type=args[1])
+    #cns = pb.constraints[-1]
 
-	cns.name = args[0]
-	#print("cns", cns.name)
-	for (key,val,sub) in tokens:
-		if key == 'invert':
-			parseArray(cns, ["invert_x", "invert_y", "invert_z"], val)
-		elif key == 'use':
-			parseArray(cns, ["use_x", "use_y", "use_z"], val)
-		elif key == 'pos_lock':
-			parseArray(cns, ["lock_location_x", "lock_location_y", "lock_location_z"], val)
-		elif key == 'rot_lock':
-			parseArray(cns, ["lock_rotation_x", "lock_rotation_y", "lock_rotation_z"], val)
-		else:
-			defaultKey(key, val,  sub, "cns", [], globals(), locals())
+    cns.name = args[0]
+    #print("cns", cns.name)
+    for (key,val,sub) in tokens:
+        if key == 'invert':
+            parseArray(cns, ["invert_x", "invert_y", "invert_z"], val)
+        elif key == 'use':
+            parseArray(cns, ["use_x", "use_y", "use_z"], val)
+        elif key == 'pos_lock':
+            parseArray(cns, ["lock_location_x", "lock_location_y", "lock_location_z"], val)
+        elif key == 'rot_lock':
+            parseArray(cns, ["lock_rotation_x", "lock_rotation_y", "lock_rotation_z"], val)
+        else:
+            defaultKey(key, val,  sub, "cns", [], globals(), locals())
 
 
-	#print("cns %s done" % cns.name)
-	return cns
+    #print("cns %s done" % cns.name)
+    return cns
 
 #
 
 
-#	parseCurve (args, tokens):
-#	parseSpline(cu, args, tokens):
-#	parseBezier(spline, n, args, tokens):
+#    parseCurve (args, tokens):
+#    parseSpline(cu, args, tokens):
+#    parseBezier(spline, n, args, tokens):
 #
 
 def parseCurve (args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing curve %s" % args )
-	bpy.ops.object.add(type='CURVE')
-	cu = setObjectAndData(args, 'Curve')
-
-	for (key, val, sub) in tokens:
-		if key == 'Spline':
-			parseSpline(cu, val, sub)
-		else:
-			defaultKey(key, val, sub, "cu", [], globals(), locals())
-	return
+    global todo
+    if verbosity > 2:
+        print( "Parsing curve %s" % args )
+    bpy.ops.object.add(type='CURVE')
+    cu = setObjectAndData(args, 'Curve')
+
+    for (key, val, sub) in tokens:
+        if key == 'Spline':
+            parseSpline(cu, val, sub)
+        else:
+            defaultKey(key, val, sub, "cu", [], globals(), locals())
+    return
 
 def parseTextCurve (args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing text curve %s" % args )
-	bpy.ops.object.text_add()
-	txt = setObjectAndData(args, 'Text')
-
-	for (key, val, sub) in tokens:
-		if key == 'Spline':
-			parseSpline(txt, val, sub)
-		elif key == 'BodyFormat':
-			parseCollection(txt.body_format, sub, [])
-		elif key == 'EditFormat':
-			parseDefault(txt.edit_format, sub, {}, [])
-		elif key == 'Font':
-			parseDefault(txt.font, sub, {}, [])
-		elif key == 'TextBox':
-			parseCollection(txt.body_format, sub, [])
-		else:
-			defaultKey(key, val, sub, "txt", [], globals(), locals())
-	return
+    global todo
+    if verbosity > 2:
+        print( "Parsing text curve %s" % args )
+    bpy.ops.object.text_add()
+    txt = setObjectAndData(args, 'Text')
+
+    for (key, val, sub) in tokens:
+        if key == 'Spline':
+            parseSpline(txt, val, sub)
+        elif key == 'BodyFormat':
+            parseCollection(txt.body_format, sub, [])
+        elif key == 'EditFormat':
+            parseDefault(txt.edit_format, sub, {}, [])
+        elif key == 'Font':
+            parseDefault(txt.font, sub, {}, [])
+        elif key == 'TextBox':
+            parseCollection(txt.body_format, sub, [])
+        else:
+            defaultKey(key, val, sub, "txt", [], globals(), locals())
+    return
 
 
 def parseSpline(cu, args, tokens):
-	typ = args[0]
-	spline = cu.splines.new(typ)
-	nPointsU = int(args[1])
-	nPointsV = int(args[2])
-	#spline.point_count_u = nPointsU
-	#spline.point_count_v = nPointsV
-	if typ == 'BEZIER' or typ == 'BSPLINE':
-		spline.bezier_points.add(nPointsU)
-	else:
-		spline.points.add(nPointsU)
-
-	n = 0
-	for (key, val, sub) in tokens:
-		if key == 'bz':
-			parseBezier(spline.bezier_points[n], val, sub)
-			n += 1
-		elif key == 'pt':
-			parsePoint(spline.points[n], val, sub)
-			n += 1
-		else:
-			defaultKey(key, val, sub, "spline", [], globals(), locals())
-	return
-	
+    typ = args[0]
+    spline = cu.splines.new(typ)
+    nPointsU = int(args[1])
+    nPointsV = int(args[2])
+    #spline.point_count_u = nPointsU
+    #spline.point_count_v = nPointsV
+    if typ == 'BEZIER' or typ == 'BSPLINE':
+        spline.bezier_points.add(nPointsU)
+    else:
+        spline.points.add(nPointsU)
+
+    n = 0
+    for (key, val, sub) in tokens:
+        if key == 'bz':
+            parseBezier(spline.bezier_points[n], val, sub)
+            n += 1
+        elif key == 'pt':
+            parsePoint(spline.points[n], val, sub)
+            n += 1
+        else:
+            defaultKey(key, val, sub, "spline", [], globals(), locals())
+    return
+    
 def parseBezier(bez, args, tokens):
-	bez.co = eval(args[0])
-	bez.co = theScale*bez.co	
-	bez.handle1 = eval(args[1])	
-	bez.handle1_type = args[2]
-	bez.handle2 = eval(args[3])	
-	bez.handle2_type = args[4]
-	return
+    bez.co = eval(args[0])
+    bez.co = theScale*bez.co    
+    bez.handle1 = eval(args[1])    
+    bez.handle1_type = args[2]
+    bez.handle2 = eval(args[3])    
+    bez.handle2_type = args[4]
+    return
 
 def parsePoint(pt, args, tokens):
-	pt.co = eval(args[0])
-	pt.co = theScale*pt.co
-	return
+    pt.co = eval(args[0])
+    pt.co = theScale*pt.co
+    return
 
 #
-#	parseLattice (args, tokens):
+#    parseLattice (args, tokens):
 #
 
 def parseLattice (args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing lattice %s" % args )
-	bpy.ops.object.add(type='LATTICE')
-	lat = setObjectAndData(args, 'Lattice')	
-	for (key, val, sub) in tokens:
-		if key == 'Points':
-			parseLatticePoints(val, sub, lat.points)
-		else:
-			defaultKey(key, val, sub, "lat", [], globals(), locals())
-	return
+    global todo
+    if verbosity > 2:
+        print( "Parsing lattice %s" % args )
+    bpy.ops.object.add(type='LATTICE')
+    lat = setObjectAndData(args, 'Lattice')    
+    for (key, val, sub) in tokens:
+        if key == 'Points':
+            parseLatticePoints(val, sub, lat.points)
+        else:
+            defaultKey(key, val, sub, "lat", [], globals(), locals())
+    return
 
 def parseLatticePoints(args, tokens, points):
-	global todo
-	n = 0
-	for (key, val, sub) in tokens:
-		if key == 'pt':
-			v = points[n].co
-			(x,y,z) = eval(val[0])
-			v.x = theScale*x
-			v.y = theScale*y
-			v.z = theScale*z
+    global todo
+    n = 0
+    for (key, val, sub) in tokens:
+        if key == 'pt':
+            v = points[n].co
+            (x,y,z) = eval(val[0])
+            v.x = theScale*x
+            v.y = theScale*y
+            v.z = theScale*z
 
-			v = points[n].deformed_co
-			(x,y,z) = eval(val[1])
-			v.x = theScale*x
-			v.y = theScale*y
-			v.z = theScale*z
+            v = points[n].deformed_co
+            (x,y,z) = eval(val[1])
+            v.x = theScale*x
+            v.y = theScale*y
+            v.z = theScale*z
 
-			n += 1
-	return
+            n += 1
+    return
 
 #
-#	parseLamp (args, tokens):
-#	parseFalloffCurve(focu, args, tokens):
+#    parseLamp (args, tokens):
+#    parseFalloffCurve(focu, args, tokens):
 #
 
 def parseLamp (args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing lamp %s" % args )
-	bpy.ops.object.add(type='LAMP')
-	lamp = setObjectAndData(args, 'Lamp')	
-	for (key, val, sub) in tokens:
-		if key == 'FalloffCurve':
-			parseFalloffCurve(lamp.falloff_curve, val, sub)
-		else:
-			defaultKey(key, val, sub, "lamp", [], globals(), locals())
-	return
+    global todo
+    if verbosity > 2:
+        print( "Parsing lamp %s" % args )
+    bpy.ops.object.add(type='LAMP')
+    lamp = setObjectAndData(args, 'Lamp')    
+    for (key, val, sub) in tokens:
+        if key == 'FalloffCurve':
+            parseFalloffCurve(lamp.falloff_curve, val, sub)
+        else:
+            defaultKey(key, val, sub, "lamp", [], globals(), locals())
+    return
 
 def parseFalloffCurve(focu, args, tokens):
-	return
+    return
 
 #
-#	parseGroup (args, tokens):
-#	parseGroupObjects(args, tokens, grp):
+#    parseGroup (args, tokens):
+#    parseGroupObjects(args, tokens, grp):
 #
 
 def parseGroup (args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing group %s" % args )
-
-	grpName = args[0]
-	grp = bpy.data.groups.new(grpName)
-	loadedData['Group'][grpName] = grp
-	for (key, val, sub) in tokens:
-		if key == 'Objects':
-			parseGroupObjects(val, sub, grp)
-		else:
-			defaultKey(key, val, sub, "grp", [], globals(), locals())
-	return
+    global todo
+    if verbosity > 2:
+        print( "Parsing group %s" % args )
+
+    grpName = args[0]
+    grp = bpy.data.groups.new(grpName)
+    loadedData['Group'][grpName] = grp
+    for (key, val, sub) in tokens:
+        if key == 'Objects':
+            parseGroupObjects(val, sub, grp)
+        else:
+            defaultKey(key, val, sub, "grp", [], globals(), locals())
+    return
 
 def parseGroupObjects(args, tokens, grp):
-	global todo
-	for (key, val, sub) in tokens:
-		if key == 'ob':
-			try:
-				ob = loadedData['Object'][val[0]]
-				grp.objects.link(ob)
-			except:
-				pass
-	return
+    global todo
+    for (key, val, sub) in tokens:
+        if key == 'ob':
+            try:
+                ob = loadedData['Object'][val[0]]
+                grp.objects.link(ob)
+            except:
+                pass
+    return
 
 #
-#	parseWorld (args, tokens):
+#    parseWorld (args, tokens):
 #
 
 def parseWorld (args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing world %s" % args )
-	world = bpy.context.scene.world
-	for (key, val, sub) in tokens:
-		if key == 'Lighting':
-			parseDefault(world.lighting, sub, {}, [])
-		elif key == 'Mist':
-			parseDefault(world.mist, sub, {}, [])
-		elif key == 'Stars':
-			parseDefault(world.stars, sub, {}, [])
-		else:
-			defaultKey(key, val, sub, "world", [], globals(), locals())
-	return
-
-#
-#	parseScene (args, tokens):
-#	parseRenderSettings(render, args, tokens):
-#	parseToolSettings(tool, args, tokens):
+    global todo
+    if verbosity > 2:
+        print( "Parsing world %s" % args )
+    world = bpy.context.scene.world
+    for (key, val, sub) in tokens:
+        if key == 'Lighting':
+            parseDefault(world.lighting, sub, {}, [])
+        elif key == 'Mist':
+            parseDefault(world.mist, sub, {}, [])
+        elif key == 'Stars':
+            parseDefault(world.stars, sub, {}, [])
+        else:
+            defaultKey(key, val, sub, "world", [], globals(), locals())
+    return
+
+#
+#    parseScene (args, tokens):
+#    parseRenderSettings(render, args, tokens):
+#    parseToolSettings(tool, args, tokens):
 #
 
 def parseScene (args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing scene %s" % args )
-	scn = bpy.context.scene
-	for (key, val, sub) in tokens:
-		if key == 'NodeTree':
-			scn.use_nodes = True
-			parseNodeTree(scn, val, sub)
-		elif key == 'GameData':
-			parseDefault(scn.game_data, sub, {}, [])
-		elif key == 'KeyingSet':
-			pass
-			#parseDefault(scn.keying_sets, sub, {}, [])
-		elif key == 'ObjectBase':
-			pass
-			#parseDefault(scn.bases, sub, {}, [])
-		elif key == 'RenderSettings':
-			parseRenderSettings(scn.render, sub, [])
-		elif key == 'ToolSettings':
-			subkeys = {'ImagePaint' : "image_paint",  
-				'Sculpt' : "sculpt",  
-				'VertexPaint' : "vertex_paint",  
-				'WeightPaint' : "weight_paint" }
-			parseDefault(scn.tool_settings, sub, subkeys, [])
-		elif key == 'UnitSettings':
-			parseDefault(scn.unit_settings, sub, {}, [])
-		else:
-			defaultKey(key, val, sub, "scn", [], globals(), locals())
-	return
+    global todo
+    if verbosity > 2:
+        print( "Parsing scene %s" % args )
+    scn = bpy.context.scene
+    for (key, val, sub) in tokens:
+        if key == 'NodeTree':
+            scn.use_nodes = True
+            parseNodeTree(scn, val, sub)
+        elif key == 'GameData':
+            parseDefault(scn.game_data, sub, {}, [])
+        elif key == 'KeyingSet':
+            pass
+            #parseDefault(scn.keying_sets, sub, {}, [])
+        elif key == 'ObjectBase':
+            pass
+            #parseDefault(scn.bases, sub, {}, [])
+        elif key == 'RenderSettings':
+            parseRenderSettings(scn.render, sub, [])
+        elif key == 'ToolSettings':
+            subkeys = {'ImagePaint' : "image_paint",  
+                'Sculpt' : "sculpt",  
+                'VertexPaint' : "vertex_paint",  
+                'WeightPaint' : "weight_paint" }
+            parseDefault(scn.tool_settings, sub, subkeys, [])
+        elif key == 'UnitSettings':
+            parseDefault(scn.unit_settings, sub, {}, [])
+        else:
+            defaultKey(key, val, sub, "scn", [], globals(), locals())
+    return
 
 def parseRenderSettings(render, args, tokens):
-	global todo
-	if verbosity > 2:
-		print( "Parsing RenderSettings %s" % args )
-	for (key, val, sub) in tokens:
-		if key == 'Layer':
-			pass
-			#parseDefault(scn.layers, sub, [])
-		else:
-			defaultKey(key, val, sub, "render", [], globals(), locals())
-	return
+    global todo
+    if verbosity > 2:
+        print( "Parsing RenderSettings %s" % args )
+    for (key, val, sub) in tokens:
+        if key == 'Layer':
+            pass
+            #parseDefault(scn.layers, sub, [])
+        else:
+            defaultKey(key, val, sub, "render", [], globals(), locals())
+    return
 
 #
-#	postProcess()
+#    postProcess()
 #
 
 def postProcess():
-	if not toggle & T_MHX:
-		return
-	try:
-		ob = loadedData['Object']['HumanMesh']
-	except:
-		ob = None
-	if toggle & T_Diamond == 0 and ob:
-		deleteDiamonds(ob)
-	if toggle & T_Rigify and False:
-		for rig in loadedData['Rigify'].values():
-			bpy.context.scene.objects.active = rig
-			print("Rigify", rig)
-			bpy.ops.pose.metarig_generate()
-			print("Metarig generated")
-			#bpy.context.scene.objects.unlink(rig)
-
-			rig = bpy.context.scene.objects.active
-			print("Rigged", rig, bpy.context.object)
-			ob = loadedData['Object']['HumanMesh']
-			mod = ob.modifiers[0]
-			print(ob, mod, mod.object)
-			mod.object = rig
-			print("Rig changed", mod.object)
-	return			
-
-#
-#	deleteDiamonds(ob)
-#	Delete joint diamonds in main mesh
+    if not toggle & T_MHX:
+        return
+    try:
+        ob = loadedData['Object']['HumanMesh']
+    except:
+        ob = None
+    if toggle & T_Diamond == 0 and ob:
+        deleteDiamonds(ob)
+    if toggle & T_Rigify and False:
+        for rig in loadedData['Rigify'].values():
+            bpy.context.scene.objects.active = rig
+            print("Rigify", rig)
+            bpy.ops.pose.metarig_generate()
+            print("Metarig generated")
+            #bpy.context.scene.objects.unlink(rig)
+
+            rig = bpy.context.scene.objects.active
+            print("Rigged", rig, bpy.context.object)
+            ob = loadedData['Object']['HumanMesh']
+            mod = ob.modifiers[0]
+            print(ob, mod, mod.object)
+            mod.object = rig
+            print("Rig changed", mod.object)
+    return            
+
+#
+#    deleteDiamonds(ob)
+#    Delete joint diamonds in main mesh
 #
 
 def deleteDiamonds(ob):
-	bpy.context.scene.objects.active = ob
-	if not bpy.context.object:
-		return
-	print("Delete diamonds in %s" % bpy.context.object)
-	bpy.ops.object.mode_set(mode='EDIT')
-	bpy.ops.mesh.select_all(action='DESELECT')
-	bpy.ops.object.mode_set(mode='OBJECT')
-	me = ob.data
-	for f in me.faces:		
-		if len(f.vertices) < 4:
-			for vn in f.vertices:
-				me.vertices[vn].select = True
-	bpy.ops.object.mode_set(mode='EDIT')
-	bpy.ops.mesh.delete(type='VERT')
-	bpy.ops.object.mode_set(mode='OBJECT')
-	return
-
-	
-#
-#	parseProcess(args, tokens):
-#	applyTransform(objects, rig, parents):
+    bpy.context.scene.objects.active = ob
+    if not bpy.context.object:
+        return
+    print("Delete diamonds in %s" % bpy.context.object)
+    bpy.ops.object.mode_set(mode='EDIT')
+    bpy.ops.mesh.select_all(action='DESELECT')
+    bpy.ops.object.mode_set(mode='OBJECT')
+    me = ob.data
+    for f in me.faces:        
+        if len(f.vertices) < 4:
+            for vn in f.vertices:
+                me.vertices[vn].select = True
+    bpy.ops.object.mode_set(mode='EDIT')
+    bpy.ops.mesh.delete(type='VERT')
+    bpy.ops.object.mode_set(mode='OBJECT')
+    return
+
+    
+#
+#    parseProcess(args, tokens):
+#    applyTransform(objects, rig, parents):
 #
 
 def parseProcess(args, tokens):
-	if toggle & T_Bend == 0:
-		return
-	try:
-		rig = loadedData['Object'][args[0]]
-	except:
-		rig = None
-	if not rig:
-		return
-
-	parents = {}
-	objects = []
-
-	for (key, val, sub) in tokens:
-		#print(key, val)
-		if key == 'Reparent':
-			bname = val[0]
-			try:
-				eb = ebones[bname]
-				parents[bname] = eb.parent.name
-				eb.parent = ebones[val[1]]
-			except:
-				pass
-		elif key == 'Bend':
-			axis = val[1]
-			angle = float(val[2])
-			mat = mathutils.Matrix.Rotation(angle, 4, axis)
-			try:
-				pb = pbones[val[0]]
-				prod = pb.matrix_basis * mat
-				for i in range(4):
-					for j in range(4):
-						pb.matrix_local[i][j] = prod[i][j]
-			except:
-				print("No bone "+val[0])
-				pass
-		elif key == 'Snap':
-			try:
-				eb = ebones[val[0]]
-			except:
-				eb = None
-			tb = ebones[val[1]]
-			typ = val[2]
-			if eb == None:
-				pass
-			elif typ == 'Inv':
-				eb.head = tb.tail
-				eb.tail = tb.head
-			elif typ == 'Head':
-				eb.head = tb.head
-			elif typ == 'Tail':
-				eb.tail = tb.tail
-			elif typ == 'Both':
-				eb.head = tb.head
-				eb.tail = tb.tail
-				eb.roll = tb.roll
-			else:
-				raise NameError("Snap type %s" % typ)
-		elif key == 'PoseMode':
-			bpy.context.scene.objects.active = rig
-			bpy.ops.object.mode_set(mode='POSE')
-			pbones = rig.pose.bones	
-		elif key == 'ObjectMode':
-			bpy.context.scene.objects.active = rig
-			bpy.ops.object.mode_set(mode='POSE')
-			pbones = rig.pose.bones	
-		elif key == 'EditMode':
-			bpy.context.scene.objects.active = rig
-			bpy.ops.object.mode_set(mode='EDIT')
-			ebones = rig.data.edit_bones	
-			bpy.ops.armature.select_all(action='DESELECT')
-		elif key == 'Roll':
-			try:
-				eb = ebones[val[0]]
-			except:
-				eb = None
-			if eb:
-				eb.roll = float(val[1])
-		elif key == 'Select':
-			pass
-		elif key == 'RollUp':
-			pass
-		elif key == 'Apply':
-			applyTransform(objects, rig, parents)
-		elif key == 'ApplyArmature':
-			try:
-				ob = loadedData['Object'][val[0]]
-				objects.append((ob,sub))
-			except:
-				ob = None
-		elif key == 'Object':
-			try:
-				ob = loadedData['Object'][val[0]]
-			except:
-				ob = None
-			if ob:
-				bpy.context.scene.objects.active = ob
-				#mod = ob.modifiers[0]
-				#ob.modifiers.remove(mod)
-				for (key1, val1, sub1) in sub:
-					if key1 == 'Modifier':
-						parseModifier(ob, val1, sub1)
-	return
+    if toggle & T_Bend == 0:
+        return
+    try:
+        rig = loadedData['Object'][args[0]]
+    except:
+        rig = None
+    if not rig:
+        return
+
+    parents = {}
+    objects = []
+
+    for (key, val, sub) in tokens:
+        #print(key, val)
+        if key == 'Reparent':
+            bname = val[0]
+            try:
+                eb = ebones[bname]
+                parents[bname] = eb.parent.name
+                eb.parent = ebones[val[1]]
+            except:
+                pass
+        elif key == 'Bend':
+            axis = val[1]
+            angle = float(val[2])
+            mat = mathutils.Matrix.Rotation(angle, 4, axis)
+            try:
+                pb = pbones[val[0]]
+                prod = pb.matrix_local * mat
+                for i in range(4):
+                    for j in range(4):
+                        pb.matrix_local[i][j] = prod[i][j]
+            except:
+                print("No bone "+val[0])
+                pass
+        elif key == 'Snap':
+            try:
+                eb = ebones[val[0]]
+            except:
+                eb = None
+            tb = ebones[val[1]]
+            typ = val[2]
+            if eb == None:
+                pass
+            elif typ == 'Inv':
+                eb.head = tb.tail
+                eb.tail = tb.head
+            elif typ == 'Head':
+                eb.head = tb.head
+            elif typ == 'Tail':
+                eb.tail = tb.tail
+            elif typ == 'Both':
+                eb.head = tb.head
+                eb.tail = tb.tail
+                eb.roll = tb.roll
+            else:
+                raise NameError("Snap type %s" % typ)
+        elif key == 'PoseMode':
+            bpy.context.scene.objects.active = rig
+            bpy.ops.object.mode_set(mode='POSE')
+            pbones = rig.pose.bones    
+        elif key == 'ObjectMode':
+            bpy.context.scene.objects.active = rig
+            bpy.ops.object.mode_set(mode='POSE')
+            pbones = rig.pose.bones    
+        elif key == 'EditMode':
+            bpy.context.scene.objects.active = rig
+            bpy.ops.object.mode_set(mode='EDIT')
+            ebones = rig.data.edit_bones    
+            bpy.ops.armature.select_all(action='DESELECT')
+        elif key == 'Roll':
+            try:
+                eb = ebones[val[0]]
+            except:
+                eb = None
+            if eb:
+                eb.roll = float(val[1])
+        elif key == 'Select':
+            pass
+        elif key == 'RollUp':
+            pass
+        elif key == 'Apply':
+            applyTransform(objects, rig, parents)
+        elif key == 'ApplyArmature':
+            try:
+                ob = loadedData['Object'][val[0]]
+                objects.append((ob,sub))
+            except:
+                ob = None
+        elif key == 'Object':
+            try:
+                ob = loadedData['Object'][val[0]]
+            except:
+                ob = None
+            if ob:
+                bpy.context.scene.objects.active = ob
+                #mod = ob.modifiers[0]
+                #ob.modifiers.remove(mod)
+                for (key1, val1, sub1) in sub:
+                    if key1 == 'Modifier':
+                        parseModifier(ob, val1, sub1)
+    return
 
 def applyTransform(objects, rig, parents):
-	for (ob,tokens) in objects:
-		print("Applying transform to %s" % ob)
-		bpy.context.scene.objects.active = ob		
-		bpy.ops.object.visual_transform_apply()
-		bpy.ops.object.modifier_apply(apply_as='DATA', modifier='Armature')
+    for (ob,tokens) in objects:
+        print("Applying transform to %s" % ob)
+        bpy.context.scene.objects.active = ob        
+        bpy.ops.object.visual_transform_apply()
+        bpy.ops.object.modifier_apply(apply_as='DATA', modifier='Armature')
 
-	bpy.context.scene.objects.active = rig
-	bpy.ops.object.mode_set(mode='POSE')
-	bpy.ops.pose.armature_apply()
-	bpy.ops.object.mode_set(mode='OBJECT')
-	bpy.ops.object.mode_set(mode='EDIT')
-	ebones = rig.data.edit_bones
-	for (bname, pname) in parents.items():
-		eb = ebones[bname]
-		par = ebones[pname]
-		if eb.use_connect:
-			par.tail = eb.head
-		eb.parent = par
+    bpy.context.scene.objects.active = rig
+    bpy.ops.object.mode_set(mode='POSE')
+    bpy.ops.pose.armature_apply()
+    bpy.ops.object.mode_set(mode='OBJECT')
+    bpy.ops.object.mode_set(mode='EDIT')
+    ebones = rig.data.edit_bones
+    for (bname, pname) in parents.items():
+        eb = ebones[bname]
+        par = ebones[pname]
+        if eb.use_connect:
+            par.tail = eb.head
+        eb.parent = par
 
-	bpy.ops.object.mode_set(mode='OBJECT')
-	return			
+    bpy.ops.object.mode_set(mode='OBJECT')
+    return            
 
 #
-#	defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
+#    defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
 #
 
 def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
-	global todo
-
-	if ext == 'Property':
-		try:
-			expr = "%s['%s'] = %s" % (var, args[0], args[1])
-		except:
-			expr = None
-		print("Property", expr)
-		if expr:
-			exec(expr, glbals, lcals)
-		return
-		
-	nvar = "%s.%s" % (var, ext)
-	#print(ext)
-	if ext in exclude:
-		return
-	#print("D", nvar)
-
-	if len(args) == 0:
-		raise NameError("Key length 0: %s" % ext)
-		
-	rnaType = args[0]
-	if rnaType == 'Add':
-		print("*** Cannot Add yet ***")
-		return
-
-	elif rnaType == 'Refer':
-		typ = args[1]
-		name = args[2]
-		data = "loadedData['%s']['%s']" % (typ, name)
-
-	elif rnaType == 'Struct' or rnaType == 'Define':
-		typ = args[1]
-		name = args[2]
-		try:
-			data = eval(nvar, glbals, lcals)
-		except:
-			data = None			
-		# print("Old structrna", nvar, data)
-
-		if data == None:
-			try:
-				creator = args[3]
-			except:
-				creator = None
-			# print("Creator", creator, eval(var,glbals,lcals))
-
-			try:
-				rna = eval(var,glbals,lcals)
-				data = eval(creator)
-			except:
-				data = None	
-			# print("New struct", nvar, typ, data)
-
-		if rnaType == 'Define':
-			loadedData[typ][name] = data
-
-		if data:
-			for (key, val, sub) in tokens:
-				defaultKey(key, val, sub, "data", [], globals(), locals())
-
-		print("Struct done", nvar)
-		return
-
-	elif rnaType == 'PropertyRNA':
-		raise NameError("PropertyRNA!")
-		#print("PropertyRNA ", ext, var)
-		for (key, val, sub) in tokens:
-			defaultKey(ext, val, sub, nvar, [], glbals, lcals)
-		return
-
-	elif rnaType == 'Array':
-		for n in range(1, len(args)):
-			expr = "%s[%d] = %s" % (nvar, n-1, args[n])
-			exec(expr, glbals, lcals)
-		if len(args) > 0:
-			expr = "%s[0] = %s" % (nvar, args[1])
-			exec(expr, glbals, lcals)			
-		return
-		
-	elif rnaType == 'List':
-		data = []
-		for (key, val, sub) in tokens:
-			elt = eval(val[1], glbals, lcals)
-			data.append(elt)
-
-	elif rnaType == 'Matrix':
-		return
-		i = 0
-		n = len(tokens)
-		for (key, val, sub) in tokens:
-			if key == 'row':	
-				for j in range(n):
-					expr = "%s[%d][%d] = %g" % (nvar, i, j, float(val[j]))
-					exec(expr, glbals, lcals)
-				i += 1
-		return
-
-	else:
-		try:
-			data = loadedData[rnaType][args[1]]
-			#print("From loaded", rnaType, args[1], data)
-			return data
-		except:
-			data = rnaType
-
-	#print(var, ext, data)
-	expr = "%s = %s" % (nvar, data)
-	try:
-		exec(expr, glbals, lcals)
-	except:
-		pushOnTodoList(var, expr, glbals, lcals)
-	return
+    global todo
+
+    if ext == 'Property':
+        try:
+            expr = "%s['%s'] = %s" % (var, args[0], args[1])
+        except:
+            expr = None
+        # print("Property", expr)
+        if expr:
+            exec(expr, glbals, lcals)
+        return
+        
+    nvar = "%s.%s" % (var, ext)
+    #print(ext)
+    if ext in exclude:
+        return
+    #print("D", nvar)
+
+    if len(args) == 0:
+        raise NameError("Key length 0: %s" % ext)
+        
+    rnaType = args[0]
+    if rnaType == 'Add':
+        print("*** Cannot Add yet ***")
+        return
+
+    elif rnaType == 'Refer':
+        typ = args[1]
+        name = args[2]
+        data = "loadedData['%s']['%s']" % (typ, name)
+
+    elif rnaType == 'Struct' or rnaType == 'Define':
+        typ = args[1]
+        name = args[2]
+        try:
+            data = eval(nvar, glbals, lcals)
+        except:
+            data = None            
+        # print("Old structrna", nvar, data)
+
+        if data == None:
+            try:
+                creator = args[3]
+            except:
+                creator = None
+            # print("Creator", creator, eval(var,glbals,lcals))
+
+            try:
+                rna = eval(var,glbals,lcals)
+                data = eval(creator)
+            except:
+                data = None    
+            # print("New struct", nvar, typ, data)
+
+        if rnaType == 'Define':
+            loadedData[typ][name] = data
+
+        if data:
+            for (key, val, sub) in tokens:
+                defaultKey(key, val, sub, "data", [], globals(), locals())
+
+        print("Struct done", nvar)
+        return
+
+    elif rnaType == 'PropertyRNA':
+        raise NameError("PropertyRNA!")
+        #print("PropertyRNA ", ext, var)
+        for (key, val, sub) in tokens:
+            defaultKey(ext, val, sub, nvar, [], glbals, lcals)
+        return
+
+    elif rnaType == 'Array':
+        for n in range(1, len(args)):
+            expr = "%s[%d] = %s" % (nvar, n-1, args[n])
+            exec(expr, glbals, lcals)
+        if len(args) > 0:
+            expr = "%s[0] = %s" % (nvar, args[1])
+            exec(expr, glbals, lcals)            
+        return
+        
+    elif rnaType == 'List':
+        data = []
+        for (key, val, sub) in tokens:
+            elt = eval(val[1], glbals, lcals)
+            data.append(elt)
+
+    elif rnaType == 'Matrix':
+        return
+        i = 0
+        n = len(tokens)
+        for (key, val, sub) in tokens:
+            if key == 'row':    
+                for j in range(n):
+                    expr = "%s[%d][%d] = %g" % (nvar, i, j, float(val[j]))
+                    exec(expr, glbals, lcals)
+                i += 1
+        return
+
+    else:
+        try:
+            data = loadedData[rnaType][args[1]]
+            #print("From loaded", rnaType, args[1], data)
+            return data
+        except:
+            data = rnaType
+
+    #print(var, ext, data)
+    expr = "%s = %s" % (nvar, data)
+    try:
+        exec(expr, glbals, lcals)
+    except:
+        pushOnTodoList(var, expr, glbals, lcals)
+    return
 
 #
 #
 #
 
 def pushOnTodoList(var, expr, glbals, lcals):
-	global todo
-	print("Tdo", var)
-	print(dir(eval(var, glbals, lcals)))
-	raise NameError("Todo", expr)
-	todo.append((expr, glbals, lcals))
-	return
+    global todo
+    print("Tdo", var)
+    print(dir(eval(var, glbals, lcals)))
+    raise NameError("Todo", expr)
+    todo.append((expr, glbals, lcals))
+    return
 
-			
+            
 #
-#	parseBoolArray(mask):
+#    parseBoolArray(mask):
 #
 
 def parseBoolArray(mask):
-	list = []
-	for c in mask:
-		if c == '0':			
-			list.append(False)
-		else:
-			list.append(True)
-	return list
+    list = []
+    for c in mask:
+        if c == '0':            
+            list.append(False)
+        else:
+            list.append(True)
+    return list
 
-#	parseMatrix(args, tokens)
+#    parseMatrix(args, tokens)
 #
 
 def parseMatrix(args, tokens):
-	matrix = Matrix( [1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1] )
-	i = 0
-	for (key, val, sub) in tokens:
-		if key == 'row':	
-			matrix[i][0] = float(val[0])
-			matrix[i][1] = float(val[1])
-			matrix[i][2] = float(val[2])
-			matrix[i][3] = float(val[3])
-			i += 1
-	return matrix
+    matrix = Matrix( [1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1] )
+    i = 0
+    for (key, val, sub) in tokens:
+        if key == 'row':    
+            matrix[i][0] = float(val[0])
+            matrix[i][1] = float(val[1])
+            matrix[i][2] = float(val[2])
+            matrix[i][3] = float(val[3])
+            i += 1
+    return matrix
 
 #
-#	parseDefault(data, tokens, subkeys, exclude):
+#    parseDefault(data, tokens, subkeys, exclude):
 #
 
 def parseDefault(data, tokens, subkeys, exclude):
-	for (key, val, sub) in tokens:	
-		if key in subkeys.keys():
-			for (key2, val2, sub2) in sub:
-				defaultKey(key2, val2, sub2, "data.%s" % subkeys[key], [], globals(), locals())
-		else:
-			defaultKey(key, val, sub, "data", exclude, globals(), locals())
+    for (key, val, sub) in tokens:    
+        if key in subkeys.keys():
+            for (key2, val2, sub2) in sub:
+                defaultKey(key2, val2, sub2, "data.%s" % subkeys[key], [], globals(), locals())
+        else:
+            defaultKey(key, val, sub, "data", exclude, globals(), locals())
 
 def parseCollection(data, tokens, exclude):
-	return
+    return
 
 
 #
-#	Utilities	
+#    Utilities    
 #
 
 #
-#	extractBpyType(data):
+#    extractBpyType(data):
 #
 
 def extractBpyType(data):
-	typeSplit = str(type(data)).split("'")
-	if typeSplit[0] != '<class ':
-		return None
-	classSplit = typeSplit[1].split(".")
-	if classSplit[0] == 'bpy' and classSplit[1] == 'types':
-		return classSplit[2]
-	elif classSplit[0] == 'bpy_types':
-		return classSplit[1]
-	else:
-		return None
+    typeSplit = str(type(data)).split("'")
+    if typeSplit[0] != '<class ':
+        return None
+    classSplit = typeSplit[1].split(".")
+    if classSplit[0] == 'bpy' and classSplit[1] == 'types':
+        return classSplit[2]
+    elif classSplit[0] == 'bpy_types':
+        return classSplit[1]
+    else:
+        return None
 
 #
-#	Bool(string):
+#    Bool(string):
 #
 
 def Bool(string):
-	if string == 'True':
-		return True
-	elif string == 'False':
-		return False
-	else:
-		raise NameError("Bool %s?" % string)
-		
+    if string == 'True':
+        return True
+    elif string == 'False':
+        return False
+    else:
+        raise NameError("Bool %s?" % string)
+        
 #
-#	invalid(condition):
+#    invalid(condition):
 #
 
 def invalid(condition):
-	global rigLeg, rigArm, toggle
-	res = eval(condition, globals())
-	try:
-		res = eval(condition, globals())
-		#print("%s = %s" % (condition, res))
-		return not res
-	except:
-		#print("%s invalid!" % condition)
-		return True
+    global rigLeg, rigArm, toggle
+    res = eval(condition, globals())
+    try:
+        res = eval(condition, globals())
+        #print("%s = %s" % (condition, res))
+        return not res
+    except:
+        #print("%s invalid!" % condition)
+        return True
 
 
-	
+    
 #
-#	clearScene(context):
-#	hideLayers():
+#    clearScene(context):
+#    hideLayers():
 #
-	
+    
 def clearScene():
-	global toggle
-	scn = bpy.context.scene
-	for n in range(len(scn.layers)):
-		scn.layers[n] = True
-	print("clearScene %s %s" % (toggle & T_Replace, scn))
-	if not toggle & T_Replace:
-		return scn
-
-	for ob in scn.objects:
-		if ob.type == "MESH" or ob.type == "ARMATURE" or ob.type == 'EMPTY':
-			scn.objects.active = ob
-			bpy.ops.object.mode_set(mode='OBJECT')
-			scn.objects.unlink(ob)
-			del ob
-	#print(scn.objects)
-	return scn
+    global toggle
+    scn = bpy.context.scene
+    for n in range(len(scn.layers)):
+        scn.layers[n] = True
+    print("clearScene %s %s" % (toggle & T_Replace, scn))
+    if not toggle & T_Replace:
+        return scn
+
+    for ob in scn.objects:
+        if ob.type == "MESH" or ob.type == "ARMATURE" or ob.type == 'EMPTY':
+            scn.objects.active = ob
+            bpy.ops.object.mode_set(mode='OBJECT')
+            scn.objects.unlink(ob)
+            del ob
+    #print(scn.objects)
+    return scn
 
 def hideLayers():
-	scn = bpy.context.scene
-	for n in range(len(scn.layers)):
-		if n < 8:
-			scn.layers[n] = True
-		else:
-			scn.layers[n] = False
-	return
+    scn = bpy.context.scene
+    for n in range(len(scn.layers)):
+        if n < 8:
+            scn.layers[n] = True
+        else:
+            scn.layers[n] = False
+    return
 
 #
-#	User interface
+#    User interface
 #
 
 DEBUG= False
 from bpy.props import *
 
 class IMPORT_OT_makehuman_mhx(bpy.types.Operator):
-	'''Import from MHX file format (.mhx)'''
-	bl_idname = "import_scene.makehuman_mhx"
-	bl_description = 'Import from MHX file format (.mhx)'
-	bl_label = "Import MHX"
-	bl_space_type = "PROPERTIES"
-	bl_region_type = "WINDOW"
-
-	filepath = StringProperty(name="File Path", description="File path used for importing the MHX file", maxlen= 1024, default= "")
-
-	scale = FloatProperty(name="Scale", description="Default meter, decimeter = 1.0", default = theScale)
-	enforce = BoolProperty(name="Enforce version", description="Only accept MHX files of correct version", default=toggle&T_EnforceVersion)
-	mesh = BoolProperty(name="Mesh", description="Use main mesh", default=toggle&T_Mesh)
-	proxy = BoolProperty(name="Proxies", description="Use proxies", default=toggle&T_Proxy)
-	armature = BoolProperty(name="Armature", description="Use armature", default=toggle&T_Armature)
-	replace = BoolProperty(name="Replace scene", description="Replace scene", default=toggle&T_Replace)
-	cage = BoolProperty(name="Cage", description="Load mesh deform cage", default=toggle&T_Cage)
-	clothes = BoolProperty(name="Clothes", description="Include clothes", default=toggle&T_Clothes)
-	stretch = BoolProperty(name="Stretchy limbs", description="Stretchy limbs", default=toggle&T_Stretch)
-	face = BoolProperty(name="Face shapes", description="Include facial shapekeys", default=toggle&T_Face)
-	shape = BoolProperty(name="Body shapes", description="Include body shapekeys", default=toggle&T_Shape)
-	symm = BoolProperty(name="Symmetric shapes", description="Keep shapekeys symmetric", default=toggle&T_Symm)
-	diamond = BoolProperty(name="Diamonds", description="Keep joint diamonds", default=toggle&T_Diamond)
-	bend = BoolProperty(name="Bend joints", description="Bend joints for better IK", default=toggle&T_Bend)
-		
-	def execute(self, context):
-		global toggle
-		O_EnforceVersion = T_EnforceVersion if self.properties.enforce else 0
-		O_Mesh = T_Mesh if self.properties.mesh else 0
-		O_Proxy = T_Proxy if self.properties.proxy else 0
-		O_Armature = T_Armature if self.properties.armature else 0
-		O_Replace = T_Replace if self.properties.replace else 0
-		O_Cage = T_Cage if self.properties.cage else 0
-		O_Clothes = T_Clothes if self.properties.clothes else 0
-		O_Stretch = T_Stretch if self.properties.stretch else 0
-		O_Face = T_Face if self.properties.face else 0
-		O_Shape = T_Shape if self.properties.shape else 0
-		O_Symm = T_Symm if self.properties.symm else 0
-		O_Diamond = T_Diamond if self.properties.diamond else 0
-		O_Bend = T_Bend if self.properties.bend else 0
-		toggle = ( O_EnforceVersion | O_Mesh | O_Proxy | O_Armature | O_Replace | O_Stretch | O_Cage | 
-				O_Face | O_Shape | O_Symm | O_Diamond | O_Bend | O_Clothes | T_MHX )
-
-		print("Load", self.properties.filepath)
-		readMhxFile(self.properties.filepath, self.properties.scale)
-		return {'FINISHED'}
-
-	def invoke(self, context, event):
-		context.window_manager.fileselect_add(self)
-		return {'RUNNING_MODAL'}
+    '''Import from MHX file format (.mhx)'''
+    bl_idname = "import_scene.makehuman_mhx"
+    bl_description = 'Import from MHX file format (.mhx)'
+    bl_label = "Import MHX"
+    bl_space_type = "PROPERTIES"
+    bl_region_type = "WINDOW"
+
+    filepath = StringProperty(name="File Path", description="File path used for importing the MHX file", maxlen= 1024, default= "")
+
+    scale = FloatProperty(name="Scale", description="Default meter, decimeter = 1.0", default = theScale)
+
+
+
+    enforce = BoolProperty(name="Enforce version", description="Only accept MHX files of correct version", default=toggle&T_EnforceVersion)
+    mesh = BoolProperty(name="Mesh", description="Use main mesh", default=toggle&T_Mesh)
+    proxy = BoolProperty(name="Proxies", description="Use proxies", default=toggle&T_Proxy)
+    armature = BoolProperty(name="Armature", description="Use armature", default=toggle&T_Armature)
+    replace = BoolProperty(name="Replace scene", description="Replace scene", default=toggle&T_Replace)
+    cage = BoolProperty(name="Cage", description="Load mesh deform cage", default=toggle&T_Cage)
+    clothes = BoolProperty(name="Clothes", description="Include clothes", default=toggle&T_Clothes)
+    stretch = BoolProperty(name="Stretchy limbs", description="Stretchy limbs", default=toggle&T_Stretch)
+    face = BoolProperty(name="Face shapes", description="Include facial shapekeys", default=toggle&T_Face)
+    shape = BoolProperty(name="Body shapes", description="Include body shapekeys", default=toggle&T_Shape)
+    symm = BoolProperty(name="Symmetric shapes", description="Keep shapekeys symmetric", default=toggle&T_Symm)
+    diamond = BoolProperty(name="Diamonds", description="Keep joint diamonds", default=toggle&T_Diamond)
+    bend = BoolProperty(name="Bend joints", description="Bend joints for better IK", default=toggle&T_Bend)
+        
+    def execute(self, context):
+        global toggle
+        O_EnforceVersion = T_EnforceVersion if self.properties.enforce else 0
+        O_Mesh = T_Mesh if self.properties.mesh else 0
+        O_Proxy = T_Proxy if self.properties.proxy else 0
+        O_Armature = T_Armature if self.properties.armature else 0
+        O_Replace = T_Replace if self.properties.replace else 0
+        O_Cage = T_Cage if self.properties.cage else 0
+        O_Clothes = T_Clothes if self.properties.clothes else 0
+        O_Stretch = T_Stretch if self.properties.stretch else 0
+        O_Face = T_Face if self.properties.face else 0
+        O_Shape = T_Shape if self.properties.shape else 0
+        O_Symm = T_Symm if self.properties.symm else 0
+        O_Diamond = T_Diamond if self.properties.diamond else 0
+        O_Bend = T_Bend if self.properties.bend else 0
+        toggle = ( O_EnforceVersion | O_Mesh | O_Proxy | O_Armature | O_Replace | O_Stretch | O_Cage | 
+                O_Face | O_Shape | O_Symm | O_Diamond | O_Bend | O_Clothes | T_MHX )
+
+        print("Load", self.properties.filepath)
+        readMhxFile(self.properties.filepath, self.properties.scale)
+        return {'FINISHED'}
+
+    def invoke(self, context, event):
+        context.window_manager.fileselect_add(self)
+        return {'RUNNING_MODAL'}
 
 def menu_func(self, context):
     self.layout.operator(IMPORT_OT_makehuman_mhx.bl_idname, text="MakeHuman (.mhx)...")
 
 def register():
-	bpy.types.INFO_MT_file_import.append(menu_func)
+    bpy.types.INFO_MT_file_import.append(menu_func)
 
 def unregister():
-	bpy.types.INFO_MT_file_import.remove(menu_func)
+    bpy.types.INFO_MT_file_import.remove(menu_func)
 
 if __name__ == "__main__":
-	try:
-		unregister()
-	except:
-		pass
-	register()
+    try:
+        unregister()
+    except:
+        pass
+    register()
 
 #
-#	Testing
+#    Testing
 #
 """
 #readMhxFile("C:/Documents and Settings/xxxxxxxxxxxxxxxxxxxx/Mina dokument/makehuman/exports/foo-25.mhx", 'Classic')