Skip to content
Snippets Groups Projects
io_import_scene_mhx.py 61.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ##### BEGIN GPL LICENSE BLOCK #####
    #
    #  This program is free software; you can redistribute it and/or
    #  modify it under the terms of the GNU General Public License
    #  as published by the Free Software Foundation; either version 2
    #  of the License, or (at your option) any later version.
    #
    #  This program is distributed in the hope that it will be useful,
    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #  GNU General Public License for more details.
    #
    #  You should have received a copy of the GNU General Public License
    #  along with this program; if not, write to the Free Software Foundation,
    #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    #
    # ##### END GPL LICENSE BLOCK #####
    
    bl_addon_info = {
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        "name": "Import MakeHuman (.mhx)",
    
        "author": "Thomas Larsson",
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        "version": (0,9,5),
    
        "blender": (2, 5, 3),
    
        "location": "File > Import",
        "description": "Import files in the MakeHuman eXchange format (.mhx)",
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        "warning": "Alpha version",
        "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"}
    
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    """ 
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    **Project Name:**      MakeHuman
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    **Product Home Page:** http://www.makehuman.org/
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    **Code Home Page:**    http://code.google.com/p/makehuman/
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    **Authors:**           Thomas Larsson
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    **Copyright(c):**      MakeHuman Team 2001-2010
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    **Licensing:**         GPL3 (see also http://sites.google.com/site/makehumandocs/licensing)
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    **Coding Standards:**  See http://sites.google.com/site/makehumandocs/developers-guide
    
    Abstract
    MHX (MakeHuman eXchange format) importer for Blender 2.5x.
    Version 0.9
    
    """
    
    """
    Place this file in the .blender/scripts/addons dir
    You have to activated the script in the "Add-Ons" tab (user preferences).
    Access from the File > Import menu.
    """
    
    #
    #
    #
    
    import bpy
    import os
    import time
    import mathutils
    from mathutils import *
    import geometry
    import string
    
    MAJOR_VERSION = 0
    MINOR_VERSION = 9
    MHX249 = False
    Blender24 = False
    Blender25 = True
    TexDir = "~/makehuman/exports"
    
    #
    #
    #
    
    theScale = 1.0
    useMesh = 1
    doSmash = 1
    verbosity = 2
    warnedTextureDir = False
    warnedVersion = False
    
    true = True
    false = False
    Epsilon = 1e-6
    nErrors = 0
    theTempDatum = None
    
    todo = []
    
    #
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    toggle flags
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    T_ArmIK = 0x01
    T_LegIK = 0x02
    T_Replace = 0x20
    T_Face = 0x40
    T_Shape = 0x80
    T_Mesh = 0x100
    T_Armature = 0x200
    T_Proxy = 0x400
    T_Panel = 0x800
    
    T_Rigify = 0x1000
    T_Preset = 0x2000
    T_Symm = 0x4000
    T_MHX = 0x8000
    
    toggle = T_Replace + T_ArmIK + T_LegIK + T_Mesh + T_Armature + T_Face
    
    #
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    setFlagsAndFloats(rigFlags):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    Global floats
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    fLegIK = 0.0
    fArmIK = 0.0
    fFingerPanel = 0.0
    fFingerIK = 0.0
    fFingerCurl = 0.0
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    rigLeg and rigArm flags
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    T_Toes = 0x0001
    T_GoboFoot = 0x0002
    T_InvFoot = 0x0004
    
    T_FingerPanel = 0x100
    T_FingerCurl = 0x0200
    T_FingerIK = 0x0400
    
    
    T_LocalFKIK = 0x8000
    
    rigLeg = 0
    rigArm = 0
    
    def setFlagsAndFloats(rigFlags):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global toggle, rigLeg, rigArm
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        (footRig, fingerRig) = rigFlags
        rigLeg = 0
        rigArm = 0
        if footRig == 'Reverse foot': rigLeg |= T_InvFoot
        elif footRig == 'Gobo': rigLeg |= T_GoboFoot
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        if fingerRig == 'Panel': rigArm |= T_FingerPanel
        elif fingerRig == 'IK': rigArm |= T_FingerIK
        elif fingerRig == 'Curl': rigArm |= T_FingerCurl
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        toggle |= T_Panel
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        # Global floats, used as influences
        global fFingerCurl, fLegIK, fArmIK, fFingerIK
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        fFingerCurl = 1.0 if rigArm&T_FingerCurl else 0.0
        fLegIK = 1.0 if toggle&T_LegIK else 0.0
        fArmIK = 1.0 if toggle&T_ArmIK else 0.0
        fFingerIK = 1.0 if rigArm&T_FingerIK else 0.0
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    Dictionaries
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    loadedData = {
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        'NONE' : {},
    
        'Object' : {},
        'Mesh' : {},
        'Armature' : {},
        'Lamp' : {},
        'Camera' : {},
        'Lattice' : {},
        'Curve' : {},
    
        'Material' : {},
        'Image' : {},
        'MaterialTextureSlot' : {},
        'Texture' : {},
        
        'Bone' : {},
        'BoneGroup' : {},
        'Rigify' : {},
    
        'Action' : {},
        'Group' : {},
    
        'MeshTextureFaceLayer' : {},
        'MeshColorLayer' : {},
        'VertexGroup' : {},
        'ShapeKey' : {},
        'ParticleSystem' : {},
    
        'ObjectConstraints' : {},
        'ObjectModifiers' : {},
        'MaterialSlot' : {},
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    }
    
    Plural = {
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        'Object' : 'objects',
        'Mesh' : 'meshes',
        'Lattice' : 'lattices',
        'Curve' : 'curves',
        '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',
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    Creators
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def uvtexCreator(me, name):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        print("uvtexCreator", me, name)
        return me.uv_textures.new(name)
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    def vertcolCreator(me, name):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        print("vertcolCreator", me, name)
        return me.vertex_colors.new(name)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    loadMhx(filePath, context, flags):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def loadMhx(filePath, context, flags):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global toggle
        toggle = flags
        readMhxFile(filePath)
        return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    readMhxFile(filePath, rigFlags):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def readMhxFile(filePath, rigFlags):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global todo, nErrors
        
        fileName = os.path.expanduser(filePath)
        (shortName, ext) = os.path.splitext(fileName)
        if ext != ".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
    
        setFlagsAndFloats(rigFlags)
    
        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] == '#':
                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    # loadMhx
    
    #
    #    getObject(name, var, glbals, lcals):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def getObject(name, var, glbals, lcals):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        try:
            ob = loadedData['Object'][name]
        except:
            if name != "None":
                expr = "%s = loadedData['Object'][name]" % var
                print("Todo ", expr)
                todo.append((expr, glbals, lcals))
            ob = None
        return ob
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    parse(tokens):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    ifResult = False
    
    def parse(tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global warnedVersion, MHX249, ifResult
        
        for (key, val, sub) in tokens:    
            # print("Parse %s" % key)
            data = None
            if key == 'MHX':
                if int(val[0]) != MAJOR_VERSION and int(val[1]) != MINOR_VERSION and not warnedVersion:
                    print("Warning: \nThis file was created with another version of MHX\n")
                    warnedVersion = True
    
            elif key == 'MHX249':
                MHX249 = eval(val[0])
                print("Blender 2.49 compatibility mode is %s\n" % MHX249)
    
            elif key == 'if':
                try:
                    ifResult = eval(val[0])
                except:
                    ifResult = False
                if ifResult:
                    parse(sub)
                    
            elif key == 'elif':
                if not ifResult:
                    try:
                        ifResult = eval(val[0])
                    except:
                        ifResult = False
                    if ifResult:
                        parse(sub)
            
            elif key == 'else':
                if not ifResult:
                    parse(sub)
            
    
            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 == "Object":
                parseObject(val, sub)
            elif key == "Mesh":
                data = parseMesh(val, sub)
            elif key == "Curve":
                data = parseCurve(val, sub)
            elif key == "Lattice":
                data = parseLattice(val, sub)
            elif key == "Group":
                data = parseGroup(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 == "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, 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):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def parseDefaultType(typ, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global todo
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        name = args[0]
        data = None
        expr = "bpy.data.%s.new('%s')" % (Plural[typ], name)
        print(expr)
        data = eval(expr)
        print("  ok", data)
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        bpyType = typ.capitalize()
        print(bpyType, name, data)
        loadedData[bpyType][name] = data
        if data == None:
            return None
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        for (key, val, sub) in tokens:
            #print("%s %s" % (key, val))
            defaultKey(key, val, sub, 'data', [], globals(), locals())
        print("Done ", data)
        return data
        
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    concatList(elts)
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def concatList(elts):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        string = ""
        for elt in elts:
            string += " %s" % elt
        return string
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    parseAction(args, tokens):
    #    parseFCurve(fcu, args, tokens):
    #    parseKeyFramePoint(pt, args, tokens):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def parseAction(args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def channelFromDataPath(dataPath, index):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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)
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def parseActionFCurve(act, ob, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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.use_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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def parseKeyFramePoint(pt, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        pt.co = (float(args[0]), float(args[1]))
        if len(args) > 2:
            pt.handle_left = (float(args[2]), float(args[3]))
            pt.handle_right = (float(args[3]), float(args[5]))
        return pt
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    parseAnimationData(rna, tokens):
    #    parseDriver(drv, args, tokens):
    #    parseDriverVariable(var, args, tokens):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def parseAnimationData(rna, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        if 0 and toggle & T_MHX:
            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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def parseAnimDataFCurve(adata, rna, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    """
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            fcurve = con.driver_add("influence", 0)
            driver = fcurve.driver
            driver.type = 'AVERAGE'
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    """
    def parseDriver(adata, dataPath, index, rna, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def parseDriverVariable(drv, rna, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def parseFModifier(fcu, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        #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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    """
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    """
    def parseDriverTarget(var, nTarget, rna, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        targ = var.targets[nTarget]
        # targ.rna_path = args[0]
        # targ.id_type = args[1]
        targ.id = loadedData['Object'][args[0]]
        for (key, val, sub) in tokens:
            defaultKey(key, val, sub, 'targ', [], globals(), locals())
        #print("Targ", targ, targ.id, targ.data_path, targ.id_type, targ.bone_target, targ.use_local_space_transform)
        return targ
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    parseMaterial(args, ext, tokens):
    #    parseMTex(mat, args, tokens):
    #    parseTexture(args, tokens):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def parseMaterial(args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global todo
        name = args[0]
        #print("Parse material "+name)
        mat = bpy.data.materials.new(name)
        if mat == None:
            return None
        loadedData['Material'][name] = mat
        #print("Material %s %s %s" % (mat, name, loadedData['Material'][name]))
        for (key, val, sub) in tokens:
            if key == 'MTex':
                parseMTex(mat, val, sub)
            elif key == 'Ramp':
                parseRamp(mat, val, sub)
            elif key == 'SSS':
                parseSSS(mat, val, sub)
            elif key == 'Strand':
                parseStrand(mat, val, sub)
            else:
                exclude = ['specular_intensity', 'use_tangent_shading']
                defaultKey(key, val, sub, 'mat', [], globals(), locals())
        #print("Done ", mat)
        
        return mat
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def parseMTex(mat, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global todo
        index = int(args[0])
        texname = args[1]
        texco = args[2]
        mapto = args[3]
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
        mtex = mat.texture_slots.add()
        mtex.texture = loadedData['Texture'][texname]
        mtex.texture_coords = texco
        mtex.use_map_color_diffuse = True # XXX, fixme, mapto not used
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        for (key, val, sub) in tokens:
            defaultKey(key, val, sub, "mtex", [], globals(), locals())
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        return mtex
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def parseTexture(args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global todo
        if verbosity > 2:
            print( "Parsing texture %s" % args )
        tex = bpy.data.textures.new(name=args[0], 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)
            else:
                defaultKey(key, val,  sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
    
        return tex
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def parseRamp(data, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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())
        
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    def parseSSS(mat, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        sss = mat.subsurface_scattering
        for (key, val, sub) in tokens:
            defaultKey(key, val, sub, "sss", [], globals(), locals())
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def parseStrand(mat, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        strand = mat.strand
        for (key, val, sub) in tokens:
            defaultKey(key, val, sub, "strand", [], globals(), locals())
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    doLoadImage(filepath):
    #    loadImage(filepath):
    #    parseImage(args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    
    def loadImage(filepath):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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
        
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    def parseImage(args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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', 'is_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):
    #    createObjectAndData(args, typ):
    #
        
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    def parseObject(args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        if verbosity > 2:
            print( "Parsing object %s" % args )
        name = args[0]
        typ = args[1]
        datName = args[2]
        try:
            data = loadedData[typ.capitalize()][datName]    
        except:
            data = None
    
        if data == None and typ != 'EMPTY':
            print("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")
        except:
            ob = createObject(typ, name, data, datName)
        if bpy.context.object != ob:
            print("Context", ob, bpy.context.object, bpy.context.scene.objects.active)
            # ob = foo 
    
        for (key, val, sub) in tokens:
            if key == 'Modifier':
                parseModifier(ob, val, sub)
            elif key == 'Constraint':
                parseConstraint(ob.constraints, val, sub)
            elif key == 'AnimationData':
                if eval(val[0]):
                    parseAnimationData(ob, sub)
            elif key == 'ParticleSystem':
                parseParticleSystem(ob, val, sub)
            else:
                defaultKey(key, val, sub, "ob", ['type', 'data'], globals(), locals())
    
        # Needed for updating layers
        bpy.ops.object.mode_set(mode='EDIT')
        bpy.ops.object.mode_set(mode='OBJECT')
        return
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def createObject(typ, name, data, datName):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        #print( "Creating object %s %s %s" % (typ, name, data) )    
        ob = bpy.data.objects.new(name, data)
        loadedData[typ][datName] = data
        loadedData['Object'][name] = ob
        return ob
        
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    def linkObject(ob, data):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        #print("Data", data, ob.data)
        if data and ob.data == None:
            ob.data = 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
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def createObjectAndData(args, typ):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        datName = args[0]
        obName = args[1]
        bpy.ops.object.add(type=typ.upper())
        ob = bpy.context.object
        ob.name = obName
        ob.data.name = datName
        loadedData[typ][datName] = ob.data
        loadedData['Object'][obName] = ob
        return ob.data
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    parseModifier(ob, args, tokens):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def parseModifier(ob, args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        name = args[0]
        typ = args[1]
        if typ == 'PARTICLE_SYSTEM':
            return None