Skip to content
Snippets Groups Projects
io_import_scene_mhx.py 132 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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' : [
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
            ('LipsPart', 0.6), 
            ('UpLipsMidHeight', 0), 
            ('LoLipsMidHeight', 0), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
            ('LipsPart', 0.4), 
            ('UpLipsMidHeight', 0), 
            ('LoLipsMidHeight', 0), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0), 
            ('LoLipsMidHeight', 0), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 1.0), 
            ('MouthNarrow_R', 1.0), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0), 
            ('LoLipsMidHeight', 0), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0.4), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0.9), 
            ('MouthNarrow_R', 0.9), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0), 
            ('LoLipsMidHeight', 0), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0.8), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0.5), 
            ('MouthNarrow_R', 0.5), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0.2), 
            ('LoLipsMidHeight', -0.2), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0.2), 
            ('MouthWidth_R', 0.2), 
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
    
            ('LipsPart', 1.0), 
            ('UpLipsMidHeight', 0), 
            ('LoLipsMidHeight', 0.3), 
            ('LoLipsIn', 0.6),
            ('MouthOpen', 0), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0.5), 
            ('LoLipsMidHeight', -0.7), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0.8), 
            ('MouthWidth_R', 0.8), 
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
    
            ('LoLipsIn', 0),
            ('MouthOpen', 0), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0.2), 
            ('MouthWidth_R', 0.2), 
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
    
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0.6), 
            ('LoLipsMidHeight', -0.6), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0.5), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0.4), 
            ('LoLipsMidHeight', 0), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0.7), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0.5), 
            ('LoLipsMidHeight', -0.6), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0.25), 
            ('TongueBackHeight', 0),
            ('TongueHeight', 0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0), 
            ('LoLipsMidHeight', 0), 
            ('LoLipsIn', 0),
            ('MouthOpen', 0.2), 
            ('TongueBackHeight', 1.0),
            ('TongueHeight', 1.0)
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0.5), 
            ('LoLipsMidHeight', -0.5), 
            ('LoLipsIn', 0),
            ('MouthOpen', -0.2), 
            ('TongueBackHeight', 1.0),
            ('TongueHeight', 1.0),
            ], 
    
            ('MouthWidth_L', 0), 
            ('MouthWidth_R', 0), 
    
            ('MouthNarrow_L', 0), 
            ('MouthNarrow_R', 0), 
            ('LipsPart', 0), 
            ('UpLipsMidHeight', 0.5), 
            ('LoLipsMidHeight', -0.5), 
            ('LoLipsIn', 0),
            ('MouthOpen', -0.2), 
            ('TongueBackHeight', 1.0),
            ('TongueHeight', 0),
            ], 
    
        'Blink' : [
            ('UpLidUp_L', 1), 
            ('UpLidUp_R', 1), 
            ('LoLidDown_L', 1),
            ('LoLidDown_R', 1)
            ], 
            
        'Unblink' : [
            ('UpLidUp_L', 0), 
            ('UpLidUp_R', 0), 
            ('LoLidDown_L', 0),
            ('LoLidDown_R', 0)
            ], 
    
    VisemePanelBones = {
        'MouthOpen' :       ('PJaw', (0,0.25)),
        'UpLipsMidHeight' : ('PUpLipMid', (0,-0.25)),
        'LoLipsMidHeight' : ('PLoLipMid', (0,-0.25)),
        'LoLipsIn':         ('PLoLipMid', (-0.25,0)),
    
        'MouthWidth_L' :    ('PMouth_L', (0.25,0)),
        'MouthWidth_R' :    ('PMouth_R', (-0.25,0)),
    
        'MouthNarrow_L' :   ('PMouth_L', (-0.25,0)),
        'MouthNarrow_R' :   ('PMouth_R', (0.25,0)),
        'LipsPart' :        ('PMouthMid', (0, -0.25)),    
        'TongueBackHeight': ('PTongue', (-0.25, 0)),
        'TongueHeight' :    ('PTongue', (0, -0.25)),
        
        'UpLidUp_L' :       ('PUpLid_L', (0,1.0)),
        'UpLidUp_R' :       ('PUpLid_R', (0,1.0)),
        'LoLidDown_L' :     ('PLoLid_L', (0,-1.0)), 
        'LoLidDown_R' :     ('PLoLid_R', (0,-1.0)), 
    }    
    
    
    VisemeList = [
        ('Rest', 'Etc', 'AH'),
        ('MBP', 'OO', 'O'),
        ('R', 'FV', 'S'),
        ('SH', 'EE', 'EH'),
        ('TH', 'L', 'G')
    ]
    
    
    #
    #   makeVisemes(ob, scn):
    #   class VIEW3D_OT_MhxMakeVisemesButton(bpy.types.Operator):
    #
    
    def makeVisemes(ob, scn):
        if ob.type != 'MESH':
            print("Active object %s is not a mesh" % ob)
            return
        if not ob.data.shape_keys:
            print("%s has no shapekeys" % ob)
            return
        try:
            ob.data.shape_keys.key_blocks["VIS_Rest"]
            print("Visemes already created")
            return
        except:
            pass        
    
        verts = ob.data.vertices            
    
        for (vis,shapes) in bodyLanguageVisemes.items():
    
            if vis in ['Blink', 'Unblink']:
                continue
            vkey = ob.shape_key_add(name="VIS_%s" % vis)  
            print(vkey.name)
            for n,v in enumerate(verts):
                vkey.data[n].co = v.co
    
            for (name,value) in shapes:
                if name[-2:] == "_R":
                    continue
                skey = ob.data.shape_keys.key_blocks[name]
                factor = 0.75*value
                for n,v in enumerate(verts):
                    vkey.data[n].co += factor*(skey.data[n].co - v.co)
    
    class VIEW3D_OT_MhxMakeVisemesButton(bpy.types.Operator):
        bl_idname = "mhx.make_visemes"
        bl_label = "Generate viseme shapekeys"
    
        bl_options = {'UNDO'}
    
    
        def execute(self, context):
            makeVisemes(context.object, context.scene)
            return{'FINISHED'}    
    
    MohoVisemes = dict({
    
        'rest' : 'Rest', 
        'etc' : 'Etc', 
        'AI' : 'AH', 
        'O' : 'O', 
        'U' : 'OO', 
        'WQ' : 'AH', 
        'L' : 'L', 
        'E' : 'EH', 
        'MBP' : 'MBP', 
        'FV' : 'FV', 
    })
    
    
    MagpieVisemes = dict({
    
        "CONS" : "Etc", 
        "AI" : 'AH', 
        "E" : "EH", 
        "O" : "O", 
        "UW" : "AH", 
        "MBP" : "MBP", 
        "L" : "L", 
        "FV" : "FV", 
        "Sh" : "SH", 
    
    })
    
    #
    #    setViseme(context, vis, setKey, frame):
    #    setBoneLocation(context, pbone, loc, mirror, setKey, frame):
    #    class VIEW3D_OT_MhxVisemeButton(bpy.types.Operator):
    #
    
    def getVisemeSet(context, rig):
        try:
            visset = rig['MhxVisemeSet']
        except:
            return bodyLanguageVisemes
        if visset == 'StopStaring':
            return stopStaringVisemes
        elif visset == 'BodyLanguage':
            return bodyLanguageVisemes
        else:
    
            raise MhxError("Unknown viseme set %s" % visset)
    
    def setVisemeAlpha7(context, vis, visemes, setKey, frame):
    
        (rig, mesh) = getMhxRigMesh(context.object)
        isPanel = False
        isProp = False
        shapekeys = None
        scale = 0.75
    
        if rig.MhxShapekeyDrivers:
    
                scale *= rig.pose.bones['PFace'].bone.length
                isPanel = True
    
                isProp = True
        elif mesh:
            shapekeys = mesh.data.shape_keys.key_blocks
    
        for (skey, value) in visemes[vis]:
            if isPanel:
                (b, (x,z)) = VisemePanelBones[skey]
                loc = mathutils.Vector((float(x*value),0,float(z*value)))            
                pb = rig.pose.bones[b]
                pb.location = loc*scale
                if setKey or context.tool_settings.use_keyframe_insert_auto:
                    for n in range(3):
                        pb.keyframe_insert('location', index=n, frame=frame, group=pb.name)
            elif isProp:
    
                skey = 'Mhf' + skey
    
                try:
                    prop = rig[skey]
                except:
                    continue
                rig[skey] = value*scale
                if setKey or context.tool_settings.use_keyframe_insert_auto:
    
                    rig.keyframe_insert('["%s"]' % skey, frame=frame, group="Visemes")    
    
            elif shapekeys:
                try:
                    shapekeys[skey].value = value*scale
                except:
                    continue
                if setKey or context.tool_settings.use_keyframe_insert_auto:
                    shapekeys[skey].keyframe_insert("value", frame=frame)            
    
        updatePose(context)
    
    
    class VIEW3D_OT_MhxVisemeButton(bpy.types.Operator):
        bl_idname = 'mhx.pose_viseme'
        bl_label = 'Viseme'
    
        bl_options = {'UNDO'}
    
        viseme = StringProperty()
    
        def invoke(self, context, event):
    
            (rig, mesh) = getMhxRigMesh(context.object)
            visemes = getVisemeSet(context, rig)
            setVisemeAlpha7(context, self.viseme, visemes, False, context.scene.frame_current)
    
    
    def readLipsync(context, filepath, offs, struct):
    
        if rig.MhAlpha8:
            props = getProps(rig, "Mhv")
            visemes = {}
            oldKeys = []
            for prop in props:
                dummy,units = getUnitsFromString("x;"+rig[prop])
                visemes[prop] = units
            props = getProps(rig, "Mhsmouth")
            auto = context.tool_settings.use_keyframe_insert_auto
            auto = True
            factor = rig.MhxStrength
    
        else:
            visemes = getVisemeSet(context, rig)    
    
        context.scene.objects.active = rig
        bpy.ops.object.mode_set(mode='POSE')    
    
        for line in fp:
            words= line.split()
            if len(words) < 2:
    
                vis = "Mhv" + struct[words[1]]
                frame = int(words[0])+offs
            if rig.MhAlpha8:
    
                setMhmProps(rig, shapekeys, "Mhsmouth", visemes[vis], factor, auto, frame)
    
            else:
                setVisemeAlpha7(context, vis, visemes, True, frame)
    
        updatePose(context)
    
        print("Lipsync file %s loaded" % filepath)
    
    class VIEW3D_OT_MhxMohoButton(bpy.types.Operator, ImportHelper):
        bl_idname = "mhx.pose_load_moho"
        bl_label = "Load Moho (.dat)"
    
        bl_options = {'UNDO'}
    
        filename_ext = ".dat"
        filter_glob = StringProperty(default="*.dat", options={'HIDDEN'})
        filepath = StringProperty(subtype='FILE_PATH')    
    
    
        def execute(self, context):        
            readLipsync(context, self.properties.filepath, context.scene.frame_start - 1, MohoVisemes)        
    
            return{'FINISHED'}    
    
        def invoke(self, context, event):
            context.window_manager.fileselect_add(self)
            return {'RUNNING_MODAL'}    
    
    
    class MhxLipsyncPanel(bpy.types.Panel):
        bl_label = "MHX Lipsync"
        bl_space_type = "VIEW_3D"
        bl_region_type = "UI"
    
        bl_options = {'DEFAULT_CLOSED'}
    
        @classmethod
        def poll(cls, context):
    
            return pollMhx(context.object)
    
                return
            layout = self.layout        
    
            if rig.MhAlpha8:
    
                layout.operator("mhx.pose_reset_expressions", text="Reset visemes").prefix="Mhsmouth"
                layout.operator("mhx.pose_key_expressions", text="Key visemes").prefix="Mhsmouth"
    
                layout.prop(rig, "MhxStrength")
                layout.separator()
    
                    if n % 3 == 0:
                        row = layout.row()
                        n = 0
                    row.operator("mhx.pose_mhm", text=prop[3:]).data="Mhsmouth;"+rig[prop]        
                    n += 1
                while n % 3 != 0:
                    row.label("")
                    n += 1
                layout.separator()
                row = layout.row()
                row.operator("mhx.pose_mhm", text="Blink").data="Mhsmouth;eye_left_closure:1;eye_right_closure:1"        
                row.operator("mhx.pose_mhm", text="Unblink").data="Mhsmouth;eye_left_closure:0;eye_right_closure:0"        
            else:   
                layout.label("Lipsync disabled for alpha7 mhx files")
                return
    
                for (vis1, vis2, vis3) in VisemeList:
                    row = layout.row()
                    row.operator("mhx.pose_viseme", text=vis1).viseme = vis1
                    row.operator("mhx.pose_viseme", text=vis2).viseme = vis2
                    row.operator("mhx.pose_viseme", text=vis3).viseme = vis3
                layout.separator()
                row = layout.row()
                row.operator("mhx.pose_viseme", text="Blink").viseme = 'Blink'
                row.operator("mhx.pose_viseme", text="Unblink").viseme = 'Unblink'
                layout.separator()
                layout.operator("mhx.make_visemes")
    
                
            layout.separator()
            row = layout.row()
    
            #layout.operator("mhx.update")
    
    #   updatePose(context):
    
    #   class VIEW3D_OT_MhxUpdateButton(bpy.types.Operator):
    #
    
    
    def updatePose(context):
        scn = context.scene
    
        bpy.ops.object.posemode_toggle()
        bpy.ops.object.posemode_toggle()
    
        return
    
    class VIEW3D_OT_MhxUpdateButton(bpy.types.Operator):
        bl_idname = "mhx.update"
        bl_label = "Update"
    
        def execute(self, context):
    
            updatePose(context)
    
    
    ###################################################################################    
    #
    
    #
    ###################################################################################    
    
    class VIEW3D_OT_MhxResetExpressionsButton(bpy.types.Operator):
        bl_idname = "mhx.pose_reset_expressions"
        bl_label = "Reset expressions"
    
        bl_options = {'UNDO'}
    
    
        def execute(self, context):
    
            shapekeys = getMhmShapekeys(rig, mesh)
            clearMhmProps(rig, shapekeys, self.prefix, context.tool_settings.use_keyframe_insert_auto, context.scene.frame_current)
    
            updatePose(context)
    
            return{'FINISHED'}    
    
    
    class VIEW3D_OT_MhxKeyExpressionsButton(bpy.types.Operator):
        bl_idname = "mhx.pose_key_expressions"
        bl_label = "Key expressions"
    
        bl_options = {'UNDO'}
    
    
        def execute(self, context):
    
            props = getProps(rig, self.prefix)
    
            frame = context.scene.frame_current
    
    Thomas Larsson's avatar
    Thomas Larsson committed
                rig.keyframe_insert('["%s"]'%prop, frame=frame)
    
            updatePose(context)
    
    
    class VIEW3D_OT_MhxPinExpressionButton(bpy.types.Operator):
        bl_idname = "mhx.pose_pin_expression"
        bl_label = "Pin"
    
        bl_options = {'UNDO'}
    
    
        def execute(self, context):
    
            words = self.data.split(";")
            prefix = words[0]
            expression = words[1]
            
            props = getProps(rig, prefix)
    
            if context.tool_settings.use_keyframe_insert_auto:
                frame = context.scene.frame_current
    
                        rig[prop] = 1.0
                    else:
                        rig[prop] = 0.0
                    if abs(rig[prop] - old) > 1e-3:
    
    Thomas Larsson's avatar
    Thomas Larsson committed
                        rig.keyframe_insert('["%s"]'%prop, frame=frame)
    
                        rig[prop] = 1.0
                    else:
                        rig[prop] = 0.0
    
            updatePose(context)
    
    def getMhmShapekeys(rig, mesh):
        if rig.MhxShapekeyDrivers:
            return None
        else:
            return mesh.data.shape_keys.key_blocks
        
    
    def setMhmProps(rig, shapekeys, prefix, units, factor, auto, frame):
        clearMhmProps(rig, shapekeys, prefix, auto, frame)
    
        for (prop, value) in units:
    
            if shapekeys:
                skey = prop[3:].replace("_","-")
                shapekeys[skey].value = factor*value
                if auto:
                    shapekeys[skey].keyframe_insert("value", frame=frame)            
            else:
                rig[prop] = factor*value
                if auto:
    
    Thomas Larsson's avatar
    Thomas Larsson committed
                    rig.keyframe_insert('["%s"]'%prop, frame=frame)    
    
    def clearMhmProps(rig, shapekeys, prefix, auto, frame):
    
        props = getProps(rig, prefix)
        for prop in props:
    
            if shapekeys:
                skey = prop[3:].replace("_","-")
                shapekeys[skey].value = 0.0
                if auto:
                    shapekeys[skey].keyframe_insert("value", frame=frame)            
            else:
                rig[prop] = 0.0
                if auto:
    
    Thomas Larsson's avatar
    Thomas Larsson committed
                    rig.keyframe_insert('["%s"]'%prop, frame=frame)   
    
    
    
    def getUnitsFromString(string):    
    
        prefix = words[0]
    
        for word in words[1:]:
    
            if word == "":
                continue
            unit = word.split(":") 
            prop = "Mhs" + unit[0]
            value = float(unit[1])
    
            units.append((prop, value))
        return prefix,units            
    
                
    
    class VIEW3D_OT_MhxMhmButton(bpy.types.Operator):
        bl_idname = "mhx.pose_mhm"
        bl_label = "Mhm"
        bl_options = {'UNDO'}
        data = StringProperty()
    
        def execute(self, context):   
            rig,mesh = getMhxRigMesh(context.object)
    
            auto = context.tool_settings.use_keyframe_insert_auto
            frame = context.scene.frame_current
    
            prefix,units = getUnitsFromString(self.data)        
    
            setMhmProps(rig, shapekeys, prefix, units, rig.MhxStrength, auto, frame)
    
        props = []
        for prop in rig.keys():
            if prop.startswith(prefix):
    
        props.sort()            
        return props
    
    
    
    class MhxExpressionsPanel(bpy.types.Panel):
        bl_label = "MHX Expressions"
        bl_space_type = "VIEW_3D"
        bl_region_type = "UI"
    
        bl_options = {'DEFAULT_CLOSED'}
    
        @classmethod
        def poll(cls, context):
            return pollMhx(context.object)
    
        def draw(self, context):
            layout = self.layout
            rig,mesh = getMhxRigMesh(context.object)
            if not rig:
    
            layout.operator("mhx.pose_reset_expressions").prefix="Mhs"
            layout.operator("mhx.pose_key_expressions").prefix="Mhs"
    
            layout.prop(rig, "MhxStrength")
            layout.separator()
            for prop in exprs:
    
                layout.operator("mhx.pose_mhm", text=prop[3:]).data="Mhs;"+rig[prop]
    
    def drawShapePanel(self, context, prefix, name):
        layout = self.layout
        rig,mesh = getMhxRigMesh(context.object)
        if not rig:
            print("No MHX rig found")
            return
        if not rig.MhxShapekeyDrivers:
            layout.label("No shapekey drivers.")
            layout.label("Set %s values in mesh context instead" % name)
            return
        props = getProps(rig, prefix)
        if not props:
            layout.label("No %ss found" % name)
            return
            
        layout.operator("mhx.pose_reset_expressions", text="Reset %ss" % name).prefix=prefix
    
    Thomas Larsson's avatar
    Thomas Larsson committed
        layout.operator("mhx.pose_key_expressions", text="Key %ss" % name).prefix=prefix
    
        #layout.operator("mhx.update")
    
        layout.separator()
        for prop in props:
            row = layout.split(0.85)
    
            row.prop(rig, '["%s"]' % prop, text=prop[3:])
    
            row.operator("mhx.pose_pin_expression", text="", icon='UNPINNED').data = (prefix + ";" + prop)
        return
    
    
    
    class MhxExpressionUnitsPanel(bpy.types.Panel):
    
    Thomas Larsson's avatar
    Thomas Larsson committed
        bl_label = "MHX Expression Tuning"
    
        bl_space_type = "VIEW_3D"
        bl_region_type = "UI"
        bl_options = {'DEFAULT_CLOSED'}
        
    
        @classmethod
        def poll(cls, context):
    
            return pollMhx(context.object)
    
            drawShapePanel(self, context, "Mhs", "expression")
    
    
    class MhxCustomShapePanel(bpy.types.Panel):
        bl_label = "MHX Custom Shapes"
        bl_space_type = "VIEW_3D"
        bl_region_type = "UI"
        bl_options = {'DEFAULT_CLOSED'}
        
        @classmethod
        def poll(cls, context):
            return pollMhx(context.object)
    
        def draw(self, context):
            drawShapePanel(self, context, "Mhc", "custom shape")
    
    def getPoseMatrix(mat, pb):
        restInv = pb.bone.matrix_local.inverted()
    
            parInv = pb.parent.matrix.inverted()
            parRest = pb.parent.bone.matrix_local
            return restInv * (parRest * (parInv * mat))
    
            return restInv * mat
    
            
    def getGlobalMatrix(mat, pb):
        gmat = pb.bone.matrix_local * mat
        if pb.parent:
            parMat = pb.parent.matrix
            parRest = pb.parent.bone.matrix_local
            return parMat * (parRest.inverted() * gmat)
        else:
            return gmat
    
    def matchPoseTranslation(pb, fkPb, auto):
        mat = getPoseMatrix(fkPb.matrix, pb)
        insertLocation(pb, mat, auto)
        
    
    def insertLocation(pb, mat, auto):    
        pb.location = mat.to_translation()
        if auto:
            pb.keyframe_insert("location", group=pb.name)
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.mode_set(mode='POSE')
    
    def matchPoseRotation(pb, fkPb, auto):
        mat = getPoseMatrix(fkPb.matrix, pb)
        insertRotation(pb, mat, auto)
        
    
    def insertRotation(pb, mat, auto):    
    
        q = mat.to_quaternion()
        if pb.rotation_mode == 'QUATERNION':
            pb.rotation_quaternion = q
    
            if auto:
                pb.keyframe_insert("rotation_quaternion", group=pb.name)
    
        else:
            pb.rotation_euler = q.to_euler(pb.rotation_mode)
    
            if auto:
                pb.keyframe_insert("rotation_euler", group=pb.name)
    
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.mode_set(mode='POSE')
    
    
    
    def matchPoseReverse(pb, fkPb, auto):
    
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.mode_set(mode='POSE')
    
        gmat = fkPb.matrix * Matrix.Rotation(math.pi, 4, 'Z')
        offs = pb.bone.length * fkPb.matrix.col[1]    
        gmat[0][3] += offs[0]
        gmat[1][3] += offs[1]
        gmat[2][3] += offs[2]    
        mat = getPoseMatrix(gmat, pb)
        pb.matrix_basis = mat
        insertLocation(pb, mat, auto)
        insertRotation(pb, mat, auto)
        
    
    def matchPoseScale(pb, fkPb, auto):
        mat = getPoseMatrix(fkPb.matrix, pb)
        pb.scale = mat.to_scale()
        if auto:
            pb.keyframe_insert("scale", group=pb.name)
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.mode_set(mode='POSE')
    
        auto = context.scene.tool_settings.use_keyframe_insert_auto
        print("Snap FK Arm%s" % suffix)
    
    Thomas Larsson's avatar
    Thomas Larsson committed
        snapIk,cnsIk = getSnapBones(rig, "ArmIK", suffix)
        (uparmIk, loarmIk, elbow, elbowPt, wrist) = snapIk
        snapFk,cnsFk = getSnapBones(rig, "ArmFK", suffix)
        (uparmFk, loarmFk, elbowPtFk, handFk) = snapFk
        muteConstraints(cnsFk, True)
    
        matchPoseRotation(uparmFk, uparmFk, auto)
        matchPoseScale(uparmFk, uparmFk, auto)
    
        matchPoseRotation(loarmFk, loarmFk, auto)
        matchPoseScale(loarmFk, loarmFk, auto)
    
            matchPoseRotation(handFk, wrist, auto)
            matchPoseScale(handFk, wrist, auto)
    
    Thomas Larsson's avatar
    Thomas Larsson committed
    
        muteConstraints(cnsFk, False)
    
        scn = context.scene
        auto = scn.tool_settings.use_keyframe_insert_auto
        print("Snap IK Arm%s" % suffix)
    
    Thomas Larsson's avatar
    Thomas Larsson committed
        snapIk,cnsIk = getSnapBones(rig, "ArmIK", suffix)
        (uparmIk, loarmIk, elbow, elbowPt, wrist) = snapIk
        snapFk,cnsFk = getSnapBones(rig, "ArmFK", suffix)
        (uparmFk, loarmFk, elbowPtFk, handFk) = snapFk
        muteConstraints(cnsIk, True)
    
        #rig["MhaElbowFollowsShoulder" + suffix] = False
        #rig["MhaElbowFollowsWrist" + suffix] = False
    
        
        matchPoseTranslation(wrist, handFk, auto)
        matchPoseRotation(wrist, handFk, auto)  
        matchPoseTranslation(elbow, elbowPtFk, auto)
        matchPoseTranslation(elbowPt, elbowPtFk, auto)
        setInverse(rig, elbowPt)
    
    Thomas Larsson's avatar
    Thomas Larsson committed
        muteConstraints(cnsIk, False)
    
        auto = context.scene.tool_settings.use_keyframe_insert_auto
    
        print("Snap FK Leg%s" % suffix)
    
    Thomas Larsson's avatar
    Thomas Larsson committed
        snapIk,cnsIk = getSnapBones(rig, "LegIK", suffix)
        (uplegIk, lolegIk, kneePt, ankleIk, legIk, legFk, footIk, toeIk) = snapIk
        snapFk,cnsFk = getSnapBones(rig, "LegFK", suffix)
        (uplegFk, lolegFk, kneePtFk, footFk, toeFk) = snapFk
        muteConstraints(cnsFk, True)
        
        if not rig["MhaLegIkToAnkle" + suffix]:
            matchPoseRotation(footFk, footFk, auto)
            matchPoseRotation(toeFk, toeFk, auto)
        
    
        matchPoseRotation(uplegFk, uplegFk, auto)
        matchPoseScale(uplegFk, uplegFk, auto)
    
        matchPoseRotation(lolegFk, lolegFk, auto)
        matchPoseScale(lolegFk, lolegFk, auto)
    
    Thomas Larsson's avatar
    Thomas Larsson committed
        
        muteConstraints(cnsFk, False)
    
    def ik2fkLeg(context, suffix):
        rig = context.object
    
        scn = context.scene