Newer
Older
#filepathname = self.filepath.encode('utf-8', 'strict')
Thomas Larsson
committed
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")
#bpy.ops.mhx.success('INVOKE_DEFAULT', message = self.filepath)
except MhxError:
print("Error when loading MHX file %s:\n" % self.filepath + theMessage)
if self.advanced:
writeDefaults()
self.advanced = False
global toggle, theScale, MhxBoolProps
readDefaults()
for (prop, name, desc, flag) in MhxBoolProps:
expr = 'self.%s = (toggle&%s != 0)' % (prop, flag)
exec(expr)
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}
Thomas Larsson
committed
###################################################################################
#
# Lipsync panel
#
Thomas Larsson
committed
###################################################################################
#
# visemes
#
Thomas Larsson
committed
"""
stopStaringVisemes = ({
'Rest' : [
Thomas Larsson
committed
('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)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'MBP' : [('PMouth', (-0.3,0)),
('PUpLip', (0,1)),
('PLoLip', (0,0)),
('PJaw', (0,0.1)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'OO' : [('PMouth', (-1.5,0)),
('PUpLip', (0,0)),
('PLoLip', (0,0)),
('PJaw', (0,0.2)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'O' : [('PMouth', (-1.1,0)),
('PUpLip', (0,0)),
('PLoLip', (0,0)),
('PJaw', (0,0.5)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'R' : [('PMouth', (-0.9,0)),
('PUpLip', (0,-0.2)),
('PLoLip', (0,0.2)),
('PJaw', (0,0.2)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'FV' : [('PMouth', (0,0)),
('PUpLip', (0,0)),
('PLoLip', (0,-0.8)),
('PJaw', (0,0.1)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'S' : [('PMouth', (0,0)),
('PUpLip', (0,-0.2)),
('PLoLip', (0,0.2)),
('PJaw', (0,0.05)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'SH' : [('PMouth', (-0.6,0)),
('PUpLip', (0,-0.5)),
('PLoLip', (0,0.5)),
('PJaw', (0,0)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'EE' : [('PMouth', (0.3,0)),
('PUpLip', (0,-0.3)),
('PLoLip', (0,0.3)),
('PJaw', (0,0.025)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'AH' : [('PMouth', (-0.1,0)),
('PUpLip', (0,-0.4)),
('PLoLip', (0,0)),
('PJaw', (0,0.35)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'EH' : [('PMouth', (0.1,0)),
('PUpLip', (0,-0.2)),
('PLoLip', (0,0.2)),
('PJaw', (0,0.2)),
Thomas Larsson
committed
('PTongue', (0,0.0))],
'TH' : [('PMouth', (0,0)),
('PUpLip', (0,-0.5)),
('PLoLip', (0,0.5)),
('PJaw', (-0.2,0.1)),
Thomas Larsson
committed
('PTongue', (0,-0.6))],
'L' : [('PMouth', (0,0)),
('PUpLip', (0,-0.2)),
('PLoLip', (0,0.2)),
('PJaw', (0.2,0.2)),
Thomas Larsson
committed
('PTongue', (0,-0.8))],
'G' : [('PMouth', (0,0)),
('PUpLip', (0,-0.1)),
('PLoLip', (0,0.1)),
('PJaw', (-0.3,0.1)),
Thomas Larsson
committed
('PTongue', (0,-0.6))],
Thomas Larsson
committed
'Blink' : [('PUpLid', (0,1.0)), ('PLoLid', (0,-1.0))],
'Unblink' : [('PUpLid', (0,0)), ('PLoLid', (0,0))],
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):
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:
Thomas Larsson
committed
pass
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'}
"""
#
# 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",
"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]
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)
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)
Thomas Larsson
committed
visemes = getVisemeSet(context, rig)
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:
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
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
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:
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")
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
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
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)