Newer
Older
Thomas Larsson
committed
"""
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
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),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('LipsPart', 1.0),
('UpLipsMidHeight', 0),
('LoLipsMidHeight', 0.3),
('LoLipsIn', 0.6),
('MouthOpen', 0),
('TongueBackHeight', 0),
('TongueHeight', 0),
],
('MouthWidth_L', 0),
('MouthWidth_R', 0),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('LipsPart', 0),
('UpLipsMidHeight', 1.0),
('LoLipsMidHeight', 0),
Thomas Larsson
committed
('LoLipsIn', 0),
('MouthOpen', 0),
('TongueBackHeight', 0),
('TongueHeight', 0),
],
('MouthWidth_L', 0.2),
('MouthWidth_R', 0.2),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
Thomas Larsson
committed
('LipsPart', 0),
('UpLipsMidHeight', 0.6),
('LoLipsMidHeight', -0.6),
('LoLipsIn', 0),
('MouthOpen', 0.5),
('TongueBackHeight', 0),
('TongueHeight', 0),
],
('MouthWidth_L', 0),
('MouthWidth_R', 0),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
('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),
Thomas Larsson
committed
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
('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)
],
Thomas Larsson
committed
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)),
Thomas Larsson
committed
'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)
print("Visemes made")
return
class VIEW3D_OT_MhxMakeVisemesButton(bpy.types.Operator):
bl_idname = "mhx.make_visemes"
bl_label = "Generate viseme shapekeys"
def execute(self, context):
makeVisemes(context.object, context.scene)
return{'FINISHED'}
#
# mohoVisemes
# magpieVisemes
#
'rest' : 'Rest',
'etc' : 'Etc',
'AI' : 'AH',
'O' : 'O',
'U' : 'OO',
'WQ' : 'AH',
'L' : 'L',
'E' : 'EH',
'MBP' : 'MBP',
'FV' : 'FV',
})
Thomas Larsson
committed
"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)
Thomas Larsson
committed
def setVisemeAlpha7(context, vis, visemes, setKey, frame):
Thomas Larsson
committed
(rig, mesh) = getMhxRigMesh(context.object)
isPanel = False
isProp = False
shapekeys = None
scale = 0.75
Thomas Larsson
committed
scale *= rig.pose.bones['PFace'].bone.length
isPanel = True
Thomas Larsson
committed
isProp = True
elif mesh:
shapekeys = mesh.data.shape_keys.key_blocks
Thomas Larsson
committed
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:
Thomas Larsson
committed
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")
Thomas Larsson
committed
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)
class VIEW3D_OT_MhxVisemeButton(bpy.types.Operator):
bl_idname = 'mhx.pose_viseme'
bl_label = 'Viseme'
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)
return{'FINISHED'}
def readLipsync(context, filepath, offs, struct):
Thomas Larsson
committed
(rig, mesh) = getMhxRigMesh(context.object)
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
Thomas Larsson
committed
shapekeys = getMhmShapekeys(rig, mesh)
else:
visemes = getVisemeSet(context, rig)
context.scene.objects.active = rig
bpy.ops.object.mode_set(mode='POSE')
Thomas Larsson
committed
fp = open(filepath, "rU")
for line in fp:
words= line.split()
if len(words) < 2:
vis = "Mhv" + struct[words[1]]
frame = int(words[0])+offs
if rig.MhAlpha8:
Thomas Larsson
committed
setMhmProps(rig, shapekeys, "Mhsmouth", visemes[vis], factor, auto, frame)
else:
setVisemeAlpha7(context, vis, visemes, True, frame)
Thomas Larsson
committed
#setInterpolation(rig)
print("Lipsync file %s loaded" % filepath)
Thomas Larsson
committed
class VIEW3D_OT_MhxMohoButton(bpy.types.Operator, ImportHelper):
bl_idname = "mhx.pose_load_moho"
bl_label = "Load Moho (.dat)"
Thomas Larsson
committed
filename_ext = ".dat"
filter_glob = StringProperty(default="*.dat", options={'HIDDEN'})
filepath = StringProperty(subtype='FILE_PATH')
Thomas Larsson
committed
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):
def draw(self, context):
Thomas Larsson
committed
rig,mesh = getMhxRigMesh(context.object)
Thomas Larsson
committed
layout.label("No MHX rig found")
return
layout = self.layout
Thomas Larsson
committed
visemes = getProps(rig, "Mhv")
Thomas Larsson
committed
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"
Thomas Larsson
committed
layout.prop(rig, "MhxStrength")
layout.separator()
Thomas Larsson
committed
for prop in visemes:
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
Thomas Larsson
committed
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()
Thomas Larsson
committed
row.operator("mhx.pose_load_moho")
Thomas Larsson
committed
# class VIEW3D_OT_MhxUpdateButton(bpy.types.Operator):
#
def updatePose(context):
scn = context.scene
Thomas Larsson
committed
scn.frame_current = scn.frame_current
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):
return{'FINISHED'}
###################################################################################
#
Thomas Larsson
committed
# Expression panels
#
###################################################################################
class VIEW3D_OT_MhxResetExpressionsButton(bpy.types.Operator):
bl_idname = "mhx.pose_reset_expressions"
bl_label = "Reset expressions"
Thomas Larsson
committed
prefix = StringProperty()
def execute(self, context):
Thomas Larsson
committed
rig,mesh = getMhxRigMesh(context.object)
Thomas Larsson
committed
shapekeys = getMhmShapekeys(rig, mesh)
clearMhmProps(rig, shapekeys, self.prefix, context.tool_settings.use_keyframe_insert_auto, context.scene.frame_current)
return{'FINISHED'}
class VIEW3D_OT_MhxKeyExpressionsButton(bpy.types.Operator):
bl_idname = "mhx.pose_key_expressions"
bl_label = "Key expressions"
Thomas Larsson
committed
prefix = StringProperty()
def execute(self, context):
Thomas Larsson
committed
rig,mesh = getMhxRigMesh(context.object)
frame = context.scene.frame_current
Thomas Larsson
committed
for prop in props:
Thomas Larsson
committed
return{'FINISHED'}
class VIEW3D_OT_MhxPinExpressionButton(bpy.types.Operator):
bl_idname = "mhx.pose_pin_expression"
bl_label = "Pin"
Thomas Larsson
committed
data = StringProperty()
def execute(self, context):
Thomas Larsson
committed
rig,mesh = getMhxRigMesh(context.object)
Thomas Larsson
committed
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
Thomas Larsson
committed
for prop in props:
Thomas Larsson
committed
if prop == expression:
rig[prop] = 1.0
else:
rig[prop] = 0.0
if abs(rig[prop] - old) > 1e-3:
Thomas Larsson
committed
for prop in props:
Thomas Larsson
committed
if prop == expression:
rig[prop] = 1.0
else:
rig[prop] = 0.0
return{'FINISHED'}
Thomas Larsson
committed
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)
Thomas Larsson
committed
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
committed
def clearMhmProps(rig, shapekeys, prefix, auto, frame):
props = getProps(rig, prefix)
for prop in props:
Thomas Larsson
committed
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:
def getUnitsFromString(string):
Thomas Larsson
committed
words = string.split(";")
Thomas Larsson
committed
units = []
Thomas Larsson
committed
if word == "":
continue
unit = word.split(":")
prop = "Mhs" + unit[0]
value = float(unit[1])
units.append((prop, value))
return prefix,units
Thomas Larsson
committed
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
Thomas Larsson
committed
shapekeys = getMhmShapekeys(rig, mesh)
prefix,units = getUnitsFromString(self.data)
Thomas Larsson
committed
setMhmProps(rig, shapekeys, prefix, units, rig.MhxStrength, auto, frame)
Thomas Larsson
committed
updatePose(context)
return{'FINISHED'}
Thomas Larsson
committed
Thomas Larsson
committed
def getProps(rig, prefix):
props = []
for prop in rig.keys():
if prop.startswith(prefix):
Thomas Larsson
committed
props.append(prop)
class MhxExpressionsPanel(bpy.types.Panel):
bl_label = "MHX Expressions"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_options = {'DEFAULT_CLOSED'}
Thomas Larsson
committed
@classmethod
def poll(cls, context):
return pollMhx(context.object)
def draw(self, context):
layout = self.layout
rig,mesh = getMhxRigMesh(context.object)
if not rig:
Thomas Larsson
committed
layout.label("No MHX rig found")
Thomas Larsson
committed
return
exprs = getProps(rig, "Mhe")
if not exprs:
Thomas Larsson
committed
layout.label("No expressions found")
Thomas Larsson
committed
return
layout.operator("mhx.pose_reset_expressions").prefix="Mhs"
layout.operator("mhx.pose_key_expressions").prefix="Mhs"
Thomas Larsson
committed
layout.prop(rig, "MhxStrength")
layout.separator()
for prop in exprs:
layout.operator("mhx.pose_mhm", text=prop[3:]).data="Mhs;"+rig[prop]
Thomas Larsson
committed
Thomas Larsson
committed
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
layout.operator("mhx.pose_key_expressions", text="Key %ss" % name).prefix=prefix
Thomas Larsson
committed
#layout.operator("mhx.update")
layout.separator()
for prop in props:
row = layout.split(0.85)
Thomas Larsson
committed
row.prop(rig, '["%s"]' % prop, text=prop[3:])
Thomas Larsson
committed
row.operator("mhx.pose_pin_expression", text="", icon='UNPINNED').data = (prefix + ";" + prop)
return
Thomas Larsson
committed
class MhxExpressionUnitsPanel(bpy.types.Panel):
Thomas Larsson
committed
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
def draw(self, context):
Thomas Larsson
committed
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")
Thomas Larsson
committed
Thomas Larsson
committed
#########################################
#
Thomas Larsson
committed
#
#########################################
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))
Thomas Larsson
committed
else:
Thomas Larsson
committed
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
Thomas Larsson
committed
def matchPoseTranslation(pb, fkPb, auto):
mat = getPoseMatrix(fkPb.matrix, pb)
insertLocation(pb, mat, auto)
Thomas Larsson
committed
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')
Thomas Larsson
committed
def matchPoseRotation(pb, fkPb, auto):
mat = getPoseMatrix(fkPb.matrix, pb)
insertRotation(pb, mat, auto)
Thomas Larsson
committed
def insertRotation(pb, mat, auto):
Thomas Larsson
committed
q = mat.to_quaternion()
if pb.rotation_mode == 'QUATERNION':
pb.rotation_quaternion = q
if auto:
pb.keyframe_insert("rotation_quaternion", group=pb.name)
Thomas Larsson
committed
else:
pb.rotation_euler = q.to_euler(pb.rotation_mode)
if auto:
pb.keyframe_insert("rotation_euler", group=pb.name)
Thomas Larsson
committed
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.mode_set(mode='POSE')
def matchPoseReverse(pb, fkPb, auto):
Thomas Larsson
committed
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)
Thomas Larsson
committed
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')
Thomas Larsson
committed
def fk2ikArm(context, suffix):
rig = context.object
auto = context.scene.tool_settings.use_keyframe_insert_auto
print("Snap FK Arm%s" % suffix)
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)
Thomas Larsson
committed
matchPoseRotation(uparmFk, uparmFk, auto)
matchPoseScale(uparmFk, uparmFk, auto)
Thomas Larsson
committed
matchPoseRotation(loarmFk, loarmFk, auto)
matchPoseScale(loarmFk, loarmFk, auto)
Thomas Larsson
committed
Thomas Larsson
committed
if rig["MhaHandFollowsWrist" + suffix]:
matchPoseRotation(handFk, wrist, auto)
matchPoseScale(handFk, wrist, auto)
Thomas Larsson
committed
return
def ik2fkArm(context, suffix):
rig = context.object
scn = context.scene
auto = scn.tool_settings.use_keyframe_insert_auto
print("Snap IK Arm%s" % suffix)
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)
Thomas Larsson
committed
#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
committed
return
def fk2ikLeg(context, suffix):
rig = context.object
auto = context.scene.tool_settings.use_keyframe_insert_auto
print("Snap FK Leg%s" % suffix)
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)
Thomas Larsson
committed
matchPoseRotation(lolegFk, lolegFk, auto)
matchPoseScale(lolegFk, lolegFk, auto)
Thomas Larsson
committed
return
Thomas Larsson
committed
def ik2fkLeg(context, suffix):
rig = context.object