Skip to content
Snippets Groups Projects
io_import_scene_mhx.py 117 KiB
Newer Older
  • Learn to ignore specific revisions
  •     for (pb, cns, inf) in cnslist:
            cns.influence = inf
        return
            
    
    #
    #    postProcess(args)
    #
    
    def postProcess(args):
        human = args[0]
        print("Postprocess %s" % human)    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        try:
    
            ob = loadedData['Object'][human]
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        except:
            ob = None
        if toggle & T_Diamond == 0 and ob:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        return            
    
    #
    #    deleteDiamonds(ob)
    #    Delete joint diamonds in main mesh
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        bpy.context.scene.objects.active = ob
        if not bpy.context.object:
            return
    
        print("Delete helper geometry in %s" % bpy.context.object)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        bpy.ops.object.mode_set(mode='EDIT')
        bpy.ops.mesh.select_all(action='DESELECT')
        bpy.ops.object.mode_set(mode='OBJECT')
        me = ob.data
    
        invisioNum = -1
        for mn,mat in enumerate(me.materials):
            if "Invis" in mat.name:
                invisioNum = mn
                break
        if invisioNum < 0:
            print("WARNING: Nu Invisio material found. Cannot delete helper geometry")
        else:        
    
                if f.material_index >= invisioNum:
                    for vn in f.vertices:
                        me.vertices[vn].select = True
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        bpy.ops.object.mode_set(mode='EDIT')
        bpy.ops.mesh.delete(type='VERT')
        bpy.ops.object.mode_set(mode='OBJECT')
        return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
        if ext == 'Property':
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            try:
    
                expr = '%s["%s"] = %s' % (var, args[0], args[1])
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            except:
                expr = None
    
            if expr:
                exec(expr, glbals, lcals)
                if len(args) > 2:
                    thePropTip =  '"description":"%s"' % args[2].replace("_", " ")
            return
        elif ext == 'PropKeys':
            if len(args) < 2:
                values = '{%s}' % thePropTip
            else:
                values = '{%s%s}' % (args[1], thePropTip)        
            try:
                expr = '%s["_RNA_UI"]["%s"] = %s' % (var, args[0], values)
            except:
                expr = None
            #print("PropKeys", expr)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            if expr:
                exec(expr, glbals, lcals)
            return
    
    
        if ext == 'bpyops':
            expr = "bpy.ops.%s" % args[0]
            print(expr)
            exec(expr)
            return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            
        nvar = "%s.%s" % (var, ext)
        #print(ext)
        if ext in exclude:
            return
        #print("D", nvar)
    
        if len(args) == 0:
    
            MyError("Key length 0: %s" % ext)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            
        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)
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                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':
    
            MyError("PropertyRNA!")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            #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
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global todo
        print("Tdo", var)
        print(dir(eval(var, glbals, lcals)))
    
        MyError("Todo %s" % expr)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        todo.append((expr, glbals, lcals))
        return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    parseBoolArray(mask):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def parseBoolArray(mask):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        list = []
        for c in mask:
            if c == '0':            
                list.append(False)
            else:
                list.append(True)
        return list
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    parseMatrix(args, tokens)
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def parseMatrix(args, tokens):
    
        matrix = mathutils.Matrix()
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    parseDefault(data, tokens, subkeys, exclude):
    
    def parseDefault(data, tokens, subkeys, exclude):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    Utilities    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    extractBpyType(data):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def extractBpyType(data):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    Bool(string):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def Bool(string):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        if string == 'True':
            return True
        elif string == 'False':
            return False
        else:
    
            MyError("Bool %s?" % string)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    invalid(condition):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def invalid(condition):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    clearScene(context):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    def clearScene():
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global toggle
        scn = bpy.context.scene
        for n in range(len(scn.layers)):
            scn.layers[n] = True
    
        return scn
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        print("clearScene %s %s" % (toggle & T_Replace, scn))
        if not toggle & T_Replace:
            return scn
    
        for ob in scn.objects:
    
            if ob.type in ['MESH', 'ARMATURE', 'EMPTY', 'CURVE', 'LATTICE']:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                scn.objects.active = ob
    
                try:
                    bpy.ops.object.mode_set(mode='OBJECT')
                except:
                    pass
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                scn.objects.unlink(ob)
                del ob
    
    
        for grp in bpy.data.groups:
            grp.name = "#" + grp.name
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        #print(scn.objects)
        return scn
    
    #
    #    hideLayers(args):
    #    args = sceneLayers sceneHideLayers boneLayers boneHideLayers or nothing
    #
    
    def hideLayers(args):
        if len(args) > 1:
            sceneLayers = int(args[2], 16)
            sceneHideLayers = int(args[3], 16)
            boneLayers = int(args[4], 16)
            boneHideLayers = int(args[5], 16)
        else:
            sceneLayers = 0x00ff
            sceneHideLayers = 0
            boneLayers = 0
            boneHideLayers = 0
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        scn = bpy.context.scene
    
        mask = 1
        hidelayers = []
        for n in range(20):
            scn.layers[n] = True if sceneLayers & mask else False
            if sceneHideLayers & mask:
                hidelayers.append(n)
            mask = mask << 1
    
        for ob in scn.objects:
            for n in hidelayers:
                if ob.layers[n]:
                    ob.hide = True
    
        if boneLayers:    
            human = args[1]
            try:
                ob = loadedData['Object'][human]
            except:
                return
    
            mask = 1
            hidelayers = []
            for n in range(32):
                ob.data.layers[n] = True if boneLayers & mask else False
                if boneHideLayers & mask:
                    hidelayers.append(n)
                mask = mask << 1
    
            for b in ob.data.bones:
                for n in hidelayers:
                    if b.layers[n]:
                        b.hide = True
    
        return
        
    
    #
    #    readDefaults():
    #    writeDefaults():
    #
    
    ConfigFile = '~/mhx_import.cfg'
    
    
    def readDefaults():
    
        global toggle, theScale
    
        path = os.path.realpath(os.path.expanduser(ConfigFile))
        try:
            fp = open(path, 'rU')
            print('Storing defaults')
        except:
            print('Cannot open "%s" for reading' % path)
            return
        bver = ''
        for line in fp: 
            words = line.split()
            if len(words) >= 3:
                try:
                    toggle = int(words[0],16)
                    theScale = float(words[1])
                except:
                    print('Configuration file "%s" is corrupt' % path)                
        fp.close()
        return
    
    def writeDefaults():
    
        global toggle, theScale
    
        path = os.path.realpath(os.path.expanduser(ConfigFile))
        try:
            fp = open(path, 'w')
            print('Storing defaults')
        except:
            print('Cannot open "%s" for writing' % path)
            return
    
        fp.write("%x %f Graphicall" % (toggle, theScale))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        return
    
    ###################################################################################
    #
    #   Postprocessing of rigify rig
    #
    
    #
    ###################################################################################
    
    
        print("Modifying MHX rig to Rigify")
        scn = context.scene 
    
        mhx = loadedData['Object'][name]
        mhx['MhxRigify'] = True
        bpy.context.scene.objects.active = mhx
    
        # Delete old widgets
        """
    
        for ob in scn.objects:
            if ob.type == 'MESH' and ob.name[0:3] == "WGT":
                scn.objects.unlink(ob)
    
    
        # Save mhx bone locations    
        heads = {}
        tails = {}
        rolls = {}
        parents = {}
        extras = {}
        bpy.ops.object.mode_set(mode='EDIT')
    
        newParents = {
            'head' : 'DEF-head',
            'ribs' : 'DEF-ribs',
            'upper_arm.L' : 'DEF-upper_arm.L.02',
            'thigh.L' : 'DEF-thigh.L.02',
            'upper_arm.R' : 'DEF-upper_arm.R.02',
            'thigh.R' : 'DEF-thigh.R.02',
        }
    
        for eb in mhx.data.edit_bones:
            heads[eb.name] = eb.head.copy()
            tails[eb.name] = eb.tail.copy()
            rolls[eb.name] = eb.roll
            if eb.parent:            
                par = eb.parent.name
    
                # print(eb.name, par)
    
                try:
                    parents[eb.name] = newParents[par]
                except:
                    parents[eb.name] = par
            else:
                parents[eb.name] = None
            extras[eb.name] = not eb.layers[16]
        bpy.ops.object.mode_set(mode='OBJECT')
       
        # Find corresponding meshes. Can be several (clothes etc.)   
        meshes = []
        for ob in scn.objects:
            for mod in ob.modifiers:
                if (mod.type == 'ARMATURE' and mod.object == mhx):
                    meshes.append((ob, mod))
        if meshes == []:
    
            MyError("Did not find matching mesh")
    
            
        # Rename Head vertex group    
        for (mesh, mod) in meshes:
            try:
                vg = mesh.vertex_groups['DfmHead']
                vg.name = 'DEF-head'
            except:
                pass
    
    
        scn.objects.active = None 
        try:
            bpy.ops.object.armature_human_advanced_add()
            success = True
        except:
            success = False
        if not success:
    
            MyError("Unable to create advanced human. \n" \
    
                    "Make sure that the Rigify addon is enabled. \n" \
    
                    "It is found under Rigging.")
    
        bpy.ops.object.mode_set(mode='EDIT')
    
            eb.head = heads[eb.name]
            eb.tail = tails[eb.name]
            eb.roll = rolls[eb.name]
            extras[eb.name] = False
    
        fingerPlanes = [
            ('UP-thumb.L', 'thumb.01.L', 'thumb.03.L', ['thumb.02.L']),
            ('UP-index.L', 'finger_index.01.L', 'finger_index.03.L', ['finger_index.02.L']),
            ('UP-middle.L', 'finger_middle.01.L', 'finger_middle.03.L', ['finger_middle.02.L']),
            ('UP-ring.L', 'finger_ring.01.L', 'finger_ring.03.L', ['finger_ring.02.L']),
            ('UP-pinky.L', 'finger_pinky.01.L', 'finger_pinky.03.L', ['finger_pinky.02.L']),
            ('UP-thumb.R', 'thumb.01.R', 'thumb.03.R', ['thumb.02.R']),
            ('UP-index.R', 'finger_index.01.R', 'finger_index.03.R', ['finger_index.02.R']),
            ('UP-middle.R', 'finger_middle.01.R', 'finger_middle.03.R', ['finger_middle.02.R']),
            ('UP-ring.R', 'finger_ring.01.R', 'finger_ring.03.R', ['finger_ring.02.R']),
            ('UP-pinky.R', 'finger_pinky.01.R', 'finger_pinky.03.R', ['finger_pinky.02.R']),
        ]
    
        for (upbone, first, last, middles) in fingerPlanes:
            extras[upbone] = False
    
            #lineateChain(upbone, first, last, middles, 0.01, meta, heads, tails)
    
    
        ikPlanes = [
            ('UP-leg.L', 'thigh.L', 'shin.L'),
            ('UP-arm.L', 'upper_arm.L', 'forearm.L'),
            ('UP-leg.R', 'thigh.R', 'shin.R'),
            ('UP-arm.R', 'upper_arm.R', 'forearm.R'),
        ]
    
        for (upbone, first, last) in ikPlanes:
            extras[upbone] = False
    
            lineateChain(upbone, first, last, [], 0.1, meta, heads, tails)
    
    
        bpy.ops.object.mode_set(mode='OBJECT')
    
    
        bpy.ops.pose.rigify_generate()
    
        scn.objects.unlink(meta)
        rigify = context.object
        rigify.name = name+"Rig"
    
        layers = 20*[False]
        layers[1] = True        
        rigify.layers = layers
    
        for (mesh, mod) in meshes:
    
            mod.object = rigify
    
        grp = loadedData['Group'][name]
        grp.objects.link(rigify)
    
    
        # Parent widgets under empty
        empty = bpy.data.objects.new("Widgets", None)
        scn.objects.link(empty)
        empty.layers = 20*[False]
        empty.layers[19] = True
    
        for ob in scn.objects:
            if ob.type == 'MESH' and ob.name[0:4] == "WGT-" and not ob.parent:
                ob.parent = empty
    
                grp.objects.link(ob)
            elif ob.parent == mhx:
                ob.parent = rigify
    
        bpy.ops.object.mode_set(mode='EDIT')
        for name in heads.keys():
            if extras[name]:
    
                eb.head = heads[name]
                eb.tail = tails[name]
                eb.roll = rolls[name]            
        for name in heads.keys():
            if extras[name] and parents[name]:
    
                eb = rigify.data.edit_bones[name]
                eb.parent = rigify.data.edit_bones[parents[name]]
    
    
        # Copy constraints etc.
        bpy.ops.object.mode_set(mode='POSE')
        for name in heads.keys():
            if extras[name]:
                pb1 = mhx.pose.bones[name]
    
                pb2.custom_shape = pb1.custom_shape
                pb2.lock_location = pb1.lock_location
                pb2.lock_rotation = pb1.lock_rotation
                pb2.lock_scale = pb1.lock_scale
                b1 = pb1.bone
                b2 = pb2.bone
                b2.use_deform = b1.use_deform
                b2.hide_select = b1.hide_select
                b2.show_wire = b1.show_wire
                layers = 32*[False]
                if b1.layers[8]:
                    layers[28] = True
                else:
                    layers[29] = True
                if b1.layers[10]:
                    layers[2] = True
                b2.layers = layers
                for cns1 in pb1.constraints:
    
                    cns2 = copyConstraint(cns1, pb1, pb2, mhx, rigify)    
    
                    if cns2.type == 'CHILD_OF':
    
                        bpy.ops.constraint.childof_set_inverse(constraint=cns2.name, owner='BONE')    
        
        # Create animation data
        if mhx.animation_data:
            for fcu in mhx.animation_data.drivers:
    
                rigify.animation_data.drivers.from_existing(src_driver=fcu)
    
        fixDrivers(rigify.animation_data, mhx, rigify)
    
        for (mesh, mod) in meshes:
    
            skeys = mesh.data.shape_keys
            if skeys:
    
                fixDrivers(skeys.animation_data, mhx, rigify)
    
    
        scn.objects.unlink(mhx)
        print("Rigify rig complete")    
        return
    
    #
    
    #   lineateChain(upbone, first, last, middles, minDist, rig, heads, tails):
    
    #   lineate(pt, start, minDist, normal, offVector):
    #
    
    
    def lineateChain(upbone, first, last, middles, minDist, rig, heads, tails):
        fb = rig.data.edit_bones[first]
        lb = rig.data.edit_bones[last]
    
        uhead = heads[upbone]
        utail = tails[upbone]
        tang = lb.tail - fb.head
        tangent = tang/tang.length
        up = (uhead+utail)/2 - fb.head
        norm = up - tangent*tangent.dot(up)
        normal = norm/norm.length
        offVector = tangent.cross(normal)
        vec = utail - uhead
        fb.tail = lineate(fb.tail, fb.head, minDist, normal, offVector)
        lb.head = lineate(lb.head, fb.head, minDist, normal, offVector)
        for bone in middles:
    
            mb.head = lineate(mb.head, fb.head, minDist, normal, offVector)
            mb.tail = lineate(mb.tail, fb.head, minDist, normal, offVector)
        return
    
    def lineate(pt, start, minDist, normal, offVector):
        diff = pt - start
        diff = diff - offVector*offVector.dot(diff) 
        dist = diff.dot(normal)
        if dist < minDist:
            diff += (minDist - dist)*normal
        return start + diff
    
    #
    
        if not adata:
            return
        for fcu in adata.drivers:
            for var in fcu.driver.variables:
                for targ in var.targets:
                    if targ.id == mhx:
    
    #   copyConstraint(cns1, pb1, pb2, mhx, rigify):
    
    def copyConstraint(cns1, pb1, pb2, mhx, rigify):
    
        substitute = {
            'Head' : 'DEF-head',
            'MasterFloor' : 'root',
            'upper_arm.L' : 'DEF-upper_arm.L.01',
            'upper_arm.R' : 'DEF-upper_arm.R.01',
            'thigh.L' : 'DEF-thigh.L.01',
            'thigh.R' : 'DEF-thigh.R.01',
            'shin.L' : 'DEF-shin.L.01',
            'shin.R' : 'DEF-shin.R.01'
        }
    
        cns2 = pb2.constraints.new(cns1.type)
        for prop in dir(cns1):
            if prop == 'target':
                if cns1.target == mhx:
    
                else:
                    cns2.target = cns1.target
            elif prop == 'subtarget':
                try:
                    cns2.subtarget = substitute[cns1.subtarget]
                except:
                    cns2.subtarget = cns1.subtarget
            elif prop[0] != '_':
                try:
                    expr = "cns2.%s = cns1.%s" % (prop, prop)
                    #print(pb1.name, expr)
                    exec(expr)
                except:
                    pass
        return cns2
    
    #
    #   class OBJECT_OT_RigifyMhxButton(bpy.types.Operator):
    #
    
    class OBJECT_OT_RigifyMhxButton(bpy.types.Operator):
        bl_idname = "mhxrig.rigify_mhx"
        bl_label = "Rigify MHX rig"
    
    
        def execute(self, context):
    
            return{'FINISHED'}    
        
    #
    #   class RigifyMhxPanel(bpy.types.Panel):
    #
    
    class RigifyMhxPanel(bpy.types.Panel):
        bl_label = "Rigify MHX"
        bl_space_type = "VIEW_3D"
        bl_region_type = "UI"
        
        @classmethod
        def poll(cls, context):
            if context.object:
                try:
                    return context.object['MhxRigify']
                except:
                    return False
            return False
    
        def draw(self, context):
    
    Thomas Dinges's avatar
    Thomas Dinges committed
            self.layout.operator("mhxrig.rigify_mhx")
    
            return
    
    ###################################################################################
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    #    Error popup
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    ###################################################################################
    
    from bpy.props import StringProperty, FloatProperty, EnumProperty, BoolProperty
    
    
    class ErrorOperator(bpy.types.Operator):
        bl_idname = "mhx.error"
        bl_label = "Error when loading MHX file"
    
        def execute(self, context):
            return {'RUNNING_MODAL'}
    
        def invoke(self, context, event):
            global theErrorLines
            maxlen = 0
            for line in theErrorLines:
                if len(line) > maxlen:
                    maxlen = len(line)
            width = 20+5*maxlen
            height = 20+5*len(theErrorLines)
            #self.report({'INFO'}, theMessage)
            wm = context.window_manager
            return wm.invoke_props_dialog(self, width=width, height=height)
    
        def draw(self, context):
            global theErrorLines
            for line in theErrorLines:        
                self.layout.label(line)
    
    def MyError(message):
        global theMessage, theErrorLines, theErrorStatus
        theMessage = message
        theErrorLines = message.split('\n')
        theErrorStatus = True
        bpy.ops.mhx.error('INVOKE_DEFAULT')
        raise NameError(theMessage)
    
    class SuccessOperator(bpy.types.Operator):
        bl_idname = "mhx.success"
        bl_label = "MHX file successfully loaded:"
        message = StringProperty()
    
        def execute(self, context):
            return {'RUNNING_MODAL'}
    
        def invoke(self, context, event):
            wm = context.window_manager
            return wm.invoke_props_dialog(self)
    
        def draw(self, context):
            self.layout.label(self.message)
    
    ###################################################################################
    #
    #    User interface
    #
    ###################################################################################
    
    
    
    
    MhxBoolProps = [
        ("enforce", "Enforce version", "Only accept MHX files of correct version", T_EnforceVersion),
        ("mesh", "Mesh", "Use main mesh", T_Mesh),
        ("proxy", "Proxies", "Use proxies", T_Proxy),
        ("armature", "Armature", "Use armature", T_Armature),
    
        #("replace", "Replace scene", "Replace scene", T_Replace),
    
        ("cage", "Cage", "Load mesh deform cage", T_Cage),
        ("clothes", "Clothes", "Include clothes", T_Clothes),
    
        #("stretch", "Stretchy limbs", "Stretchy limbs", T_Stretch),
    
        ("face", "Face shapes", "Include facial shapekeys", T_Face),
        ("shape", "Body shapes", "Include body shapekeys", T_Shape),
    
        #("symm", "Symmetric shapes", "Keep shapekeys symmetric", T_Symm),
    
        ("diamond", "Helper geometry", "Keep helper geometry", T_Diamond),
    
        ("rigify", "Rigify", "Create rigify control rig", T_Rigify),
    
    ]
    
    class ImportMhx(bpy.types.Operator, ImportHelper):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        '''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"
    
        bl_options = {'UNDO'}
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
        scale = FloatProperty(name="Scale", description="Default meter, decimeter = 1.0", default = theScale)
    
        filename_ext = ".mhx"
        filter_glob = StringProperty(default="*.mhx", options={'HIDDEN'})
    
        filepath = StringProperty(subtype='FILE_PATH')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
        for (prop, name, desc, flag) in MhxBoolProps:
            expr = '%s = BoolProperty(name="%s", description="%s", default=toggle&%s)' % (prop, name, desc, flag)
            exec(expr)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            
        def execute(self, context):
    
            global toggle, theScale, MhxBoolProps
    
            toggle = 0
            for (prop, name, desc, flag) in MhxBoolProps:
    
                expr = '(%s if self.%s else 0)' % (flag, prop)
    
                toggle |=  eval(expr)
            print("execute flags %x" % toggle)
    
            theScale = self.scale
    
            try:
                readMhxFile(self.filepath)
                bpy.ops.mhx.success('INVOKE_DEFAULT', message = self.filepath)
            except NameError:
                print("Error when loading MHX file:\n" + theMessage)
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            return {'FINISHED'}
    
        def invoke(self, context, event):
    
            global toggle, theScale, MhxBoolProps
    
            self.scale = theScale
    
            for (prop, name, desc, flag) in MhxBoolProps:
    
                expr = 'self.%s = toggle&%s' % (prop, flag)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            context.window_manager.fileselect_add(self)
            return {'RUNNING_MODAL'}
    
    
    ###################################################################################    
    #
    #    Lipsync panel
    #
    ###################################################################################    
    
    #
    #    visemes
    #
    
    stopStaringVisemes = ({
        'Rest' : [
            ('PMouth', (0,0)), 
            ('PUpLip', (0,-0.1)), 
            ('PLoLip', (0,0.1)), 
            ('PJaw', (0,0.05)), 
            ('PTongue', (0,0.0))], 
        'Etc' : [
            ('PMouth', (0,0)),
            ('PUpLip', (0,-0.1)),
            ('PLoLip', (0,0.1)),
            ('PJaw', (0,0.15)),
            ('PTongue', (0,0.0))], 
        'MBP' : [('PMouth', (-0.3,0)),
            ('PUpLip', (0,1)),
            ('PLoLip', (0,0)),
            ('PJaw', (0,0.1)),
            ('PTongue', (0,0.0))], 
        'OO' : [('PMouth', (-1.5,0)),
            ('PUpLip', (0,0)),
            ('PLoLip', (0,0)),
            ('PJaw', (0,0.2)),
            ('PTongue', (0,0.0))], 
        'O' : [('PMouth', (-1.1,0)),
            ('PUpLip', (0,0)),
            ('PLoLip', (0,0)),
            ('PJaw', (0,0.5)),
            ('PTongue', (0,0.0))], 
        'R' : [('PMouth', (-0.9,0)),
            ('PUpLip', (0,-0.2)),
            ('PLoLip', (0,0.2)),
            ('PJaw', (0,0.2)),
            ('PTongue', (0,0.0))], 
        'FV' : [('PMouth', (0,0)),
            ('PUpLip', (0,0)),
            ('PLoLip', (0,-0.8)),
            ('PJaw', (0,0.1)),
            ('PTongue', (0,0.0))], 
        'S' : [('PMouth', (0,0)),
            ('PUpLip', (0,-0.2)),
            ('PLoLip', (0,0.2)),
            ('PJaw', (0,0.05)),
            ('PTongue', (0,0.0))], 
        'SH' : [('PMouth', (-0.6,0)),
            ('PUpLip', (0,-0.5)),
            ('PLoLip', (0,0.5)),
            ('PJaw', (0,0)),
            ('PTongue', (0,0.0))], 
        'EE' : [('PMouth', (0.3,0)),
            ('PUpLip', (0,-0.3)),
            ('PLoLip', (0,0.3)),
            ('PJaw', (0,0.025)),
            ('PTongue', (0,0.0))], 
        'AH' : [('PMouth', (-0.1,0)),
            ('PUpLip', (0,-0.4)),
            ('PLoLip', (0,0)),
            ('PJaw', (0,0.35)),
            ('PTongue', (0,0.0))], 
        'EH' : [('PMouth', (0.1,0)),
            ('PUpLip', (0,-0.2)),
            ('PLoLip', (0,0.2)),
            ('PJaw', (0,0.2)),
            ('PTongue', (0,0.0))], 
        'TH' : [('PMouth', (0,0)),
            ('PUpLip', (0,-0.5)),
            ('PLoLip', (0,0.5)),
            ('PJaw', (-0.2,0.1)),
            ('PTongue', (0,-0.6))], 
        'L' : [('PMouth', (0,0)),
            ('PUpLip', (0,-0.2)),
            ('PLoLip', (0,0.2)),
            ('PJaw', (0.2,0.2)),
            ('PTongue', (0,-0.8))], 
        'G' : [('PMouth', (0,0)),
            ('PUpLip', (0,-0.1)),
            ('PLoLip', (0,0.1)),
            ('PJaw', (-0.3,0.1)),
            ('PTongue', (0,-0.6))], 
    
        'Blink' : [('PUpLid', (0,1.0)), ('PLoLid', (0,-1.0))], 
        'Unblink' : [('PUpLid', (0,0)), ('PLoLid', (0,0))], 
    })
    
    bodyLanguageVisemes = ({
        'Rest' : [
            ('PMouth', (0,0)), 
            ('PMouthMid', (0,-0.6)), 
            ('PUpLipMid', (0,0)), 
            ('PLoLipMid', (0,0)), 
            ('PJaw', (0,0)), 
            ('PTongue', (0,0))], 
        'Etc' : [
            ('PMouth', (0,0)), 
            ('PMouthMid', (0,-0.4)), 
            ('PUpLipMid', (0,0)), 
            ('PLoLipMid', (0,0)), 
            ('PJaw', (0,0)), 
            ('PTongue', (0,0))], 
        'MBP' : [
            ('PMouth', (0,0)), 
            ('PMouthMid', (0,0)), 
            ('PUpLipMid', (0,0)), 
            ('PLoLipMid', (0,0)), 
            ('PJaw', (0,0)), 
            ('PTongue', (0,0))], 
        'OO' : [
            ('PMouth', (-1.0,0)),