Newer
Older
#
# visemes
#
bodyLanguageVisemes = ({
'Rest' : [
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0.6),
('UpLipsMidHeight', 0),
('LoLipsMidHeight', 0),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0.4),
('UpLipsMidHeight', 0),
('LoLipsMidHeight', 0),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0),
('UpLipsMidHeight', 0),
('LoLipsMidHeight', 0),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 1.0),
('MouthNarrow_R', 1.0),
('LipsPart', 0),
('UpLipsMidHeight', 0),
('LoLipsMidHeight', 0),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0.4),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0.9),
('MouthNarrow_R', 0.9),
('LipsPart', 0),
('UpLipsMidHeight', 0),
('LoLipsMidHeight', 0),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0.8),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0.5),
('MouthNarrow_R', 0.5),
('LipsPart', 0),
('UpLipsMidHeight', 0.2),
('LoLipsMidHeight', -0.2),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0.2),
('MouthWidth_R', 0.2),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 1.0),
('UpLipsMidHeight', 0),
('LoLipsMidHeight', 0.3),
Thomas Larsson
committed
('LoLipsIn', 0.6),
Thomas Larsson
committed
('MouthOpen', 0),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0),
('UpLipsMidHeight', 0.5),
('LoLipsMidHeight', -0.7),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0.8),
('MouthWidth_R', 0.8),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0),
('UpLipsMidHeight', 1.0),
('LoLipsMidHeight', 0),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0.2),
('MouthWidth_R', 0.2),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0),
('UpLipsMidHeight', 0.6),
('LoLipsMidHeight', -0.6),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0.5),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0),
('UpLipsMidHeight', 0.4),
('LoLipsMidHeight', 0),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0.7),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0),
('UpLipsMidHeight', 0.5),
('LoLipsMidHeight', -0.6),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0.25),
Thomas Larsson
committed
('TongueBackHeight', 0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0),
('UpLipsMidHeight', 0),
('LoLipsMidHeight', 0),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', 0.2),
Thomas Larsson
committed
('TongueBackHeight', 1.0),
('TongueHeight', 1.0)
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0),
('UpLipsMidHeight', 0.5),
('LoLipsMidHeight', -0.5),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', -0.2),
Thomas Larsson
committed
('TongueBackHeight', 1.0),
('TongueHeight', 1.0),
Thomas Larsson
committed
],
Thomas Larsson
committed
('MouthWidth_L', 0),
('MouthWidth_R', 0),
('MouthNarrow_L', 0),
('MouthNarrow_R', 0),
('LipsPart', 0),
('UpLipsMidHeight', 0.5),
('LoLipsMidHeight', -0.5),
Thomas Larsson
committed
('LoLipsIn', 0),
Thomas Larsson
committed
('MouthOpen', -0.2),
Thomas Larsson
committed
('TongueBackHeight', 1.0),
('TongueHeight', 0),
Thomas Larsson
committed
],
Thomas Larsson
committed
'Blink' : [
Thomas Larsson
committed
('UpLidUp_L', 1),
('UpLidUp_R', 1),
Thomas Larsson
committed
('LoLidDown_L', 1),
('LoLidDown_R', 1)
Thomas Larsson
committed
],
Thomas Larsson
committed
'Unblink' : [
Thomas Larsson
committed
('UpLidUp_L', 0),
('UpLidUp_R', 0),
Thomas Larsson
committed
('LoLidDown_L', 0),
('LoLidDown_R', 0)
Thomas Larsson
committed
],
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)),
Thomas Larsson
committed
'LipsPart' : ('PMouthMid', (0, -0.25)),
Thomas Larsson
committed
'TongueBackHeight': ('PTongue', (-0.25, 0)),
'TongueHeight' : ('PTongue', (0, -0.25)),
Thomas Larsson
committed
Thomas Larsson
committed
'UpLidUp_L' : ('PUpLid_L', (0,1.0)),
'UpLidUp_R' : ('PUpLid_R', (0,1.0)),
Thomas Larsson
committed
'LoLidDown_L' : ('PLoLid_L', (0,-1.0)),
'LoLidDown_R' : ('PLoLid_R', (0,-1.0)),
}
Thomas Larsson
committed
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):
Thomas Larsson
committed
rig = ob.parent
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
Thomas Larsson
committed
except KeyError:
Thomas Larsson
committed
pass
Thomas Larsson
committed
try:
ob.data.shape_keys.key_blocks["MouthOpen"]
except KeyError:
print("Mesh does not have face shapes")
return
Thomas Larsson
committed
verts = ob.data.vertices
for (vis,shapes) in bodyLanguageVisemes.items():
if vis in ['Blink', 'Unblink']:
continue
Thomas Larsson
committed
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)
Thomas Larsson
committed
print("Visemes made")
return
Thomas Larsson
committed
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)
Thomas Larsson
committed
return{'FINISHED'}
Thomas Larsson
committed
#
# mohoVisemes
# magpieVisemes
#
Thomas Larsson
committed
"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",
Thomas Larsson
committed
"AI" : "AH",
Thomas Larsson
committed
"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):
#
Thomas Larsson
committed
def getVisemeSet(context, rig):
Thomas Larsson
committed
if rig.MhxVisemeSet == "StopStaring":
return stopStaringVisemes
Thomas Larsson
committed
elif rig.MhxVisemeSet == "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]
Thomas Larsson
committed
loc = mathutils.Vector((float(x*value),0,float(z*value)))
Thomas Larsson
committed
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:
Thomas Larsson
committed
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:
Thomas Larsson
committed
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)
Thomas Larsson
committed
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
Thomas Larsson
committed
shapekeys = getMhmShapekeys(rig, mesh)
context.scene.objects.active = rig
Thomas Larsson
committed
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:
Thomas Larsson
committed
vis = struct[words[1]]
Thomas Larsson
committed
if rig.MhxVisemeSet:
setVisemeAlpha7(context, vis, visemes, True, frame)
Thomas Larsson
committed
else:
setMhmProps(rig, shapekeys, "Mhsmouth", visemes["Mhv"+vis], factor, auto, frame)
Thomas Larsson
committed
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'})
Thomas Larsson
committed
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)
Thomas Larsson
committed
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")
Thomas Larsson
committed
layout = self.layout
Thomas Larsson
committed
if not rig.MhxVisemeSet:
Thomas Larsson
committed
visemes = getProps(rig, "Mhv")
Thomas Larsson
committed
if not visemes:
layout.label("No visemes found")
return
Thomas Larsson
committed
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
Thomas Larsson
committed
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()
Thomas Larsson
committed
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:
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")
Thomas Larsson
committed
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):
Thomas Larsson
committed
return{'FINISHED'}
Thomas Larsson
committed
###################################################################################
Thomas Larsson
committed
# Expression panels
Thomas Larsson
committed
###################################################################################
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)
Thomas Larsson
committed
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]
Thomas Larsson
committed
Thomas Larsson
committed
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
else:
Thomas Larsson
committed
for prop in props:
Thomas Larsson
committed
if prop == expression:
rig[prop] = 1.0
else:
rig[prop] = 0.0
Thomas Larsson
committed
return{'FINISHED'}
Thomas Larsson
committed
def getMhmShapekeys(rig, mesh):
if rig.MhxShapekeyDrivers:
return None
else:
return mesh.data.shape_keys.key_blocks
Thomas Larsson
committed
Thomas Larsson
committed
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:
Thomas Larsson
committed
shapekeys[skey].keyframe_insert("value", frame=frame)
Thomas Larsson
committed
else:
rig[prop] = factor*value
if auto:
Thomas Larsson
committed
rig.keyframe_insert('["%s"]'%prop, frame=frame)
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:
Thomas Larsson
committed
shapekeys[skey].keyframe_insert("value", frame=frame)
Thomas Larsson
committed
else:
rig[prop] = 0.0
if auto:
Thomas Larsson
committed
rig.keyframe_insert('["%s"]'%prop, frame=frame)
Thomas Larsson
committed
def getUnitsFromString(string):
Thomas Larsson
committed
words = string.split(";")
Thomas Larsson
committed
units = []
Thomas Larsson
committed
if word == "":
continue
Thomas Larsson
committed
unit = word.split(":")
Thomas Larsson
committed
prop = "Mhs" + unit[0]
value = float(unit[1])
Thomas Larsson
committed
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()
Thomas Larsson
committed
def execute(self, context):
Thomas Larsson
committed
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)
Thomas Larsson
committed
prefix,units = getUnitsFromString(self.data)
Thomas Larsson
committed
setMhmProps(rig, shapekeys, prefix, units, rig.MhxStrength, auto, frame)
Thomas Larsson
committed
updatePose(context)
Thomas Larsson
committed
return{'FINISHED'}
Thomas Larsson
committed
def getProps(rig, prefix):
props = []
for prop in rig.keys():
if prop.startswith(prefix):
Thomas Larsson
committed
props.append(prop)
Thomas Larsson
committed
props.sort()
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
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
Thomas Larsson
committed
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
Thomas Larsson
committed
Thomas Larsson
committed
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'}
Thomas Larsson
committed
@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'}
Thomas Larsson
committed
Thomas Larsson
committed
@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
# FK-IK snapping.
Thomas Larsson
committed
#
#########################################
def getPoseMatrix(gmat, pb):
restInv = pb.bone.matrix_local.inverted()
parInv = pb.parent.matrix.inverted()
parRest = pb.parent.bone.matrix_local
return restInv * (parRest * (parInv * gmat))
Thomas Larsson
committed
else:
return restInv * gmat
Thomas Larsson
committed
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, src, auto):
pmat = getPoseMatrix(src.matrix, pb)
insertLocation(pb, pmat, auto)
Thomas Larsson
committed
Thomas Larsson
committed
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, 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]))
Thomas Larsson
committed
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')
Thomas Larsson
committed
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
try:
zBall = mBall.matrix.col[3][2]
except AttributeError:
return
Thomas Larsson
committed
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
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)
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
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)
insertLocation(pb, pmat, auto)
def matchPoseReverse(pb, src, auto):
gmat = src.matrix
tail = gmat.col[3] + src.length * gmat.col[1]
rmat = Matrix((gmat.col[0], -gmat.col[1], -gmat.col[2], tail))
rmat.transpose()
pmat = getPoseMatrix(rmat, pb)
pb.matrix_basis = pmat
insertRotation(pb, pmat, auto)
def matchPoseScale(pb, src, auto):
pmat = getPoseMatrix(src.matrix, pb)
pb.scale = pmat.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 snapFkArm(context, data):
Thomas Larsson
committed
rig = context.object
prop,old,suffix = setSnapProp(rig, data, 1.0, context, False)
auto = context.scene.tool_settings.use_keyframe_insert_auto
print("Snap FK Arm%s" % suffix)
snapFk,cnsFk = getSnapBones(rig, "ArmFK", suffix)
Thomas Larsson
committed
(uparmFk, loarmFk, handFk) = snapFk
snapIk,cnsIk = getSnapBones(rig, "ArmIK", suffix)
(uparmIk, loarmIk, elbow, elbowPt, handIk) = snapIk
Thomas Larsson
committed
matchPoseRotation(uparmFk, uparmIk, auto)
matchPoseScale(uparmFk, uparmIk, auto)
Thomas Larsson
committed
matchPoseRotation(loarmFk, loarmIk, auto)
matchPoseScale(loarmFk, loarmIk, auto)
restoreSnapProp(rig, prop, old, context)
Thomas Larsson
committed
Thomas Larsson
committed
try:
matchHand = rig["MhaHandFollowsWrist" + suffix]
except KeyError:
matchHand = True
if matchHand:
matchPoseRotation(handFk, handIk, auto)
matchPoseScale(handFk, handIk, auto)
#muteConstraints(cnsFk, False)
Thomas Larsson
committed
return
def snapIkArm(context, data):
Thomas Larsson
committed
rig = context.object
prop,old,suffix = setSnapProp(rig, data, 0.0, context, True)
auto = context.scene.tool_settings.use_keyframe_insert_auto
print("Snap IK Arm%s" % suffix)
snapIk,cnsIk = getSnapBones(rig, "ArmIK", suffix)
Thomas Larsson
committed
(uparmIk, loarmIk, elbow, elbowPt, handIk) = snapIk
snapFk,cnsFk = getSnapBones(rig, "ArmFK", suffix)
Thomas Larsson
committed
(uparmFk, loarmFk, handFk) = snapFk
Thomas Larsson
committed
Thomas Larsson
committed
matchPoseTranslation(handIk, handFk, auto)
matchPoseRotation(handIk, handFk, auto)
matchPoleTarget(elbowPt, uparmFk, loarmFk, auto)
Thomas Larsson
committed
#matchPoseRotation(uparmIk, uparmFk, auto)
#matchPoseRotation(loarmIk, loarmFk, auto)
restoreSnapProp(rig, prop, old, context)
#muteConstraints(cnsIk, False)
Thomas Larsson
committed
return
def snapFkLeg(context, data):
Thomas Larsson
committed
rig = context.object
prop,old,suffix = setSnapProp(rig, data, 1.0, context, False)
auto = context.scene.tool_settings.use_keyframe_insert_auto
print("Snap FK Leg%s" % suffix)
Thomas Larsson
committed
snap,_ = getSnapBones(rig, "Leg", suffix)
(upleg, loleg, foot, toe) = snap
snapIk,cnsIk = getSnapBones(rig, "LegIK", suffix)
Thomas Larsson
committed
(uplegIk, lolegIk, kneePt, ankleIk, legIk, footRev, toeRev, mBall, mToe, mHeel) = snapIk
snapFk,cnsFk = getSnapBones(rig, "LegFK", suffix)
Thomas Larsson
committed
(uplegFk, lolegFk, footFk, toeFk) = snapFk
Thomas Larsson
committed
matchPoseRotation(uplegFk, uplegIk, auto)
matchPoseScale(uplegFk, uplegIk, auto)
matchPoseRotation(lolegFk, lolegIk, auto)
matchPoseScale(lolegFk, lolegIk, auto)
Thomas Larsson
committed
restoreSnapProp(rig, prop, old, context)
Thomas Larsson
committed
matchPoseReverse(footFk, footRev, auto)
matchPoseReverse(toeFk, toeRev, auto)
Thomas Larsson
committed
#muteConstraints(cnsFk, False)
Thomas Larsson
committed
return
def snapIkLeg(context, data):
Thomas Larsson
committed
rig = context.object
prop,old,suffix = setSnapProp(rig, data, 0.0, context, True)
auto = scn.tool_settings.use_keyframe_insert_auto