Skip to content
Snippets Groups Projects
io_import_scene_mhx.py 133 KiB
Newer Older
  • Learn to ignore specific revisions
  •         theScale = self.scale
    
            #filepathname = self.filepath.encode('utf-8', 'strict')
    
                if not context.user_preferences.system.use_scripts_auto_execute:
                    MyError("Auto Run Python Scripts must be turned on.\nIt is found under\n File > User Preferences > File")
    
                readMhxFile(self.filepath)
    
                #bpy.ops.mhx.success('INVOKE_DEFAULT', message = self.filepath)
    
                print("Error when loading MHX file %s:\n" % self.filepath + theMessage)
    
            if self.advanced:
                writeDefaults()
                self.advanced = False
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            return {'FINISHED'}
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def invoke(self, context, event):
    
            global toggle, theScale, MhxBoolProps
    
            self.scale = theScale
    
            for (prop, name, desc, flag) in MhxBoolProps:
    
                expr = 'self.%s = (toggle&%s != 0)' % (prop, flag)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            context.window_manager.fileselect_add(self)
            return {'RUNNING_MODAL'}
    
    ###################################################################################
    
    ###################################################################################
    
    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)),
    
        'MBP' : [('PMouth', (-0.3,0)),
            ('PUpLip', (0,1)),
            ('PLoLip', (0,0)),
            ('PJaw', (0,0.1)),
    
        'OO' : [('PMouth', (-1.5,0)),
            ('PUpLip', (0,0)),
            ('PLoLip', (0,0)),
            ('PJaw', (0,0.2)),
    
        'O' : [('PMouth', (-1.1,0)),
            ('PUpLip', (0,0)),
            ('PLoLip', (0,0)),
            ('PJaw', (0,0.5)),
    
        'R' : [('PMouth', (-0.9,0)),
            ('PUpLip', (0,-0.2)),
            ('PLoLip', (0,0.2)),
            ('PJaw', (0,0.2)),
    
        'FV' : [('PMouth', (0,0)),
            ('PUpLip', (0,0)),
            ('PLoLip', (0,-0.8)),
            ('PJaw', (0,0.1)),
    
        'S' : [('PMouth', (0,0)),
            ('PUpLip', (0,-0.2)),
            ('PLoLip', (0,0.2)),
            ('PJaw', (0,0.05)),
    
        'SH' : [('PMouth', (-0.6,0)),
            ('PUpLip', (0,-0.5)),
            ('PLoLip', (0,0.5)),
            ('PJaw', (0,0)),
    
        'EE' : [('PMouth', (0.3,0)),
            ('PUpLip', (0,-0.3)),
            ('PLoLip', (0,0.3)),
            ('PJaw', (0,0.025)),
    
        'AH' : [('PMouth', (-0.1,0)),
            ('PUpLip', (0,-0.4)),
            ('PLoLip', (0,0)),
            ('PJaw', (0,0.35)),
    
        'EH' : [('PMouth', (0.1,0)),
            ('PUpLip', (0,-0.2)),
            ('PLoLip', (0,0.2)),
            ('PJaw', (0,0.2)),
    
        'TH' : [('PMouth', (0,0)),
            ('PUpLip', (0,-0.5)),
            ('PLoLip', (0,0.5)),
            ('PJaw', (-0.2,0.1)),
    
        'L' : [('PMouth', (0,0)),
            ('PUpLip', (0,-0.2)),
            ('PLoLip', (0,0.2)),
            ('PJaw', (0.2,0.2)),
    
        'G' : [('PMouth', (0,0)),
            ('PUpLip', (0,-0.1)),
            ('PLoLip', (0,0.1)),
            ('PJaw', (-0.3,0.1)),
    
        '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),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0.4),
            ('UpLipsMidHeight', 0),
            ('LoLipsMidHeight', 0),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0),
            ('LoLipsMidHeight', 0),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 1.0),
            ('MouthNarrow_R', 1.0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0),
            ('LoLipsMidHeight', 0),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0.9),
            ('MouthNarrow_R', 0.9),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0),
            ('LoLipsMidHeight', 0),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0.5),
            ('MouthNarrow_R', 0.5),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0.2),
            ('LoLipsMidHeight', -0.2),
    
            ('MouthWidth_L', 0.2),
            ('MouthWidth_R', 0.2),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 1.0),
            ('UpLipsMidHeight', 0),
            ('LoLipsMidHeight', 0.3),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0.5),
            ('LoLipsMidHeight', -0.7),
    
            ('MouthWidth_L', 0.8),
            ('MouthWidth_R', 0.8),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 1.0),
            ('LoLipsMidHeight', 0),
    
            ('MouthWidth_L', 0.2),
            ('MouthWidth_R', 0.2),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0.6),
            ('LoLipsMidHeight', -0.6),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0.4),
            ('LoLipsMidHeight', 0),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0.5),
            ('LoLipsMidHeight', -0.6),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0),
            ('LoLipsMidHeight', 0),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0.5),
            ('LoLipsMidHeight', -0.5),
    
            ('MouthWidth_L', 0),
            ('MouthWidth_R', 0),
            ('MouthNarrow_L', 0),
            ('MouthNarrow_R', 0),
            ('LipsPart', 0),
            ('UpLipsMidHeight', 0.5),
            ('LoLipsMidHeight', -0.5),
    
    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)),
    
        '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:
    
        for (vis,shapes) in bodyLanguageVisemes.items():
    
            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)
    
    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
    
        context.scene.objects.active = rig
    
        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)
    
    
    
    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)
    
            if rig.MhAlpha8:
    
                if not visemes:
                    layout.label("No visemes found")
                    return
    
                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)
    
    
    
    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]
    
            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)
    
    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)
    
                    rig.keyframe_insert('["%s"]'%prop, frame=frame)
    
        prefix = words[0]
    
        for word in words[1:]:
    
            prop = "Mhs" + unit[0]
            value = float(unit[1])
    
            units.append((prop, value))
    
    
    class VIEW3D_OT_MhxMhmButton(bpy.types.Operator):
        bl_idname = "mhx.pose_mhm"
        bl_label = "Mhm"
        bl_options = {'UNDO'}
        data = StringProperty()
    
    
            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):
    
        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")
    
        restInv = pb.bone.matrix_local.inverted()
    
            parInv = pb.parent.matrix.inverted()
            parRest = pb.parent.bone.matrix_local
    
            return restInv * (parRest * (parInv * gmat))
    
    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, src, auto):
        pmat = getPoseMatrix(src.matrix, pb)
        insertLocation(pb, pmat, 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, src, auto):
        pmat = getPoseMatrix(src.matrix, pb)
        insertRotation(pb, pmat, auto)
    
    
    def printMatrix(string,mat):
        print(string)
        for i in range(4):
            print("    %.4g %.4g %.4g %.4g" % tuple(mat[i]))
    
        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 matchIkLeg(legIk, toeFk, mBall, mToe, mHeel, auto):
        rmat = toeFk.matrix.to_3x3()
        tHead = Vector(toeFk.matrix.col[3][:3])
        ty = rmat.col[1]
        tail = tHead + ty * toeFk.bone.length
    
        zBall = mBall.matrix.col[3][2]
        zToe = mToe.matrix.col[3][2]
        zHeel = mHeel.matrix.col[3][2]
    
        x = Vector(rmat.col[0])
        y = Vector(rmat.col[1])
        z = Vector(rmat.col[2])
    
        if zHeel > zBall and zHeel > zToe:
            # 1. foot.ik is flat
            if abs(y[2]) > abs(z[2]):
                y = -z
            y[2] = 0
        else:
            # 2. foot.ik starts at heel
            hHead = Vector(mHeel.matrix.col[3][:3])
            y = tail - hHead
    
        y.normalize()
        x -= x.dot(y)*y
        x.normalize()
        z = x.cross(y)
        head = tail - y * legIk.bone.length
    
        # Create matrix
        gmat = Matrix()
        gmat.col[0][:3] = x
        gmat.col[1][:3] = y
        gmat.col[2][:3] = z
        gmat.col[3][:3] = head
        pmat = getPoseMatrix(gmat, legIk)
    
        insertLocation(legIk, pmat, auto)
        insertRotation(legIk, pmat, auto)
    
    
    
    def matchPoleTarget(pb, above, below, auto):
        x = Vector(above.matrix.col[1][:3])
        y = Vector(below.matrix.col[1][:3])
        p0 = Vector(below.matrix.col[3][:3])
        n = x.cross(y)
        if abs(n.length) > 1e-4:
            z = x - y
            n = n/n.length
            z -= z.dot(n)*n
            p = p0 + z/z.length*3.0
        else:
            p = p0
        gmat = Matrix.Translation(p)
        pmat = getPoseMatrix(gmat, pb)