Skip to content
Snippets Groups Projects
io_import_scene_mhx.py 136 KiB
Newer Older
  • Learn to ignore specific revisions
  •         #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:
    
                setattr(self, prop, mhxEval('(toggle&%s != 0)' % flag))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            context.window_manager.fileselect_add(self)
            return {'RUNNING_MODAL'}
    
    ###################################################################################
    #
    #    Main panel
    #
    ###################################################################################
    
    MhxLayers = [
        (( 0,    'Root', 'MhxRoot'),
    
         ( 1,    'Spine', 'MhxFKSpine')),
        ((10,    'Head', 'MhxHead'),
    
         ( 8,    'Face', 'MhxFace')),
        (( 9,    'Tweak', 'MhxTweak'),
         (16,    'Clothes', 'MhxClothes')),
    
        #((17,    'IK Spine', 'MhxIKSpine'),
         #((13,    'Inv FK Spine', 'MhxInvFKSpine')),
    
        ('Left', 'Right'),
        (( 2,    'IK Arm', 'MhxIKArm'),
         (18,    'IK Arm', 'MhxIKArm')),
        (( 3,    'FK Arm', 'MhxFKArm'),
         (19,    'FK Arm', 'MhxFKArm')),
        (( 4,    'IK Leg', 'MhxIKLeg'),
         (20,    'IK Leg', 'MhxIKLeg')),
        (( 5,    'FK Leg', 'MhxFKLeg'),
         (21,    'FK Leg', 'MhxFKLeg')),
        ((12,    'Extra', 'MhxExtra'),
         (28,    'Extra', 'MhxExtra')),
        (( 6,    'Fingers', 'MhxFingers'),
         (22,    'Fingers', 'MhxFingers')),
        (( 7,    'Links', 'MhxLinks'),
         (23,    'Links', 'MhxLinks')),
        ((11,    'Palm', 'MhxPalm'),
         (27,    'Palm', 'MhxPalm')),
    ]
    
    
    OtherLayers = [
        (( 1,    'Spine', 'MhxFKSpine'),
         ( 10,    'Head', 'MhxHead')),
        (( 9,    'Tweak', 'MhxTweak'),
         ( 8,    'Face', 'MhxFace')),
        ('Left', 'Right'),
        (( 3,    'Arm', 'MhxFKArm'),
         (19,    'Arm', 'MhxFKArm')),
        (( 5,    'Leg', 'MhxFKLeg'),
         (21,    'Leg', 'MhxFKLeg')),
        (( 7,    'Fingers', 'MhxLinks'),
         (23,    'Fingers', 'MhxLinks')),
        ((11,    'Palm', 'MhxPalm'),
         (27,    'Palm', 'MhxPalm')),
    ]
    
    
    
    #
    #    class MhxMainPanel(bpy.types.Panel):
    #
    
    class MhxMainPanel(bpy.types.Panel):
        bl_label = "MHX Main v %s" % bl_info["version"]
        bl_space_type = "VIEW_3D"
        bl_region_type = "UI"
        #bl_options = {'DEFAULT_CLOSED'}
    
        @classmethod
        def poll(cls, context):
            return (context.object and context.object.MhxRig)
    
        def draw(self, context):
            layout = self.layout
            layout.label("Layers")
            layout.operator("mhx.pose_enable_all_layers")
            layout.operator("mhx.pose_disable_all_layers")
    
    
            rig = context.object
            if rig.MhxRig == 'MHX':
                layers = MhxLayers
            else:
                layers = OtherLayers
    
            for (left,right) in layers:
    
                row = layout.row()
                if type(left) == str:
                    row.label(left)
                    row.label(right)
                else:
                    for (n, name, prop) in [left,right]:
    
                        row.prop(rig.data, "layers", index=n, toggle=True, text=name)
    
    
            layout.separator()
            layout.label("Export/Import MHP")
            layout.operator("mhx.saveas_mhp")
            layout.operator("mhx.load_mhp")
    
    
    class VIEW3D_OT_MhxEnableAllLayersButton(bpy.types.Operator):
        bl_idname = "mhx.pose_enable_all_layers"
        bl_label = "Enable all layers"
        bl_options = {'UNDO'}
    
        def execute(self, context):
            rig,mesh = getMhxRigMesh(context.object)
            for (left,right) in MhxLayers:
                if type(left) != str:
                    for (n, name, prop) in [left,right]:
                        rig.data.layers[n] = True
            return{'FINISHED'}
    
    
    class VIEW3D_OT_MhxDisableAllLayersButton(bpy.types.Operator):
        bl_idname = "mhx.pose_disable_all_layers"
        bl_label = "Disable all layers"
        bl_options = {'UNDO'}
    
        def execute(self, context):
            rig,mesh = getMhxRigMesh(context.object)
            layers = 32*[False]
            pb = context.active_pose_bone
            if pb:
                for n in range(32):
                    if pb.bone.layers[n]:
                        layers[n] = True
                        break
            else:
                layers[0] = True
            if rig:
                rig.data.layers = layers
            return{'FINISHED'}
    
    
    
    def saveMhpFile(rig, scn, filepath):
        roots = []
        for pb in rig.pose.bones:
            if pb.parent is None:
                roots.append(pb)
    
        (pname, ext) = os.path.splitext(filepath)
        mhppath = pname + ".mhp"
    
        fp = open(mhppath, "w", encoding="utf-8", newline="\n")
        for root in roots:
            writeMhpBones(fp, root, None)
        fp.close()
        print("Mhp file %s saved" % mhppath)
    
    
    def writeMhpBones(fp, pb, log):
        if not isMuscleBone(pb):
            b = pb.bone
            if pb.parent:
                mat = b.matrix_local.inverted() * b.parent.matrix_local * pb.parent.matrix.inverted() * pb.matrix
            else:
                mat = pb.matrix.copy()
                maty = mat[1].copy()
                matz = mat[2].copy()
                mat[1] = matz
                mat[2] = -maty
    
    
            diff = mat - Matrix()
            nonzero = False
            for i in range(4):
                if abs(diff[i].length) > 5e-3:
                    nonzero = True
                    break
    
            if nonzero:
                fp.write("%s\tmatrix" % pb.name)
                for i in range(4):
                    row = mat[i]
                    fp.write("\t%.4f\t%.4f\t%.4f\t%.4f" % (row[0], row[1], row[2], row[3]))
                fp.write("\n")
    
    
        for child in pb.children:
            writeMhpBones(fp, child, log)
    
    
    def isMuscleBone(pb):
        layers = pb.bone.layers
        if (layers[14] or layers[15] or layers[30] or layers[31]):
            return True
        for cns in pb.constraints:
            if (cns.type == 'STRETCH_TO' or
                cns.type == 'TRANSFORM' or
                cns.type == 'TRACK_TO' or
                cns.type == 'IK' or
                cns.type[0:5] == 'COPY_'):
                return True
        return False
    
    
    def loadMhpFile(rig, scn, filepath):
    
        unit = Matrix()
        for pb in rig.pose.bones:
            pb.matrix_basis = unit
    
    
        (pname, ext) = os.path.splitext(filepath)
        mhppath = pname + ".mhp"
    
        fp = open(mhppath, "rU")
        for line in fp:
            words = line.split()
            if len(words) < 4:
                continue
    
    
            try:
                pb = rig.pose.bones[words[0]]
            except KeyError:
                print("Warning: Did not find bone %s" % words[0])
                continue
    
            if isMuscleBone(pb):
                pass
    
                q = Quaternion((float(words[2]), float(words[3]), float(words[4]), float(words[5])))
                mat = q.to_matrix().to_4x4()
                pb.matrix_basis = mat
    
            elif words[1] == "gquat":
                q = Quaternion((float(words[2]), float(words[3]), float(words[4]), float(words[5])))
                mat = q.to_matrix().to_4x4()
                maty = mat[1].copy()
                matz = mat[2].copy()
                mat[1] = -matz
                mat[2] = maty
                pb.matrix_basis = pb.bone.matrix_local.inverted() * mat
    
            elif words[1] == "matrix":
                rows = []
                n = 2
                for i in range(4):
                    rows.append((float(words[n]), float(words[n+1]), float(words[n+2]), float(words[n+3])))
                    n += 4
                mat = Matrix(rows)
                if pb.parent:
                    pb.matrix_basis = mat
                else:
                    maty = mat[1].copy()
                    matz = mat[2].copy()
                    mat[1] = -matz
                    mat[2] = maty
                    pb.matrix_basis = pb.bone.matrix_local.inverted() * mat
    
            elif words[1] == "scale":
                pass
            else:
                print("WARNING: Unknown line in mcp file:\n%s" % line)
        fp.close()
        print("Mhp file %s loaded" % mhppath)
    
    
    class VIEW3D_OT_LoadMhpButton(bpy.types.Operator):
        bl_idname = "mhx.load_mhp"
        bl_label = "Load MHP File"
        bl_description = "Load a pose in MHP format"
        bl_options = {'UNDO'}
    
        filename_ext = ".mhp"
        filter_glob = StringProperty(default="*.mhp", options={'HIDDEN'})
        filepath = bpy.props.StringProperty(
            name="File Path",
            description="File path used for mhp file",
            maxlen= 1024, default= "")
    
        def execute(self, context):
            loadMhpFile(context.object, context.scene, self.properties.filepath)
            return {'FINISHED'}
    
        def invoke(self, context, event):
            context.window_manager.fileselect_add(self)
            return {'RUNNING_MODAL'}
    
    
    class VIEW3D_OT_SaveasMhpFileButton(bpy.types.Operator, ExportHelper):
        bl_idname = "mhx.saveas_mhp"
        bl_label = "Save MHP File"
        bl_description = "Save current pose in MHP format"
        bl_options = {'UNDO'}
    
        filename_ext = ".mhp"
        filter_glob = StringProperty(default="*.mhp", options={'HIDDEN'})
        filepath = bpy.props.StringProperty(
            name="File Path",
            description="File path used for mhp file",
            maxlen= 1024, default= "")
    
        def execute(self, context):
            saveMhpFile(context.object, context.scene, self.properties.filepath)
            return {'FINISHED'}
    
        def invoke(self, context, event):
            context.window_manager.fileselect_add(self)
            return {'RUNNING_MODAL'}
    
    
    ###################################################################################
    
    ###################################################################################
    
    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
    
        try:
            ob.data.shape_keys.key_blocks["MouthOpen"]
        except KeyError:
            print("Mesh does not have face shapes")
            return
    
        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({
    
        "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):
    
            return stopStaringVisemes
    
        elif rig.MhxVisemeSet == "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.MhxVisemeSet:
            visemes = getVisemeSet(context, rig)
        else:
    
            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:
    
                frame = int(words[0])+offs
    
                setVisemeAlpha7(context, vis, visemes, True, frame)
    
            else:
                setMhmProps(rig, shapekeys, "Mhsmouth", visemes["Mhv"+vis], factor, auto, 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):
    
                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:
    
                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
    
    def hasProps(ob, prefix):
        if ob is None:
            return False
    
        if ob.type == 'MESH' and ob.parent: