Skip to content
Snippets Groups Projects
io_import_scene_mhx.py 127 KiB
Newer Older
def parseDefineProperty(args, tokens):
    expr = "bpy.types.Object.%s = %sProperty" % (args[0], args[1])
    c = '('
    for option in args[2:]:
        expr += "%s %s" % (c, option)
        c = ','
    expr += ')'
    #print(expr)
    exec(expr)
    #print("Done")
    return

#
#    correctRig(args):
#

def correctRig(args):
    human = args[0]
    print("CorrectRig %s" % human)    
    try:
        ob = loadedData['Object'][human]
    except:
Luca Bonavita's avatar
Luca Bonavita committed
        return
    ob.MhxShapekeyDrivers = (toggle&T_Shapekeys and toggle&T_ShapeDrivers)
    bpy.context.scene.objects.active = ob
    bpy.ops.object.mode_set(mode='POSE')
    amt = ob.data
    cnslist = []
    for pb in ob.pose.bones:
        pb.bone.select = False
        for cns in pb.constraints:
            if cns.type == 'CHILD_OF':
                cnslist.append((pb, cns, cns.influence))
                cns.influence = 0

    for (pb, cns, inf) in cnslist:
        amt.bones.active = pb.bone
        cns.influence = 1
        #print("Childof %s %s %s %.2f" % (amt.name, pb.name, cns.name, inf))
        bpy.ops.constraint.childof_clear_inverse(constraint=cns.name, owner='BONE')
        bpy.ops.constraint.childof_set_inverse(constraint=cns.name, owner='BONE')
        cns.influence = 0

    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")
            if f.material_index >= invisioNum:
                for vn in f.vertices:
                    me.vertices[vn].select = True
    else:        
        for f in me.faces:    
            if f.material_index >= invisioNum:
                for vn in f.vertices:
                    me.vertices[vn].select = True
    if BMeshAware and toggle&T_CrashSafe:     
        theMessage = "\n  *** WARNING ***\nHelper deletion turned off due to Blender crash.\nHelpers can be deleted by deleting all selected vertices in Edit mode\n     **********\n"
        print(theMessage)
    else:
        bpy.ops.object.mode_set(mode='EDIT')
        print("Do delete")
        bpy.ops.mesh.delete(type='VERT')
        print("Verts deleted")
        bpy.ops.object.mode_set(mode='OBJECT')
        print("Back to object mode")
Luca Bonavita's avatar
Luca Bonavita committed
    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(
        "Unrecognized expression %s.\n"  % expr +
        "This can mean that Blender's python API has changed\n" +
        "since the MHX file was exported. Try to export again\n" +
        "from an up-to-date MakeHuman nightly build.\n" +
        "Alternatively, your Blender version may be obsolete.\n" +
        "Download an up-to-date version from www.graphicall.org")
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
#
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)
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)
        boneHideLayers = 0
    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.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:
            return context.object.MhxRigify
        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 MhxError(theMessage)

class MhxError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

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 + theMessage)

###################################################################################
#
#    User interface
#
###################################################################################


MhxBoolProps = [
    ("enforce", "Enforce version", "Only accept MHX files of correct version", T_EnforceVersion),
    #("crash_safe", "Crash-safe", "Disable features that have caused Blender crashes", T_CrashSafe),
    ("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),
    ("shapekeys", "Shapekeys", "Include shapekeys", T_Shapekeys),
    ("shapedrivers", "Shapekey drivers", "Include shapekey drivers", T_ShapeDrivers),
    #("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):
    """Import from MHX file format (.mhx)"""
Luca Bonavita's avatar
Luca Bonavita committed
    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
        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)
            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)),