Update
This commit is contained in:
parent
5c8bc871af
commit
de7ea0e64f
1617
Scripts/Animation/IK_FK_Switcher.py
Normal file
1617
Scripts/Animation/IK_FK_Switcher.py
Normal file
File diff suppressed because it is too large
Load Diff
2
Scripts/Animation/MotionCapHelper/.gitattributes
vendored
Normal file
2
Scripts/Animation/MotionCapHelper/.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
21
Scripts/Animation/MotionCapHelper/bin/LICENSE
Normal file
21
Scripts/Animation/MotionCapHelper/bin/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 yxnhyxnh
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
0
Scripts/Animation/MotionCapHelper/bin/__inti__.py
Normal file
0
Scripts/Animation/MotionCapHelper/bin/__inti__.py
Normal file
236
Scripts/Animation/MotionCapHelper/bin/mocaphelper.py
Normal file
236
Scripts/Animation/MotionCapHelper/bin/mocaphelper.py
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
this plugin is created for use with autodesk maya 2018+.
|
||||||
|
(because it import pyside2 module,and i don't know in which version maya would update this.)
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import maya.api.OpenMaya as om
|
||||||
|
import mocaphelperui
|
||||||
|
import mocaphelpersaccore
|
||||||
|
import mocaphelperfacore
|
||||||
|
import mocaphelperutility
|
||||||
|
|
||||||
|
import PySide2.QtWidgets
|
||||||
|
|
||||||
|
from PySide2 import QtCore
|
||||||
|
|
||||||
|
|
||||||
|
version = 1.44
|
||||||
|
ui = None
|
||||||
|
|
||||||
|
translator = QtCore.QTranslator()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def maya_useNewAPI():
|
||||||
|
"""
|
||||||
|
The presence of this function tells Maya that the plugin produces, and
|
||||||
|
expects to be passed, objects created using the Maya Python API 2.0.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Initialize the plug-in
|
||||||
|
def initializePlugin(plugin):
|
||||||
|
pluginFn = om.MFnPlugin(plugin)
|
||||||
|
try:
|
||||||
|
pluginFn.registerCommand(
|
||||||
|
mocaphelpersaccore.SmoothAnimCurve.kPluginCmdName, mocaphelpersaccore.SmoothAnimCurve.cmdCreator,mocaphelpersaccore.syntaxCreator
|
||||||
|
)
|
||||||
|
|
||||||
|
except:
|
||||||
|
sys.stderr.write(
|
||||||
|
"Failed to register command: %s\n" % mocaphelpersaccore.SmoothAnimCurve.kPluginCmdName
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
pluginFn.registerCommand(
|
||||||
|
openui.kPluginCmdName, openui.cmdCreator,openuiSyntaxCreator
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
sys.stderr.write(
|
||||||
|
"Failed to register command: %s\n" % openui.kPluginCmdName
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
pluginFn.registerCommand(
|
||||||
|
mocaphelperfacore.FrameAlign.kPluginCmdName, mocaphelperfacore.FrameAlign.cmdCreator,mocaphelperfacore.syntaxCreator
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
sys.stderr.write(
|
||||||
|
"Failed to register command: %s\n" % mocaphelperfacore.FrameAlign.kPluginCmdName
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
pluginFn.registerCommand(
|
||||||
|
Eval.kPluginCmdName, Eval.cmdCreator,evalSyntaxCreator
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
sys.stderr.write(
|
||||||
|
"Failed to register command: %s\n" % Eval.kPluginCmdName
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Uninitialize the plug-in
|
||||||
|
def uninitializePlugin(plugin):
|
||||||
|
pluginFn = om.MFnPlugin(plugin)
|
||||||
|
try:
|
||||||
|
pluginFn.deregisterCommand(mocaphelpersaccore.SmoothAnimCurve.kPluginCmdName)
|
||||||
|
except:
|
||||||
|
sys.stderr.write(
|
||||||
|
"Failed to unregister command: %s\n" % mocaphelpersaccore.SmoothAnimCurve.kPluginCmdName
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
try:
|
||||||
|
pluginFn.deregisterCommand(openui.kPluginCmdName)
|
||||||
|
except:
|
||||||
|
sys.stderr.write(
|
||||||
|
"Failed to unregister command: %s\n" % openui.kPluginCmdName
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
pluginFn.deregisterCommand(mocaphelperfacore.FrameAlign.kPluginCmdName)
|
||||||
|
except:
|
||||||
|
sys.stderr.write(
|
||||||
|
"Failed to unregister command: %s\n" % mocaphelperfacore.FrameAlign.kPluginCmdName
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
pluginFn.deregisterCommand(Eval.kPluginCmdName)
|
||||||
|
except:
|
||||||
|
sys.stderr.write(
|
||||||
|
"Failed to unregister command: %s\n" % Eval.kPluginCmdName
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
# command
|
||||||
|
|
||||||
|
|
||||||
|
class openui(om.MPxCommand):
|
||||||
|
|
||||||
|
kPluginCmdName = "moCapHelper_showUi"
|
||||||
|
|
||||||
|
uiLanguageFlagShortName = "lan"
|
||||||
|
uiLanguageFlagLongName = "language"
|
||||||
|
lang = None
|
||||||
|
def __init__(self):
|
||||||
|
om.MPxCommand.__init__(self)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cmdCreator():
|
||||||
|
return openui()
|
||||||
|
|
||||||
|
def parseArguments(self,args):
|
||||||
|
argdata = om.MArgParser(self.syntax(),args)
|
||||||
|
|
||||||
|
if argdata.isFlagSet( self.uiLanguageFlagShortName ):
|
||||||
|
self.lang = argdata.flagArgumentString(self.uiLanguageFlagShortName,0)
|
||||||
|
else:
|
||||||
|
self.lang = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def doIt(self, args):
|
||||||
|
self.parseArguments(args)
|
||||||
|
global ui
|
||||||
|
if ui != None:
|
||||||
|
print("saved ui ref:",ui)
|
||||||
|
print("closing ui:--------",ui.destroy(True,True))
|
||||||
|
|
||||||
|
|
||||||
|
app = PySide2.QtWidgets.QApplication.instance()
|
||||||
|
|
||||||
|
app.installTranslator(translator)
|
||||||
|
dir = mocaphelperutility.getDir()
|
||||||
|
# translate:
|
||||||
|
if self.lang == "CN":
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
translator.load("ui_CN",dir)
|
||||||
|
ui = mocaphelperui.MoCapHelperUI()
|
||||||
|
ui.setWindowTitle('动补助手 v'+str(version))
|
||||||
|
# print(translator.filePath())
|
||||||
|
# print(translator.translate())
|
||||||
|
|
||||||
|
# mocaphelperui.translateUi(ui.ui,ui.ui)
|
||||||
|
else:
|
||||||
|
translator.load("")
|
||||||
|
ui = mocaphelperui.MoCapHelperUI()
|
||||||
|
|
||||||
|
ui.show()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def openuiSyntaxCreator():
|
||||||
|
|
||||||
|
syntax = om.MSyntax()
|
||||||
|
|
||||||
|
syntax.addFlag( openui.uiLanguageFlagShortName, openui.uiLanguageFlagLongName, om.MSyntax.kString )
|
||||||
|
|
||||||
|
|
||||||
|
return syntax
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Eval(om.MPxCommand):
|
||||||
|
|
||||||
|
kPluginCmdName = "moCapHelper_eval"
|
||||||
|
|
||||||
|
strFlagShortName = "s"
|
||||||
|
strFlagLongName = "string"
|
||||||
|
cmd = ""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
om.MPxCommand.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parseArguments(self,args):
|
||||||
|
argdata = om.MArgParser(self.syntax(),args)
|
||||||
|
|
||||||
|
if argdata.isFlagSet( self.strFlagShortName ):
|
||||||
|
self.cmd = argdata.flagArgumentString(self.strFlagShortName,0)
|
||||||
|
else:
|
||||||
|
raise Exception("no str input")
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cmdCreator():
|
||||||
|
|
||||||
|
return Eval()
|
||||||
|
|
||||||
|
|
||||||
|
def doIt(self, args):
|
||||||
|
self.parseArguments(args)
|
||||||
|
print(self.cmd)
|
||||||
|
global ui
|
||||||
|
if ui != None:
|
||||||
|
exec(self.cmd)
|
||||||
|
else:
|
||||||
|
raise Exception("please create ui first.")
|
||||||
|
|
||||||
|
|
||||||
|
def evalSyntaxCreator():
|
||||||
|
|
||||||
|
syntax = om.MSyntax()
|
||||||
|
|
||||||
|
syntax.addFlag( Eval.strFlagShortName, Eval.strFlagLongName, om.MSyntax.kString )
|
||||||
|
|
||||||
|
|
||||||
|
return syntax
|
||||||
|
|
217
Scripts/Animation/MotionCapHelper/bin/mocaphelperarbcore.py
Normal file
217
Scripts/Animation/MotionCapHelper/bin/mocaphelperarbcore.py
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import maya.cmds as cmds
|
||||||
|
import maya.mel as mel
|
||||||
|
|
||||||
|
import mocaphelperutility
|
||||||
|
import math
|
||||||
|
|
||||||
|
def createLoc(strname,cd = (0,0,0),rot = (0,0,0),roo = "xyz"):
|
||||||
|
locname = cmds.spaceLocator(name = strname)
|
||||||
|
mocaphelperutility.setWorldPos(locname,cd)
|
||||||
|
mocaphelperutility.setWorldRot(locname,rot,roo)
|
||||||
|
return locname
|
||||||
|
|
||||||
|
def reposition(objA,objB):
|
||||||
|
tempp = mocaphelperutility.getWorldPos(objB)
|
||||||
|
tempr = mocaphelperutility.getWorldRot(objB)
|
||||||
|
temproo = mocaphelperutility.getRotOrder(objB)
|
||||||
|
mocaphelperutility.setWorldPos(objA,tempp)
|
||||||
|
mocaphelperutility.setWorldRot(objA,tempr,temproo)
|
||||||
|
|
||||||
|
|
||||||
|
def checkConstraint(obj):
|
||||||
|
parent = cmds.parentConstraint(obj, targetList = True ,q = True )
|
||||||
|
point = cmds.pointConstraint(obj, targetList = True ,q = True )
|
||||||
|
orient = cmds.orientConstraint(obj, targetList = True ,q = True )
|
||||||
|
if parent == None and point == None and orient == None:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
conslist = [parent,point,orient]
|
||||||
|
return conslist
|
||||||
|
|
||||||
|
def deleteAllConstraint(obj):
|
||||||
|
cmds.delete(obj,cn=True)
|
||||||
|
|
||||||
|
def createPointConstraint(ctrlobj,targetobj,maintainoffset = False):
|
||||||
|
name = cmds.pointConstraint(ctrlobj,targetobj,mo = maintainoffset)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def createOrientConstraint(ctrlobj,targetobj,maintainoffset = False):
|
||||||
|
name = cmds.orientConstraint(ctrlobj,targetobj,mo = maintainoffset)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def createParentConstraint(ctrlobj,targetobj,maintainoffset = False):
|
||||||
|
name = cmds.parentConstraint(ctrlobj,targetobj,mo = maintainoffset)
|
||||||
|
return name
|
||||||
|
'''
|
||||||
|
def deletePointConstraint(ctrlobj,targetobj):
|
||||||
|
cmds.pointConstraint(ctrlobj,targetobj,remove = True)
|
||||||
|
|
||||||
|
def deleteParentConstraint(ctrlobj,targetobj):
|
||||||
|
cmds.parentConstraint(ctrlobj,targetobj,remove = True)
|
||||||
|
|
||||||
|
def deleteOrientConstraint(ctrlobj,targetobj):
|
||||||
|
cmds.orientConstraint(ctrlobj,targetobj,remove = True)
|
||||||
|
'''
|
||||||
|
def bake(objs,mintime,maxtime,type = "all"):
|
||||||
|
# if smartbake == True:
|
||||||
|
if type == "all":
|
||||||
|
cmds.bakeResults(objs,t =(mintime,maxtime),simulation = True)
|
||||||
|
else:
|
||||||
|
if type == "parent":
|
||||||
|
atb = ["tx","ty","tz","sx","sy","sz","rx","ry","rz"]
|
||||||
|
|
||||||
|
elif type == "point":
|
||||||
|
atb = ["tx","ty","tz"]
|
||||||
|
|
||||||
|
elif type == "orient":
|
||||||
|
atb = ["rx","ry","rz"]
|
||||||
|
|
||||||
|
elif type == "onlyscale":
|
||||||
|
atb = ["sx","sy","sz"]
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise Exception("bake error:type unidentified:",type)
|
||||||
|
cmds.bakeResults(objs,t =(mintime,maxtime),at = atb)
|
||||||
|
|
||||||
|
def smartbake(objs,mintime,maxtime,type = "all"):
|
||||||
|
if type == "all":
|
||||||
|
cmds.bakeResults(objs,t =(mintime,maxtime),smart = True,simulation = True)
|
||||||
|
else:
|
||||||
|
if type == "parent":
|
||||||
|
atb = ["tx","ty","tz","sx","sy","sz","rx","ry","rz"]
|
||||||
|
|
||||||
|
elif type == "point":
|
||||||
|
atb = ["tx","ty","tz"]
|
||||||
|
|
||||||
|
elif type == "orient":
|
||||||
|
atb = ["rx","ry","rz"]
|
||||||
|
|
||||||
|
elif type == "onlyscale":
|
||||||
|
atb = ["sx","sy","sz"]
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise Exception("bake error:type unidentified")
|
||||||
|
cmds.bakeResults(objs,t =(mintime,maxtime),smart = True,at = atb)
|
||||||
|
|
||||||
|
|
||||||
|
def deleteInrange(objs,start,end):
|
||||||
|
if cmds.keyframe(objs,q = True) == None :
|
||||||
|
raise Exception("ref has no keys!")
|
||||||
|
else:
|
||||||
|
mocaphelperutility.cutKey(objs,start+0.01,end-0.01)
|
||||||
|
# mocaphelperutility.autoKetTangent(objs,start,start)
|
||||||
|
# mocaphelperutility.autoKetTangent(objs,end,end)
|
||||||
|
|
||||||
|
def deleteOutrange(objs,start,end):
|
||||||
|
if cmds.keyframe(objs,q = True) == None :
|
||||||
|
raise Exception("ref has no keys!")
|
||||||
|
|
||||||
|
framelist = set(cmds.keyframe(objs,q = True))
|
||||||
|
minframe = min(framelist)
|
||||||
|
maxframe = max(framelist)
|
||||||
|
if minframe < start:
|
||||||
|
mocaphelperutility.cutKey(objs,minframe,start-0.01)
|
||||||
|
# mocaphelperutility.autoKetTangent(objs,start,start)
|
||||||
|
if maxframe > end:
|
||||||
|
mocaphelperutility.cutKey(objs,end+0.01,maxframe)
|
||||||
|
# mocaphelperutility.autoKetTangent(objs,end,end)
|
||||||
|
|
||||||
|
|
||||||
|
def offsetFrame(objs,offset):
|
||||||
|
cmds.keyframe(objs,e = True,tc = float(offset),o = "over",relative = True)
|
||||||
|
|
||||||
|
def stickyDelete(ui):
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
fromframe = eval(ui.ui.arb_fromEdit.text())
|
||||||
|
curframe = mocaphelperutility.getCurrentFrame()
|
||||||
|
if fromframe != curframe:
|
||||||
|
mocaphelperutility.cutKey(objs,fromframe,curframe,True)
|
||||||
|
mocaphelperutility.autoKetTangent(objs,fromframe,curframe)
|
||||||
|
ui.ui.arb_fromEdit.setText(str(curframe))
|
||||||
|
ui.ui.arb_toEdit.setText(str(curframe))
|
||||||
|
else:
|
||||||
|
raise Exception("from == curframe")
|
||||||
|
|
||||||
|
|
||||||
|
def bakeAtoB(A,B,start,end,type,maintainoffset = False,smart = False):
|
||||||
|
print("type == ",type)
|
||||||
|
if type == "parent" or type == "all":
|
||||||
|
cons = createParentConstraint(A,B,maintainoffset)
|
||||||
|
elif type == "point":
|
||||||
|
cons = createPointConstraint(A,B,maintainoffset)
|
||||||
|
elif type == "orient":
|
||||||
|
cons = createOrientConstraint(A,B,maintainoffset)
|
||||||
|
elif type == "onlyscale":
|
||||||
|
cons = createParentConstraint(A,B,maintainoffset)
|
||||||
|
|
||||||
|
if smart:
|
||||||
|
smartbake(B,start,end,type)
|
||||||
|
else:
|
||||||
|
bake(B,start,end,type)
|
||||||
|
|
||||||
|
mocaphelperutility.deleteObj(cons)
|
||||||
|
|
||||||
|
|
||||||
|
def pinCurPos(objs,mintime,maxtime):
|
||||||
|
min = mintime
|
||||||
|
max = maxtime
|
||||||
|
if min > max:
|
||||||
|
min = maxtime
|
||||||
|
max = mintime
|
||||||
|
if min == max:
|
||||||
|
raise Exception("min == max.")
|
||||||
|
|
||||||
|
|
||||||
|
cdlist = []
|
||||||
|
# cmds.currentTime(min)
|
||||||
|
for obj in objs:
|
||||||
|
|
||||||
|
pos = mocaphelperutility.getWorldPos(obj)
|
||||||
|
rot = mocaphelperutility.getWorldRot(obj)
|
||||||
|
cdlist.append([pos,rot])
|
||||||
|
for i in range(int(math.floor(min)),int(math.ceil(max)+1)):
|
||||||
|
|
||||||
|
cmds.currentTime(float(i))
|
||||||
|
cmds.setKeyframe(objs,at = ["tx","ty","tz","rx","ry","rz"])
|
||||||
|
for i in range(len(objs)):
|
||||||
|
pos = cdlist[i][0]
|
||||||
|
rot = cdlist[i][1]
|
||||||
|
cmds.xform(objs[i],ws = True,translation = pos,rotation = rot)
|
||||||
|
|
||||||
|
|
||||||
|
def pinParentPos(objs,mintime,maxtime):
|
||||||
|
|
||||||
|
leng = len(objs)
|
||||||
|
if leng <= 1:
|
||||||
|
raise Exception("not enough obj selected,at least 2.")
|
||||||
|
min = mintime
|
||||||
|
max = maxtime
|
||||||
|
if min > max:
|
||||||
|
min = maxtime
|
||||||
|
max = mintime
|
||||||
|
if min == max:
|
||||||
|
raise Exception("min == max.")
|
||||||
|
|
||||||
|
|
||||||
|
# cmds.currentTime(min)
|
||||||
|
consobj = objs[:-1]
|
||||||
|
beconsobj = objs[-1]
|
||||||
|
|
||||||
|
pos = mocaphelperutility.getWorldPos(beconsobj)
|
||||||
|
rot = mocaphelperutility.getWorldRot(beconsobj)
|
||||||
|
roo = mocaphelperutility.getRotOrder(beconsobj)
|
||||||
|
loc = createLoc("mocaphelper_arb_pinparent_temp_loc",pos,rot,roo)[0]
|
||||||
|
createParentConstraint(consobj,loc,True)
|
||||||
|
bake(loc,min,max,type="parent")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(int(math.floor(min)),int(math.ceil(max)+1)):
|
||||||
|
|
||||||
|
cmds.currentTime(float(i))
|
||||||
|
cmds.setKeyframe(beconsobj,at = ["tx","ty","tz","rx","ry","rz"])
|
||||||
|
reposition(beconsobj,loc)
|
||||||
|
|
||||||
|
mocaphelperutility.deleteObj(loc)
|
||||||
|
mocaphelperutility.selectNodes(beconsobj)
|
100
Scripts/Animation/MotionCapHelper/bin/mocaphelperfacore.py
Normal file
100
Scripts/Animation/MotionCapHelper/bin/mocaphelperfacore.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import maya.api.OpenMaya as om
|
||||||
|
import maya.api.OpenMayaAnim as omani
|
||||||
|
import maya.cmds as cmds
|
||||||
|
|
||||||
|
import maya.mel as mel
|
||||||
|
|
||||||
|
import mocaphelperutility
|
||||||
|
|
||||||
|
refobjsShortFlagName = "-ref"
|
||||||
|
refobjsLongFlagName = "-refobjs"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def syntaxCreator():
|
||||||
|
|
||||||
|
syntax = om.MSyntax()
|
||||||
|
|
||||||
|
syntax.addFlag( refobjsShortFlagName, refobjsLongFlagName, om.MSyntax.kString )
|
||||||
|
|
||||||
|
|
||||||
|
return syntax
|
||||||
|
|
||||||
|
class FrameAlign(om.MPxCommand):
|
||||||
|
kPluginCmdName = "moCapHelper_frameAlign"
|
||||||
|
|
||||||
|
ref = ""
|
||||||
|
animcruvechanage = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
om.MPxCommand.__init__(self)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cmdCreator():
|
||||||
|
return FrameAlign()
|
||||||
|
|
||||||
|
|
||||||
|
def parseArguments(self,args):
|
||||||
|
|
||||||
|
argdata = om.MArgParser(self.syntax(),args)
|
||||||
|
|
||||||
|
if argdata.isFlagSet( refobjsShortFlagName ):
|
||||||
|
self.ref = argdata.flagArgumentString(refobjsShortFlagName,0)
|
||||||
|
else:
|
||||||
|
raise Exception("No refence argument!")
|
||||||
|
|
||||||
|
def isUndoable(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def doIt(self,args):
|
||||||
|
self.animcruvechanage = omani.MAnimCurveChange()
|
||||||
|
self.parseArguments(args)
|
||||||
|
# start = cmds.playbackOptions( q=True,min=True )
|
||||||
|
# end = cmds.playbackOptions( q=True,max=True )
|
||||||
|
if mocaphelperutility.objExist(self.ref) == False:
|
||||||
|
raise Exception("ref obj does not exist!")
|
||||||
|
selectedobjs = mocaphelperutility.getSelectedNodes()
|
||||||
|
print(self.ref)
|
||||||
|
if cmds.keyframe(self.ref,q = True) == None :
|
||||||
|
raise Exception("ref has no keys!")
|
||||||
|
else:
|
||||||
|
framelist = set(cmds.keyframe(self.ref,q = True))
|
||||||
|
for frame in framelist:
|
||||||
|
cmds.setKeyframe(selectedobjs,t = (frame,frame),rk= True,hierarchy = "none",i = True,itt = "auto")
|
||||||
|
|
||||||
|
for obj in selectedobjs:
|
||||||
|
objframelist = set(cmds.keyframe(obj,q = True))
|
||||||
|
for objframe in objframelist:
|
||||||
|
if objframe in framelist:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
mocaphelperutility.cutKey(obj,objframe,objframe)
|
||||||
|
|
||||||
|
|
||||||
|
def undoIt(self):
|
||||||
|
if self.animcruvechanage != None :
|
||||||
|
self.animcruvechanage.undoIt()
|
||||||
|
print("undo success")
|
||||||
|
else:
|
||||||
|
print("undo failed:self.animcruvechanage == None")
|
||||||
|
|
||||||
|
def redoIt(self):
|
||||||
|
if self.animcruvechanage != None :
|
||||||
|
self.animcruvechanage.redoIt()
|
||||||
|
print("redo success")
|
||||||
|
else:
|
||||||
|
print("redo failed:self.animcruvechanage == None")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# def cutlist(sourcelist,splitlist):
|
||||||
|
# backindex = 0
|
||||||
|
# forwardindex = 0
|
||||||
|
# for i in len(sourcelist):
|
||||||
|
# if sourcelist[i] in splitlist:
|
||||||
|
|
||||||
|
# def fastRecord(obj):
|
||||||
|
# pos = mocaphelperutility.getWorldPos(obj)
|
||||||
|
# loc = mocaphelperarbcore.createLoc("mocaphelper_fa_temp_loc")
|
53
Scripts/Animation/MotionCapHelper/bin/mocaphelperpbcore.py
Normal file
53
Scripts/Animation/MotionCapHelper/bin/mocaphelperpbcore.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import datetime
|
||||||
|
import getpass
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import maya.cmds as cmds
|
||||||
|
import maya.mel as mel
|
||||||
|
|
||||||
|
|
||||||
|
PREV_DIR_ENV = "Mocaphelper_Playblast_Path"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_prev_path():
|
||||||
|
if cmds.optionVar(exists=PREV_DIR_ENV):
|
||||||
|
return cmds.optionVar(q=PREV_DIR_ENV)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_prev_path(dir_path):
|
||||||
|
cmds.optionVar(sv=(PREV_DIR_ENV, dir_path))
|
||||||
|
|
||||||
|
|
||||||
|
def getMagicMaskNode():
|
||||||
|
magic_mask_nodes = cmds.ls(type='magicMask')
|
||||||
|
if magic_mask_nodes == None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return magic_mask_nodes[0]
|
||||||
|
|
||||||
|
|
||||||
|
def resetHUD():
|
||||||
|
mel.eval('source "initHUD";')
|
||||||
|
|
||||||
|
|
||||||
|
def removeHUD():
|
||||||
|
default_hud_list = cmds.headsUpDisplay(lh=True)
|
||||||
|
if default_hud_list:
|
||||||
|
for default_hud in default_hud_list:
|
||||||
|
cmds.headsUpDisplay(default_hud, rem=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# cmds.setAttr('%s.displayFilmGate' % main_cam, 0)
|
||||||
|
# cmds.setAttr('%s.displayResolution' % main_cam, 0)
|
||||||
|
|
||||||
|
|
||||||
|
def moCapHelper_Playblast(cam,filepath,offscreen):
|
||||||
|
pass
|
168
Scripts/Animation/MotionCapHelper/bin/mocaphelperrecore.py
Normal file
168
Scripts/Animation/MotionCapHelper/bin/mocaphelperrecore.py
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
import maya.api.OpenMaya as om
|
||||||
|
import maya.cmds as cmds
|
||||||
|
import maya.mel as mel
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
import mocaphelperutility
|
||||||
|
|
||||||
|
|
||||||
|
def retestlist(strlist,exp,casecheck = False):
|
||||||
|
matchlist = []
|
||||||
|
pyVersion = mocaphelperutility.getPythonVersion()
|
||||||
|
if pyVersion < 3:
|
||||||
|
|
||||||
|
if (type(exp)== unicode ):
|
||||||
|
raw_exp = repr(exp)[2:-1]
|
||||||
|
elif (type(exp)== str ):
|
||||||
|
raw_exp = exp
|
||||||
|
else:
|
||||||
|
raise Exception("unidentified string format input!")
|
||||||
|
|
||||||
|
else:
|
||||||
|
raw_exp = exp
|
||||||
|
|
||||||
|
print("convert---"+exp+"---to---"+raw_exp)
|
||||||
|
for longname in strlist:
|
||||||
|
shortname = longname2shortname(longname)[0]
|
||||||
|
print("checking:---exp---"+raw_exp+"---objname---"+shortname)
|
||||||
|
if casecheck == False:
|
||||||
|
if re.search(raw_exp,shortname,re.I) != None:
|
||||||
|
matchlist.append(longname)
|
||||||
|
print("succeed")
|
||||||
|
else:
|
||||||
|
print("failed")
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if re.search(raw_exp,shortname) != None:
|
||||||
|
matchlist.append(longname)
|
||||||
|
print("succeed")
|
||||||
|
else:
|
||||||
|
print("failed")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(matchlist) == 0:
|
||||||
|
print("no obj match expression!")
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return matchlist
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def expCreateDisplayLayer(exp,name,prefix = "",casecheck = False,childcheck = True,nodetype = "all"):
|
||||||
|
selected = mocaphelperutility.getSelectedNodes()
|
||||||
|
if childcheck:
|
||||||
|
|
||||||
|
untestlist = mocaphelperutility.getChildNodes(selected,nodetype=nodetype)
|
||||||
|
else:
|
||||||
|
untestlist = selected
|
||||||
|
combinelist = []
|
||||||
|
#check for multiple exp exist
|
||||||
|
if exp.find(";") != -1 or name.find(";") != -1:
|
||||||
|
splitedexplist = exp.split(";")
|
||||||
|
splitednamelist = name.split(";")
|
||||||
|
if len(splitedexplist) != len(splitednamelist):
|
||||||
|
raise Exception("name and exp count not match!")
|
||||||
|
else:
|
||||||
|
for i in range(len(splitedexplist)):
|
||||||
|
combinelist.append([splitedexplist[i],splitednamelist[i]])
|
||||||
|
else:
|
||||||
|
combinelist =[[exp,name]]
|
||||||
|
|
||||||
|
for combine in combinelist:
|
||||||
|
|
||||||
|
matchlist = retestlist(untestlist,combine[0],casecheck)
|
||||||
|
print("matchlist:",matchlist)
|
||||||
|
|
||||||
|
createDisplayLayer(prefix+combine[1],matchlist)
|
||||||
|
|
||||||
|
|
||||||
|
def createDisplayLayer(name,objlist):
|
||||||
|
cmds.createDisplayLayer(n= name,nr = True,empty = True)
|
||||||
|
cmds.editDisplayLayerMembers(name,objlist,nr = True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def extractLayerInfo(ui):
|
||||||
|
name = cmds.editDisplayLayerGlobals( query=True, cdl=True )
|
||||||
|
members =cmds.editDisplayLayerMembers( name, query=True )
|
||||||
|
exp = ""
|
||||||
|
for member in members:
|
||||||
|
noPrefixMember = deleteRigPrefix(member)
|
||||||
|
if noPrefixMember[1] == True:
|
||||||
|
exp = exp+"."+ noPrefixMember[0] +"|"
|
||||||
|
else:
|
||||||
|
exp = exp+ noPrefixMember[0] +"|"
|
||||||
|
# remove last "|",cause it will match all name str.
|
||||||
|
exp = exp[0:-1]
|
||||||
|
ui.ui.re_layerNameEdit.setText(name)
|
||||||
|
ui.ui.re_expEdit.setText(exp)
|
||||||
|
return
|
||||||
|
|
||||||
|
def selMainCtrl():
|
||||||
|
# main name:
|
||||||
|
# ".MainExtra2" ".wenchangtai" ".Main_all"
|
||||||
|
curves = cmds.ls(type = "dagNode")
|
||||||
|
curves = mocaphelperutility.filterCertainTypeInList(curves,type = "nurbsCurve")
|
||||||
|
matchlist = []
|
||||||
|
a = retestlist(curves,".MainExtra2$|.wenchangtai$|.Main_all$")
|
||||||
|
if a != None:
|
||||||
|
matchlist += a
|
||||||
|
cmds.select(cl = True)
|
||||||
|
cmds.select(matchlist)
|
||||||
|
|
||||||
|
|
||||||
|
def longname2shortname(name):
|
||||||
|
id = name.rfind("|")
|
||||||
|
if id == -1:
|
||||||
|
return name,False
|
||||||
|
else:
|
||||||
|
return name[id+1:],True
|
||||||
|
|
||||||
|
def deleteRigPrefix(name):
|
||||||
|
id = name.rfind(":")
|
||||||
|
if id == -1:
|
||||||
|
return name,False
|
||||||
|
else:
|
||||||
|
return name[id:],True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def presetfileRebuild(filepath,backupfilepath):
|
||||||
|
backupstr = presetFileRead(backupfilepath)
|
||||||
|
presetFileWrite(filepath,backupstr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def rawStrBuild(rawstr):
|
||||||
|
split = rawstr.split("\n")
|
||||||
|
newlist = []
|
||||||
|
for i in range(int(len(split)/2)):
|
||||||
|
name = split[2*i]
|
||||||
|
exp = split[2*i+1]
|
||||||
|
newlist.append([name,exp])
|
||||||
|
if len(newlist) == 0:
|
||||||
|
raise Exception("split list is empty!")
|
||||||
|
else:
|
||||||
|
return newlist
|
||||||
|
|
||||||
|
def strAppend(oristr,line1,line2):
|
||||||
|
newstr = oristr+"\n"+str(line1)+"\n"+str(line2)
|
||||||
|
return newstr
|
||||||
|
|
||||||
|
|
||||||
|
def presetFileRead(filepath):
|
||||||
|
file = open(filepath,mode ="r+")
|
||||||
|
file.seek(0,0)
|
||||||
|
raw = file.read()
|
||||||
|
file.close()
|
||||||
|
return raw
|
||||||
|
|
||||||
|
|
||||||
|
def presetFileWrite(filepath,str):
|
||||||
|
print("writing file:\n"+str)
|
||||||
|
file = open(filepath,mode ="w+")
|
||||||
|
file.seek(0,0)
|
||||||
|
file.write(str)
|
||||||
|
file.close()
|
||||||
|
|
278
Scripts/Animation/MotionCapHelper/bin/mocaphelpersaccore.py
Normal file
278
Scripts/Animation/MotionCapHelper/bin/mocaphelpersaccore.py
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
import maya.api.OpenMaya as om
|
||||||
|
import maya.api.OpenMayaAnim as omani
|
||||||
|
import maya.cmds as cmds
|
||||||
|
|
||||||
|
import maya.mel as mel
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
# selectionList = om.MGlobal.getActiveSelectionList()
|
||||||
|
# iterator = om.MItSelectionList( selectionList, om.MFn.kDagNode )
|
||||||
|
methodShortFlagName = "-m"
|
||||||
|
methodLongFlagName = "-method"
|
||||||
|
iterShortFlagName = "-i"
|
||||||
|
iterLongFlagName = "-iteration"
|
||||||
|
intensityShortFlagName = "-in"
|
||||||
|
intensityLongFlagName = "-intensity"
|
||||||
|
seltypeShortFlagName = "-sel"
|
||||||
|
seltypeLongFlagName = "-selecttype"
|
||||||
|
useTimeShortFlagName = "-u"
|
||||||
|
useTimeLongFlagName = "-usetime"
|
||||||
|
timeUnitShortFlagName = "-tu"
|
||||||
|
timeUnitLongFlagName = "-timeunit"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def syntaxCreator():
|
||||||
|
|
||||||
|
syntax = om.MSyntax()
|
||||||
|
|
||||||
|
syntax.addFlag( methodShortFlagName, methodLongFlagName, om.MSyntax.kString )
|
||||||
|
syntax.addFlag( iterShortFlagName, iterLongFlagName, om.MSyntax.kLong )
|
||||||
|
syntax.addFlag( intensityShortFlagName, intensityLongFlagName, om.MSyntax.kDouble )
|
||||||
|
syntax.addFlag( seltypeShortFlagName, seltypeLongFlagName, om.MSyntax.kLong )
|
||||||
|
syntax.addFlag( useTimeShortFlagName, useTimeLongFlagName, om.MSyntax.kBoolean )
|
||||||
|
syntax.addFlag( timeUnitShortFlagName, timeUnitLongFlagName, om.MSyntax.kDouble )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return syntax
|
||||||
|
|
||||||
|
|
||||||
|
class SmoothAnimCurve(om.MPxCommand):
|
||||||
|
kPluginCmdName = "moCapHelper_smoothAniCurve"
|
||||||
|
method = 0
|
||||||
|
iteration = 1
|
||||||
|
intensity = 1.0
|
||||||
|
seltype = 0
|
||||||
|
useTime = True
|
||||||
|
timeUnit = 5.0
|
||||||
|
|
||||||
|
animcruvechanage = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
om.MPxCommand.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
|
def parseArguments(self,args):
|
||||||
|
|
||||||
|
argdata = om.MArgParser(self.syntax(),args)
|
||||||
|
|
||||||
|
if argdata.isFlagSet( methodShortFlagName ):
|
||||||
|
if argdata.flagArgumentString(methodShortFlagName,0) == "3linear":
|
||||||
|
self.method = 0
|
||||||
|
elif argdata.flagArgumentString(methodShortFlagName,0) == "3bell":
|
||||||
|
self.method = 1
|
||||||
|
elif argdata.flagArgumentString(methodShortFlagName,0) == "3ham":
|
||||||
|
self.method = 2
|
||||||
|
elif argdata.flagArgumentString(methodShortFlagName,0) == "5quad":
|
||||||
|
self.method = 10
|
||||||
|
elif argdata.flagArgumentString(methodShortFlagName,0) == "5bell":
|
||||||
|
self.method = 11
|
||||||
|
elif argdata.flagArgumentString(methodShortFlagName,0) == "5ham":
|
||||||
|
self.method = 12
|
||||||
|
else:
|
||||||
|
raise Exception("input method argument is not vaild!"+str(argdata.flagArgumentString(methodShortFlagName,0)))
|
||||||
|
else:
|
||||||
|
raise Exception("no input method argument")
|
||||||
|
|
||||||
|
if argdata.isFlagSet( iterShortFlagName ):
|
||||||
|
if argdata.flagArgumentInt(iterShortFlagName,0) <= 100:
|
||||||
|
self.iteration = argdata.flagArgumentInt(iterShortFlagName,0)
|
||||||
|
else:
|
||||||
|
raise Exception("iteration is bigger than 100,little bit too high,right?")
|
||||||
|
|
||||||
|
if argdata.isFlagSet( intensityShortFlagName ):
|
||||||
|
self.intensity = argdata.flagArgumentFloat(intensityShortFlagName,0)
|
||||||
|
|
||||||
|
if argdata.isFlagSet( seltypeShortFlagName ):
|
||||||
|
self.seltype = argdata.flagArgumentInt(seltypeShortFlagName,0)
|
||||||
|
|
||||||
|
if argdata.isFlagSet( useTimeShortFlagName ):
|
||||||
|
self.useTime = argdata.flagArgumentBool(useTimeShortFlagName,0)
|
||||||
|
|
||||||
|
if argdata.isFlagSet( timeUnitShortFlagName ):
|
||||||
|
self.timeUnit = argdata.flagArgumentFloat(timeUnitShortFlagName,0)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cmdCreator():
|
||||||
|
return SmoothAnimCurve()
|
||||||
|
|
||||||
|
def doIt(self, args):
|
||||||
|
|
||||||
|
self.animcruvechanage = omani.MAnimCurveChange()
|
||||||
|
self.parseArguments(args)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
animcurves = self.getanimcurves()
|
||||||
|
|
||||||
|
for iter in range(self.iteration):
|
||||||
|
|
||||||
|
for cv in animcurves:
|
||||||
|
keylist = self.getkeylist(cv)
|
||||||
|
templist = self.smoothkeylistvalue(cv,keylist)
|
||||||
|
print(templist)
|
||||||
|
mslist = om.MGlobal.getSelectionListByName(repr(cv)[2:-1])
|
||||||
|
mit = om.MItSelectionList(mslist)
|
||||||
|
mobj = mit.getDependNode()
|
||||||
|
manimcurve = omani.MFnAnimCurve(mobj)
|
||||||
|
curveisangular = False
|
||||||
|
if manimcurve.animCurveType == manimcurve.kAnimCurveTA or manimcurve.animCurveType == manimcurve.kAnimCurveUA :
|
||||||
|
curveisangular = True
|
||||||
|
for i in templist:
|
||||||
|
if curveisangular:
|
||||||
|
value = math.radians(i[1])
|
||||||
|
else:
|
||||||
|
value = i[1]
|
||||||
|
manimcurve.setValue(i[0],value,self.animcruvechanage)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
print("using smoothanimcurve cmd with argument:\nselect type:",self.seltype,"\niteration:",self.iteration,"\nintensity:",self.intensity,"\nusetime:",self.useTime,"\ntimeunit:",self.timeUnit,"\nmethod:",self.method)
|
||||||
|
|
||||||
|
|
||||||
|
def undoIt(self):
|
||||||
|
if self.animcruvechanage != None :
|
||||||
|
self.animcruvechanage.undoIt()
|
||||||
|
print("undo success")
|
||||||
|
else:
|
||||||
|
print("undo failed:self.animcruvechanage == None")
|
||||||
|
|
||||||
|
def redoIt(self):
|
||||||
|
if self.animcruvechanage != None :
|
||||||
|
self.animcruvechanage.redoIt()
|
||||||
|
print("redo success")
|
||||||
|
else:
|
||||||
|
print("redo failed:self.animcruvechanage == None")
|
||||||
|
|
||||||
|
def isUndoable(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def getanimcurves(self):
|
||||||
|
selectflag = cmds.animCurveEditor("graphEditor1GraphEd",query = True,areCurvesSelected = True)
|
||||||
|
showncurves = cmds.animCurveEditor("graphEditor1GraphEd",query = True,curvesShown = True)
|
||||||
|
selectedcurves = cmds.keyframe(q = True,s = True,name = True)
|
||||||
|
isoflag = 0
|
||||||
|
if showncurves == None:
|
||||||
|
raise Exception("plugin can't find any curve in graph editor,no curve shown or selected.")
|
||||||
|
else:
|
||||||
|
isoflag = len(showncurves) != len(selectedcurves)
|
||||||
|
|
||||||
|
if selectflag:
|
||||||
|
return selectedcurves
|
||||||
|
if isoflag:
|
||||||
|
self.seltype == 0
|
||||||
|
return showncurves
|
||||||
|
else:
|
||||||
|
raise Exception("plugin can't find any curve in graph editor,no curve shown or selected.")
|
||||||
|
|
||||||
|
# if selectflag:
|
||||||
|
# return selectedcurves
|
||||||
|
# else:
|
||||||
|
# return showncurves
|
||||||
|
# print(showncurves)
|
||||||
|
# print("----------------")
|
||||||
|
# print(selectedcurves)
|
||||||
|
|
||||||
|
def getkeylist(self,animcurve):
|
||||||
|
numkeys = cmds.keyframe(animcurve,q = True,keyframeCount = True)
|
||||||
|
keylist = []
|
||||||
|
#seltype == 0 :all keys on curves
|
||||||
|
if self.seltype == 0:
|
||||||
|
for i in range(numkeys):
|
||||||
|
keylist.append([i,0.0])
|
||||||
|
#seltype == 1 :selected keys only
|
||||||
|
elif self.seltype == 1:
|
||||||
|
numselkeyindexlist = cmds.keyframe(animcurve,sl = True,q=True,indexValue = True)
|
||||||
|
for index in numselkeyindexlist:
|
||||||
|
keylist.append([int(index),0.0])
|
||||||
|
return keylist
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def smoothkeylistvalue(self,curve,keylist):
|
||||||
|
flag5pt = False
|
||||||
|
compareint = 0
|
||||||
|
if self.method>=9:
|
||||||
|
compareint = 1
|
||||||
|
flag5pt = True
|
||||||
|
numkeys = cmds.keyframe(curve,q = True,keyframeCount = True)
|
||||||
|
for key in keylist:
|
||||||
|
time = getkeytime(curve,key[0])
|
||||||
|
value = getkeyvalue(curve,time)
|
||||||
|
|
||||||
|
|
||||||
|
if key[0] <=compareint or numkeys-key[0]<=compareint+1:
|
||||||
|
|
||||||
|
key[1] = value
|
||||||
|
|
||||||
|
else:
|
||||||
|
pretime2 = 0
|
||||||
|
prevalue2 = 0
|
||||||
|
nexttime2 = 0
|
||||||
|
nextvalue2 = 0
|
||||||
|
|
||||||
|
pretime = getkeytime(curve,key[0]-1)
|
||||||
|
nexttime = getkeytime(curve,key[0]+1)
|
||||||
|
|
||||||
|
if self.useTime:
|
||||||
|
pretime = time - self.timeUnit
|
||||||
|
nexttime = time + self.timeUnit
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
prevalue = getkeyvalue(curve,pretime)
|
||||||
|
nextvalue = getkeyvalue(curve,nexttime)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if flag5pt:
|
||||||
|
pretime2 = getkeytime(curve,key[0]-2)
|
||||||
|
nexttime2 = getkeytime(curve,key[0]+2)
|
||||||
|
|
||||||
|
if self.useTime:
|
||||||
|
pretime2 = time - self.timeUnit*2
|
||||||
|
nexttime2 = time + self.timeUnit*2
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
prevalue2 = getkeyvalue(curve,pretime2)
|
||||||
|
nextvalue2 = getkeyvalue(curve,nexttime2)
|
||||||
|
|
||||||
|
if self.method == 0:
|
||||||
|
tempvalue = value+prevalue+nextvalue
|
||||||
|
key[1] = lerp(value,tempvalue/3,self.intensity)
|
||||||
|
elif self.method == 1:
|
||||||
|
tempvalue = 0.576*value+0.212*prevalue+0.212*nextvalue
|
||||||
|
key[1] = lerp(value,tempvalue,self.intensity)
|
||||||
|
elif self.method == 2:
|
||||||
|
tempvalue = 0.86*value+0.07*prevalue+0.07*nextvalue
|
||||||
|
key[1] = lerp(value,tempvalue,self.intensity)
|
||||||
|
elif self.method == 10:
|
||||||
|
tempvalue = 12*prevalue+nextvalue-3*prevalue2+nextvalue2+17*value
|
||||||
|
key[1] = lerp(value,tempvalue/35,self.intensity)
|
||||||
|
elif self.method == 11:
|
||||||
|
tempvalue = 0.11*(prevalue2+nextvalue2)+0.24*(prevalue+nextvalue)+0.3*(value)
|
||||||
|
key[1] = lerp(value,tempvalue,self.intensity)
|
||||||
|
elif self.method == 12:
|
||||||
|
tempvalue = 0.04*(prevalue2+nextvalue2)+0.24*(prevalue+nextvalue)+0.44*(value)
|
||||||
|
key[1] = lerp(value,tempvalue,self.intensity)
|
||||||
|
else:
|
||||||
|
raise Exception("method error while using smoothkeylistvalue()")
|
||||||
|
|
||||||
|
return keylist
|
||||||
|
|
||||||
|
def getkeytime(curve,id):
|
||||||
|
time = cmds.keyframe(curve,index=(id,id),q=True)[0]
|
||||||
|
return time
|
||||||
|
def getkeyvalue(curve,time):
|
||||||
|
value = cmds.keyframe(curve,t = (time,time),ev = True , q = True )[0]
|
||||||
|
return value
|
||||||
|
def lerp(originvalue,newvalue,intensity):
|
||||||
|
temp = newvalue-originvalue
|
||||||
|
return originvalue+temp*intensity
|
||||||
|
|
661
Scripts/Animation/MotionCapHelper/bin/mocaphelperui.py
Normal file
661
Scripts/Animation/MotionCapHelper/bin/mocaphelperui.py
Normal file
@ -0,0 +1,661 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from mocaphelper import version
|
||||||
|
import mocaphelperutility
|
||||||
|
import mocaphelperrecore
|
||||||
|
import mocaphelperarbcore
|
||||||
|
|
||||||
|
|
||||||
|
from maya import cmds
|
||||||
|
from maya import mel
|
||||||
|
from maya import OpenMayaUI as omui
|
||||||
|
|
||||||
|
from PySide2.QtCore import *
|
||||||
|
from PySide2.QtGui import *
|
||||||
|
from PySide2.QtWidgets import *
|
||||||
|
from PySide2.QtUiTools import *
|
||||||
|
from shiboken2 import wrapInstance
|
||||||
|
|
||||||
|
mayaMainWindowPtr = omui.MQtUtil.mainWindow()
|
||||||
|
pyVersion = mocaphelperutility.getPythonVersion()
|
||||||
|
if pyVersion < 3:
|
||||||
|
mayaMainWindow = wrapInstance(long(mayaMainWindowPtr), QWidget)
|
||||||
|
else:
|
||||||
|
mayaMainWindow = wrapInstance(int(mayaMainWindowPtr), QWidget)
|
||||||
|
|
||||||
|
|
||||||
|
class MoCapHelperUI(QWidget):
|
||||||
|
#sac:
|
||||||
|
sac_iteration = 1
|
||||||
|
sac_intensity = 1.0
|
||||||
|
sac_useTime = True
|
||||||
|
sac_method = "3linear"
|
||||||
|
sac_selType = "curves"
|
||||||
|
sac_timeUnit = 5.0
|
||||||
|
|
||||||
|
#fa:
|
||||||
|
fa_refobjs = None
|
||||||
|
|
||||||
|
#re:
|
||||||
|
re_exp = ""
|
||||||
|
re_name = ""
|
||||||
|
re_caseCheck = False
|
||||||
|
re_prefix = ""
|
||||||
|
|
||||||
|
#arb:
|
||||||
|
arb_fromtime = 10.0
|
||||||
|
arb_totime = 11.0
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
|
super(MoCapHelperUI, self).__init__(*args, **kwargs)
|
||||||
|
self.setParent(mayaMainWindow)
|
||||||
|
self.setWindowFlags(Qt.Window)
|
||||||
|
self.setObjectName('mocaphelperui')
|
||||||
|
self.setWindowTitle('moCapHelper v'+str(version))
|
||||||
|
self.loadUI()
|
||||||
|
self.initSac()
|
||||||
|
self.initFa()
|
||||||
|
self.initre()
|
||||||
|
self.intiArb()
|
||||||
|
self.re_exp = self.ui.re_expEdit.text()
|
||||||
|
# self.arb_syncRange()
|
||||||
|
|
||||||
|
def loadUI(self):
|
||||||
|
loader = QUiLoader()
|
||||||
|
currentDir = os.path.dirname(__file__)
|
||||||
|
file = QFile(currentDir+"/mocaphelperui.ui")
|
||||||
|
file.open(QFile.ReadOnly)
|
||||||
|
try:
|
||||||
|
self.ui = loader.load(file, parentWidget=self)
|
||||||
|
finally:
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
layout.addWidget(self.ui)
|
||||||
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
layout.setSpacing(0)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
#sac:
|
||||||
|
def initSac(self):
|
||||||
|
|
||||||
|
self.ui.sac_itEdit.textEdited.connect(self.on_sac_itEditEdited)
|
||||||
|
self.ui.sac_inEdit.textEdited.connect(self.on_sac_inEditEdited)
|
||||||
|
self.ui.sac_utCheckBox.stateChanged.connect(self.on_sac_utCheckBoxChanged)
|
||||||
|
self.ui.sac_tuEdit.textEdited.connect(self.on_sac_tuEditEdited)
|
||||||
|
self.ui.sac_selTypeComboBox.activated[str].connect(self.on_sac_selTypeComboBoxChanged)
|
||||||
|
self.ui.sac_smoothMethodComboBox.activated[str].connect(self.on_sac_smoothMethodComboBoxChanged)
|
||||||
|
self.ui.sac_cmdButton.clicked.connect(self.on_sac_cmdButtonClicked)
|
||||||
|
|
||||||
|
def on_sac_itEditEdited(self):
|
||||||
|
self.sac_iteration = int(eval(self.ui.sac_itEdit.text()))
|
||||||
|
|
||||||
|
def on_sac_inEditEdited(self):
|
||||||
|
self.sac_intensity = float(eval(self.ui.sac_inEdit.text()))
|
||||||
|
|
||||||
|
def on_sac_utCheckBoxChanged(self):
|
||||||
|
self.sac_useTime = self.ui.sac_utCheckBox.isChecked()
|
||||||
|
|
||||||
|
def on_sac_tuEditEdited(self):
|
||||||
|
self.sac_timeUnit = float(eval(self.ui.sac_tuEdit.text()))
|
||||||
|
|
||||||
|
def on_sac_selTypeComboBoxChanged(self, text):
|
||||||
|
self.sac_selType = text
|
||||||
|
|
||||||
|
def on_sac_smoothMethodComboBoxChanged(self, text):
|
||||||
|
self.sac_method = text
|
||||||
|
|
||||||
|
def on_sac_cmdButtonClicked(self):
|
||||||
|
seltype = 0
|
||||||
|
|
||||||
|
if self.sac_selType == 'selected keys' :
|
||||||
|
seltype = 1
|
||||||
|
|
||||||
|
cmds.moCapHelper_smoothAniCurve( method = self.sac_method , i = self.sac_iteration , intensity = self.sac_intensity , sel = seltype , u = self.sac_useTime , tu = self.sac_timeUnit )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#fa:
|
||||||
|
def initFa(self):
|
||||||
|
|
||||||
|
self.ui.fa_assignButton.clicked.connect(self.on_fa_assignButtonClicked)
|
||||||
|
self.ui.fa_cmdButton.clicked.connect(self.on_fa_cmdButtonClicked)
|
||||||
|
self.ui.fa_fastRecordButton.clicked.connect(self.on_fa_fastRecordButtonClicked)
|
||||||
|
|
||||||
|
|
||||||
|
def on_fa_assignButtonClicked(self):
|
||||||
|
curnode = mocaphelperutility.getSelectedNodes()[0]
|
||||||
|
self.ui.fa_refEdit.setText(curnode)
|
||||||
|
|
||||||
|
def on_fa_cmdButtonClicked(self):
|
||||||
|
if self.ui.fa_refEdit.text() =="":
|
||||||
|
raise Exception("no ref obj in ui!")
|
||||||
|
else:
|
||||||
|
#cmds.moCapHelper_frameAlign(ref = self.fa_refobjs)
|
||||||
|
mel.eval("moCapHelper_frameAlign -ref "+self.ui.fa_refEdit.text())
|
||||||
|
|
||||||
|
def on_fa_fastRecordButtonClicked(self):
|
||||||
|
obj = mocaphelperutility.getSelectedNodes()[0]
|
||||||
|
loc = mocaphelperarbcore.createLoc("mocaphelper_fa_temp_loc")[0]
|
||||||
|
cmds.setKeyframe(loc,at = ["tx"])
|
||||||
|
self.ui.fa_refEdit.setText(obj)
|
||||||
|
mocaphelperutility.selectNodes(loc)
|
||||||
|
self.on_fa_cmdButtonClicked()
|
||||||
|
self.ui.fa_refEdit.setText(loc)
|
||||||
|
|
||||||
|
#re:
|
||||||
|
def initre(self):
|
||||||
|
currentDir = os.path.dirname(__file__)
|
||||||
|
self.re_presetFilePath = currentDir+"\\re_exp_preset.txt"
|
||||||
|
self.re_backupPresetFilePath = currentDir+"\\re_exp_preset_backup.txt"
|
||||||
|
if os.path.exists(self.re_presetFilePath) == False:
|
||||||
|
mocaphelperrecore.presetfileRebuild(self.re_presetFilePath,self.re_backupPresetFilePath)
|
||||||
|
|
||||||
|
|
||||||
|
self.ui.re_expPresetComboBox.currentIndexChanged.connect(self.on_re_expPresetComboBoxChanged)
|
||||||
|
self.re_reloadPreset()
|
||||||
|
|
||||||
|
self.ui.re_reloadButton.clicked.connect(self.on_re_reloadButtonClicked)
|
||||||
|
self.ui.re_openFileButton.clicked.connect(self.on_re_openFileButtonClicked)
|
||||||
|
self.ui.re_assignButton.clicked.connect(self.on_re_assignButtonClicked)
|
||||||
|
self.ui.re_recordButton.clicked.connect(self.on_re_recordButtonClicked)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.ui.re_layerNameEdit.setText("layername")
|
||||||
|
self.ui.re_prefixEdit.textChanged.connect(self.on_re_layerPrefixEditEdited)
|
||||||
|
self.ui.re_prefixEdit.textEdited.connect(self.on_re_layerPrefixEditEdited)
|
||||||
|
self.ui.re_layerNameEdit.textChanged.connect(self.on_re_layerNameEditEdited)
|
||||||
|
self.ui.re_layerNameEdit.textEdited.connect(self.on_re_layerNameEditEdited)
|
||||||
|
|
||||||
|
self.ui.re_expEdit.textChanged.connect(self.on_re_expEditEdited)
|
||||||
|
self.ui.re_expEdit.textEdited.connect(self.on_re_expEditEdited)
|
||||||
|
self.ui.re_selectMainCtrlButton.clicked.connect(self.on_re_selectMainCtrlButtonClicked)
|
||||||
|
self.ui.re_selectChildButton.clicked.connect(self.on_re_selectChildButtonClicked)
|
||||||
|
self.ui.re_selectChildCtrlButton.clicked.connect(self.on_re_selectChildCtrlButtonClicked)
|
||||||
|
self.ui.re_selectVisChildCtrlButton.clicked.connect(self.on_re_selectVisChildCtrlButtonClicked)
|
||||||
|
self.ui.re_expSelectButton.clicked.connect(self.on_re_expSelectButtonClicked)
|
||||||
|
self.ui.re_expCreateLayerButton.clicked.connect(self.on_re_expcreateLayerButtonClicked)
|
||||||
|
self.ui.re_selectedCreateLayerButton.clicked.connect(self.on_re_selcreateLayerButtonClicked)
|
||||||
|
self.ui.re_caseCheckCheckBox.stateChanged.connect(self.on_re_caseCheckCheckBoxChanged)
|
||||||
|
self.ui.re_extractLayerInfoButton.clicked.connect(self.on_re_extractLayerInfoButtonClicked)
|
||||||
|
|
||||||
|
def on_re_layerPrefixEditEdited(self):
|
||||||
|
self.re_prefix = self.ui.re_prefixEdit.text()
|
||||||
|
|
||||||
|
def on_re_layerNameEditEdited(self):
|
||||||
|
self.re_name = self.ui.re_layerNameEdit.text()
|
||||||
|
|
||||||
|
def on_re_expEditEdited(self):
|
||||||
|
self.re_exp = self.ui.re_expEdit.text()
|
||||||
|
|
||||||
|
def on_re_selectChildButtonClicked(self):
|
||||||
|
selectednodes = mocaphelperutility.getSelectedNodes()
|
||||||
|
children = mocaphelperutility.getChildNodes(selectednodes,nodetype="all")
|
||||||
|
mocaphelperutility.selectNodes(children)
|
||||||
|
print("objs selected: ",children)
|
||||||
|
|
||||||
|
def on_re_selectChildCtrlButtonClicked(self):
|
||||||
|
selectednodes = mocaphelperutility.getSelectedNodes()
|
||||||
|
children = mocaphelperutility.getChildNodes(selectednodes,nodetype="nurbsCurve")
|
||||||
|
mocaphelperutility.selectNodes(children)
|
||||||
|
print("objs selected: ",children)
|
||||||
|
|
||||||
|
def on_re_selectVisChildCtrlButtonClicked(self):
|
||||||
|
selectednodes = mocaphelperutility.getSelectedNodes()
|
||||||
|
children = mocaphelperutility.getChildNodes(selectednodes,nodetype="nurbsCurve")
|
||||||
|
mocaphelperutility.selectNodes(children,visible=True)
|
||||||
|
print("objs selected: ",children)
|
||||||
|
|
||||||
|
def on_re_selectMainCtrlButtonClicked(self):
|
||||||
|
mocaphelperrecore.selMainCtrl()
|
||||||
|
|
||||||
|
def on_re_expSelectButtonClicked(self):
|
||||||
|
actOnType = getReActOnType(self)
|
||||||
|
childcheck = self.ui.re_childCheckBox.isChecked()
|
||||||
|
seltednodes = mocaphelperutility.getSelectedNodes()
|
||||||
|
if childcheck:
|
||||||
|
ctrls = mocaphelperutility.getChildNodes(seltednodes,nodetype=actOnType)
|
||||||
|
else:
|
||||||
|
ctrls = seltednodes
|
||||||
|
matchlist = mocaphelperrecore.retestlist(ctrls,self.re_exp,self.re_caseCheck)
|
||||||
|
mocaphelperutility.selectNodes(matchlist)
|
||||||
|
print("objs selected: ",matchlist)
|
||||||
|
|
||||||
|
|
||||||
|
def on_re_selcreateLayerButtonClicked(self):
|
||||||
|
sel = mocaphelperutility.getSelectedNodes()
|
||||||
|
mocaphelperrecore.createDisplayLayer(self.re_prefix+self.re_name,sel)
|
||||||
|
|
||||||
|
def on_re_expcreateLayerButtonClicked(self):
|
||||||
|
actOnType = getReActOnType(self)
|
||||||
|
childcheck = self.ui.re_childCheckBox.isChecked()
|
||||||
|
mocaphelperutility.openUndoChunk()
|
||||||
|
try:
|
||||||
|
|
||||||
|
mocaphelperrecore.expCreateDisplayLayer(self.re_exp,self.re_name,self.re_prefix,self.re_caseCheck,childcheck = childcheck ,nodetype = actOnType)
|
||||||
|
finally:
|
||||||
|
mocaphelperutility.closeUndoChunk()
|
||||||
|
def on_re_extractLayerInfoButtonClicked(self):
|
||||||
|
mocaphelperrecore.extractLayerInfo(self)
|
||||||
|
|
||||||
|
def on_re_caseCheckCheckBoxChanged(self):
|
||||||
|
self.re_caseCheck = self.ui.re_caseCheckCheckBox.isChecked()
|
||||||
|
|
||||||
|
def on_re_expPresetComboBoxChanged(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_re_assignButtonClicked(self):
|
||||||
|
index = self.ui.re_expPresetComboBox.currentIndex()
|
||||||
|
self.ui.re_layerNameEdit.setText(self.re_itemlist[index][0])
|
||||||
|
self.ui.re_expEdit.setText(self.re_itemlist[index][1])
|
||||||
|
|
||||||
|
|
||||||
|
def on_re_recordButtonClicked(self):
|
||||||
|
self.re_rawstr = mocaphelperrecore.strAppend(self.re_rawstr,self.re_name,self.re_exp)
|
||||||
|
self.re_itemlist = mocaphelperrecore.rawStrBuild(self.re_rawstr)
|
||||||
|
mocaphelperrecore.presetfileRebuild(self.re_presetFilePath,self.re_backupPresetFilePath)
|
||||||
|
mocaphelperrecore.presetFileWrite(self.re_presetFilePath,self.re_rawstr)
|
||||||
|
self.re_reloadPreset()
|
||||||
|
|
||||||
|
def on_re_openFileButtonClicked(self):
|
||||||
|
os.startfile(self.re_presetFilePath)
|
||||||
|
|
||||||
|
def on_re_reloadButtonClicked(self):
|
||||||
|
self.re_reloadPreset()
|
||||||
|
|
||||||
|
def re_expPresetComboBoxRebuild(self):
|
||||||
|
self.ui.re_expPresetComboBox.clear()
|
||||||
|
for item in self.re_itemlist:
|
||||||
|
convertedstr = "\""+item[0]+"\"\""+item[1]+"\""
|
||||||
|
self.ui.re_expPresetComboBox.addItem( convertedstr )
|
||||||
|
self.ui.re_expPresetComboBox.setCurrentIndex(0)
|
||||||
|
|
||||||
|
def re_reloadPreset(self):
|
||||||
|
if os.path.exists(self.re_presetFilePath) == False:
|
||||||
|
mocaphelperrecore.presetfileRebuild(self.re_presetFilePath,self.re_backupPresetFilePath)
|
||||||
|
self.re_rawstr = mocaphelperrecore.presetFileRead(self.re_presetFilePath)
|
||||||
|
self.re_itemlist = mocaphelperrecore.rawStrBuild(self.re_rawstr)
|
||||||
|
self.re_expPresetComboBoxRebuild()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# arb:
|
||||||
|
def intiArb(self):
|
||||||
|
# timerange
|
||||||
|
self.ui.arb_setFromButton.clicked.connect(self.arb_setFrom)
|
||||||
|
self.ui.arb_setToButton.clicked.connect(self.arb_setTo)
|
||||||
|
self.ui.arb_syncRangeButton.clicked.connect(self.arb_syncRange)
|
||||||
|
self.ui.arb_delInRangeButton.clicked.connect(self.on_arb_delInRangeButtonClicked)
|
||||||
|
self.ui.arb_delOutRangeButton.clicked.connect(self.on_arb_delOutRangeButtonClicked)
|
||||||
|
self.ui.arb_offsetFrameButton.clicked.connect(self.on_arb_offsetFrameButtonClicked)
|
||||||
|
self.ui.arb_stickyDelButton.clicked.connect(self.on_arb_stickyDelButtonClicked)
|
||||||
|
|
||||||
|
self.ui.arb_fromEdit.textChanged.connect(self.on_arb_fromEditEdited)
|
||||||
|
self.ui.arb_fromEdit.textEdited.connect(self.on_arb_fromEditEdited)
|
||||||
|
|
||||||
|
self.ui.arb_toEdit.textChanged.connect(self.on_arb_toEditEdited)
|
||||||
|
self.ui.arb_toEdit.textEdited.connect(self.on_arb_toEditEdited)
|
||||||
|
# basic
|
||||||
|
self.ui.arb_createLocButton.clicked.connect(self.on_arb_createLocButtonClicked)
|
||||||
|
self.ui.arb_rePosButton.clicked.connect(self.on_arb_rePosButtonClicked)
|
||||||
|
self.ui.arb_pointConstraintButton.clicked.connect(self.on_arb_pointConstraintButtonClicked)
|
||||||
|
self.ui.arb_orientConstraintButton.clicked.connect(self.on_arb_orientConstraintButtonClicked)
|
||||||
|
self.ui.arb_parentConstraintButton.clicked.connect(self.on_arb_parentConstraintButtonClicked)
|
||||||
|
self.ui.arb_delConstraintButton.clicked.connect(self.on_arb_delConstraintButtonClicked)
|
||||||
|
self.ui.arb_bakeButton.clicked.connect(self.on_arb_bakeButtonClicked)
|
||||||
|
# simplebake
|
||||||
|
self.ui.arb_simpleBakeAAssignButton.clicked.connect(self.on_arb_simpleBakeAAssignButtonClicked)
|
||||||
|
self.ui.arb_simpleBakeBAssignButton.clicked.connect(self.on_arb_simpleBakeBAssignButtonClicked)
|
||||||
|
|
||||||
|
self.ui.arb_simpleBakeToLocButton.clicked.connect(self.on_arb_simpleBakeToLocButtonClicked)
|
||||||
|
self.ui.arb_simpleBakeAToBButton.clicked.connect(self.on_arb_simpleBakeAToBButtonClicked)
|
||||||
|
self.ui.arb_simpleBakeBToAButton.clicked.connect(self.on_arb_simpleBakeBToAButtonClicked)
|
||||||
|
# fk2ik
|
||||||
|
|
||||||
|
self.ui.arb_fk2ikEndCtrlAssignButton.clicked.connect(self.on_arb_fk2ikEndCtrlAssignButtonClicked)
|
||||||
|
self.ui.arb_fk2ikCtrlRefAssignButton.clicked.connect(self.on_arb_fk2ikCtrlRefAssignButtonClicked)
|
||||||
|
self.ui.arb_fk2ikTwistAssignButton.clicked.connect(self.on_arb_fk2ikTwistAssignButtonClicked)
|
||||||
|
self.ui.arb_fk2ikTwistRefAssignButton.clicked.connect(self.on_arb_fk2ikTwistRefAssignButtonClicked)
|
||||||
|
self.ui.arb_fk2ikConvertButton.clicked.connect(self.on_arb_fk2ikConvertButtonClicked)
|
||||||
|
|
||||||
|
# pinpos
|
||||||
|
self.ui.arb_pinPosPinCurButton.clicked.connect(self.on_arb_pinPosPinCurButtonClicked)
|
||||||
|
self.ui.arb_pinPosPinParentButton.clicked.connect(self.on_arb_pinPosPinParentButtonClicked)
|
||||||
|
|
||||||
|
self.arb_syncRange()
|
||||||
|
|
||||||
|
def on_arb_fromEditEdited(self):
|
||||||
|
print("setfrom:",eval(self.ui.arb_fromEdit.text()))
|
||||||
|
self.arb_fromtime = float(eval(self.ui.arb_fromEdit.text()))
|
||||||
|
|
||||||
|
|
||||||
|
def on_arb_toEditEdited(self):
|
||||||
|
print("setto:",eval(self.ui.arb_toEdit.text()))
|
||||||
|
self.arb_totime = float(eval(self.ui.arb_toEdit.text()))
|
||||||
|
# print("setto:",self.ui.arb_toEdit.text(),self.arb_totime)
|
||||||
|
|
||||||
|
def arb_syncRange(self):
|
||||||
|
timerange = mocaphelperutility.getTimeRange()
|
||||||
|
print("syncrangeresult:",timerange)
|
||||||
|
self.ui.arb_fromEdit.setText(str(timerange[0]))
|
||||||
|
self.ui.arb_toEdit.setText(str(timerange[1]))
|
||||||
|
|
||||||
|
|
||||||
|
def arb_setFrom(self):
|
||||||
|
time = mocaphelperutility.getCurrentFrame()
|
||||||
|
self.ui.arb_fromEdit.setText(str(time))
|
||||||
|
|
||||||
|
def arb_setTo(self):
|
||||||
|
time = mocaphelperutility.getCurrentFrame()
|
||||||
|
self.ui.arb_toEdit.setText(str(time))
|
||||||
|
|
||||||
|
def on_arb_delInRangeButtonClicked(self):
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
print("delete inrange",self.arb_fromtime,self.arb_totime)
|
||||||
|
mocaphelperarbcore.deleteInrange(objs,self.arb_fromtime,self.arb_totime)
|
||||||
|
|
||||||
|
def on_arb_delOutRangeButtonClicked(self):
|
||||||
|
if self.arb_fromtime>self.arb_totime:
|
||||||
|
raise Exception("fromtime > totime")
|
||||||
|
else:
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
print("delete outrange",self.arb_fromtime,self.arb_totime)
|
||||||
|
mocaphelperarbcore.deleteOutrange(objs,self.arb_fromtime,self.arb_totime)
|
||||||
|
|
||||||
|
def on_arb_offsetFrameButtonClicked(self):
|
||||||
|
if self.arb_fromtime==self.arb_totime:
|
||||||
|
raise Exception("fromtime == totime")
|
||||||
|
else:
|
||||||
|
offsettime = self.arb_totime-self.arb_fromtime
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
mocaphelperarbcore.offsetFrame(objs,offsettime)
|
||||||
|
|
||||||
|
def on_arb_stickyDelButtonClicked(self):
|
||||||
|
mocaphelperarbcore.stickyDelete(self)
|
||||||
|
|
||||||
|
def on_arb_createLocButtonClicked(self):
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
if len(objs) == 0:
|
||||||
|
cmds.warning("No nodes selected")
|
||||||
|
return
|
||||||
|
pos = mocaphelperutility.getWorldPos(objs[0])
|
||||||
|
rot = mocaphelperutility.getWorldRot(objs[0])
|
||||||
|
roo = mocaphelperutility.getRotOrder(objs[0])
|
||||||
|
mocaphelperarbcore.createLoc("c_loc_"+objs[0],pos,rot,roo)
|
||||||
|
|
||||||
|
def on_arb_rePosButtonClicked(self):
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
if len(objs) == 0:
|
||||||
|
cmds.warning("No nodes selected")
|
||||||
|
return
|
||||||
|
mocaphelperarbcore.reposition(objs[0],objs[1])
|
||||||
|
|
||||||
|
def on_arb_pointConstraintButtonClicked(self):
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
ctrlobj = objs[:-1]
|
||||||
|
targetobj = objs[-1]
|
||||||
|
mocaphelperarbcore.createPointConstraint(ctrlobj,targetobj,maintainoffset=self.ui.arb_maintainOffsetCheckBox.isChecked())
|
||||||
|
|
||||||
|
def on_arb_orientConstraintButtonClicked(self):
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
ctrlobj = objs[:-1]
|
||||||
|
targetobj = objs[-1]
|
||||||
|
mocaphelperarbcore.createOrientConstraint(ctrlobj,targetobj,maintainoffset=self.ui.arb_maintainOffsetCheckBox.isChecked())
|
||||||
|
|
||||||
|
def on_arb_parentConstraintButtonClicked(self):
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
ctrlobj = objs[:-1]
|
||||||
|
targetobj = objs[-1]
|
||||||
|
mocaphelperarbcore.createParentConstraint(ctrlobj,targetobj,maintainoffset=self.ui.arb_maintainOffsetCheckBox.isChecked())
|
||||||
|
|
||||||
|
def on_arb_delConstraintButtonClicked(self):
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
mocaphelperarbcore.deleteAllConstraint(objs)
|
||||||
|
# for obj in objs:
|
||||||
|
# check = mocaphelperarbcore.checkConstraint(obj)
|
||||||
|
# if check != False:
|
||||||
|
# if check[0] != None:
|
||||||
|
# mocaphelperarbcore.deleteParentConstraint(check[0],obj)
|
||||||
|
# elif check[1] != None :
|
||||||
|
# mocaphelperarbcore.deletePointConstraint(check[1],obj)
|
||||||
|
# elif check[2] != None :
|
||||||
|
# mocaphelperarbcore.deleteOrientConstraint(check[2],obj)
|
||||||
|
# else:
|
||||||
|
# raise Exception("delconstraint error: constraint list out of range!")
|
||||||
|
# else:
|
||||||
|
# point = cmds.listRelatives(obj,children = True,type = "pointConstraint")
|
||||||
|
# orient = cmds.listRelatives(obj,children = True,type = "orientConstraint")
|
||||||
|
|
||||||
|
|
||||||
|
def on_arb_bakeButtonClicked(self):
|
||||||
|
mintime = self.arb_fromtime
|
||||||
|
maxtime = self.arb_totime
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
singleobj = objs[0]
|
||||||
|
check = mocaphelperarbcore.checkConstraint(singleobj)
|
||||||
|
smartbake = self.ui.arb_smartBakeCheckBox.isChecked()
|
||||||
|
if len(objs) == 1 and self.ui.arb_onlyBakeConstraintCheckBox.isChecked() and check != False:
|
||||||
|
type = "all"
|
||||||
|
if check[0] != None:
|
||||||
|
type = "parent"
|
||||||
|
elif check[1] != None :
|
||||||
|
type = "point"
|
||||||
|
elif check[2] != None :
|
||||||
|
type = "orient"
|
||||||
|
else:
|
||||||
|
type = "parent"
|
||||||
|
|
||||||
|
if smartbake:
|
||||||
|
mocaphelperarbcore.smartbake(objs,mintime,maxtime,type)
|
||||||
|
else:
|
||||||
|
mocaphelperarbcore.bake(objs,mintime,maxtime,type)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def on_arb_simpleBakeAAssignButtonClicked(self):
|
||||||
|
obj = mocaphelperutility.getSelectedNodes()[0]
|
||||||
|
self.ui.arb_simpleBakeAEdit.setText(obj)
|
||||||
|
|
||||||
|
def on_arb_simpleBakeBAssignButtonClicked(self):
|
||||||
|
obj = mocaphelperutility.getSelectedNodes()[0]
|
||||||
|
self.ui.arb_simpleBakeBEdit.setText(obj)
|
||||||
|
|
||||||
|
def on_arb_simpleBakeToLocButtonClicked(self):
|
||||||
|
mintime = self.arb_fromtime
|
||||||
|
maxtime = self.arb_totime
|
||||||
|
targetA = self.ui.arb_simpleBakeAEdit.text()
|
||||||
|
mocaphelperutility.openUndoChunk()
|
||||||
|
try:
|
||||||
|
|
||||||
|
# obj = mocaphelperutility.getSelectedNodes()[0]
|
||||||
|
locA = mocaphelperarbcore.createLoc(targetA +"_loc")
|
||||||
|
mocaphelperarbcore.createParentConstraint(targetA,locA,False)
|
||||||
|
mocaphelperarbcore.bake(locA,mintime,maxtime,"all")
|
||||||
|
mocaphelperarbcore.deleteAllConstraint(locA)
|
||||||
|
self.ui.arb_simpleBakeBEdit.setText(locA[0])
|
||||||
|
|
||||||
|
finally:
|
||||||
|
mocaphelperutility.closeUndoChunk()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def on_arb_simpleBakeAToBButtonClicked(self):
|
||||||
|
targetA = self.ui.arb_simpleBakeAEdit.text()
|
||||||
|
targetB = self.ui.arb_simpleBakeBEdit.text()
|
||||||
|
maintainoffset=self.ui.arb_maintainOffsetCheckBox.isChecked()
|
||||||
|
mocaphelperutility.openUndoChunk()
|
||||||
|
try:
|
||||||
|
check = mocaphelperarbcore.checkConstraint(targetB)
|
||||||
|
if check != False:
|
||||||
|
raise Exception("obj B has constraint already!")
|
||||||
|
else:
|
||||||
|
mintime = self.arb_fromtime
|
||||||
|
maxtime = self.arb_totime
|
||||||
|
type = getArbType(self)
|
||||||
|
mocaphelperarbcore.bakeAtoB(targetA,targetB,mintime,maxtime,type,maintainoffset,smart = self.ui.arb_smartBakeCheckBox.isChecked())
|
||||||
|
|
||||||
|
finally:
|
||||||
|
mocaphelperutility.closeUndoChunk()
|
||||||
|
|
||||||
|
def on_arb_simpleBakeBToAButtonClicked(self):
|
||||||
|
targetA = self.ui.arb_simpleBakeAEdit.text()
|
||||||
|
targetB = self.ui.arb_simpleBakeBEdit.text()
|
||||||
|
maintainoffset=self.ui.arb_maintainOffsetCheckBox.isChecked()
|
||||||
|
mocaphelperutility.openUndoChunk()
|
||||||
|
try:
|
||||||
|
check = mocaphelperarbcore.checkConstraint(targetA)
|
||||||
|
if check != False:
|
||||||
|
raise Exception("obj A has constraint already!")
|
||||||
|
else:
|
||||||
|
mintime = self.arb_fromtime
|
||||||
|
maxtime = self.arb_totime
|
||||||
|
type = getArbType(self)
|
||||||
|
mocaphelperarbcore.bakeAtoB(targetB,targetA,mintime,maxtime,type,maintainoffset,smart = self.ui.arb_smartBakeCheckBox.isChecked())
|
||||||
|
finally:
|
||||||
|
mocaphelperutility.closeUndoChunk()
|
||||||
|
|
||||||
|
|
||||||
|
def on_arb_fk2ikEndCtrlAssignButtonClicked(self):
|
||||||
|
obj = mocaphelperutility.getSelectedNodes()[0]
|
||||||
|
self.ui.arb_fk2ikEndCtrlEdit.setText(obj)
|
||||||
|
|
||||||
|
def on_arb_fk2ikCtrlRefAssignButtonClicked(self):
|
||||||
|
obj = mocaphelperutility.getSelectedNodes()[0]
|
||||||
|
self.ui.arb_fk2ikCtrlRefEdit.setText(obj)
|
||||||
|
|
||||||
|
def on_arb_fk2ikTwistAssignButtonClicked(self):
|
||||||
|
obj = mocaphelperutility.getSelectedNodes()[0]
|
||||||
|
self.ui.arb_fk2ikTwistEdit.setText(obj)
|
||||||
|
|
||||||
|
def on_arb_fk2ikTwistRefAssignButtonClicked(self):
|
||||||
|
obj = mocaphelperutility.getSelectedNodes()[0]
|
||||||
|
self.ui.arb_fk2ikTwistRefEdit.setText(obj)
|
||||||
|
|
||||||
|
def on_arb_fk2ikConvertButtonClicked(self):
|
||||||
|
mintime = self.arb_fromtime
|
||||||
|
maxtime = self.arb_totime
|
||||||
|
maintainoffset=self.ui.arb_maintainOffsetCheckBox.isChecked()
|
||||||
|
smartbake = self.ui.arb_smartBakeCheckBox.isChecked()
|
||||||
|
endctrl = self.ui.arb_fk2ikEndCtrlEdit.text()
|
||||||
|
ctrlref = self.ui.arb_fk2ikCtrlRefEdit.text()
|
||||||
|
twist = self.ui.arb_fk2ikTwistEdit.text()
|
||||||
|
twistref = self.ui.arb_fk2ikTwistRefEdit.text()
|
||||||
|
mocaphelperutility.openUndoChunk()
|
||||||
|
try:
|
||||||
|
if mocaphelperutility.objExist(endctrl) == False:
|
||||||
|
endctrl = ""
|
||||||
|
if mocaphelperutility.objExist(ctrlref) == False:
|
||||||
|
ctrlref = ""
|
||||||
|
if mocaphelperutility.objExist(twist) == False:
|
||||||
|
twist = ""
|
||||||
|
if mocaphelperutility.objExist(twistref) == False:
|
||||||
|
twistref = ""
|
||||||
|
|
||||||
|
check = mocaphelperarbcore.checkConstraint(endctrl)
|
||||||
|
if check != False:
|
||||||
|
raise Exception("endctrl has constraint already!")
|
||||||
|
if mocaphelperutility.objExist(twist) == True:
|
||||||
|
check = mocaphelperarbcore.checkConstraint(twist)
|
||||||
|
if check != False:
|
||||||
|
raise Exception("twist has constraint already!")
|
||||||
|
|
||||||
|
if endctrl== "" or ctrlref =="":
|
||||||
|
raise Exception("endctrl or ctrlref not set or not exist")
|
||||||
|
else:
|
||||||
|
if twist == "" or twistref == "":
|
||||||
|
|
||||||
|
mocaphelperarbcore.bakeAtoB(ctrlref,endctrl,mintime,maxtime,"parent",maintainoffset,smartbake)
|
||||||
|
else:
|
||||||
|
mocaphelperarbcore.bakeAtoB(ctrlref,endctrl,mintime,maxtime,"parent",maintainoffset,smartbake)
|
||||||
|
|
||||||
|
twistpos = mocaphelperutility.getWorldPos(twist)
|
||||||
|
twistrot = mocaphelperutility.getWorldRot(twist)
|
||||||
|
twistroo = mocaphelperutility.getRotOrder(twist)
|
||||||
|
twistloc = mocaphelperarbcore.createLoc("temp_twist_loc",twistpos,twistrot,twistroo)
|
||||||
|
cons1 = mocaphelperarbcore.createParentConstraint(twistref,twistloc,True)
|
||||||
|
cons2 = mocaphelperarbcore.createPointConstraint(twistloc,twist,False)
|
||||||
|
if smartbake:
|
||||||
|
mocaphelperarbcore.smartbake(twist,mintime,maxtime,"point")
|
||||||
|
else:
|
||||||
|
mocaphelperarbcore.bake(twist,mintime,maxtime,"point")
|
||||||
|
|
||||||
|
mocaphelperutility.deleteObj(cons1)
|
||||||
|
mocaphelperutility.deleteObj(cons2)
|
||||||
|
mocaphelperutility.deleteObj(twistloc)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
mocaphelperutility.closeUndoChunk()
|
||||||
|
|
||||||
|
def on_arb_pinPosPinCurButtonClicked(self):
|
||||||
|
mintime = self.arb_fromtime
|
||||||
|
maxtime = self.arb_totime
|
||||||
|
mocaphelperutility.openUndoChunk()
|
||||||
|
try:
|
||||||
|
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
mocaphelperarbcore.pinCurPos(objs,mintime,maxtime)
|
||||||
|
finally:
|
||||||
|
mocaphelperutility.closeUndoChunk()
|
||||||
|
|
||||||
|
def on_arb_pinPosPinParentButtonClicked(self):
|
||||||
|
mintime = self.arb_fromtime
|
||||||
|
maxtime = self.arb_totime
|
||||||
|
mocaphelperutility.openUndoChunk()
|
||||||
|
try:
|
||||||
|
objs = mocaphelperutility.getSelectedNodes()
|
||||||
|
mocaphelperarbcore.pinParentPos(objs,mintime,maxtime)
|
||||||
|
finally:
|
||||||
|
mocaphelperutility.closeUndoChunk()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getArbType(obj):
|
||||||
|
index = obj.ui.arb_simpleBakeTypeComboBox.currentIndex()
|
||||||
|
# type = mocaphelperutility.unicodeToStr(type)
|
||||||
|
# enList = ["all","parent","point","orient","onlyscale"]
|
||||||
|
# cnList = ["平移旋转","平移","旋转","所有属性"]
|
||||||
|
type = None
|
||||||
|
if index == 0:
|
||||||
|
type = "all"
|
||||||
|
|
||||||
|
elif index == 1:
|
||||||
|
type = "parent"
|
||||||
|
|
||||||
|
elif index == 2:
|
||||||
|
type = "point"
|
||||||
|
|
||||||
|
elif index == 3:
|
||||||
|
type = "orient"
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise Exception("id out of range")
|
||||||
|
print("index is now:",index,".type is now:",type)
|
||||||
|
|
||||||
|
return type
|
||||||
|
|
||||||
|
|
||||||
|
def getReActOnType(obj):
|
||||||
|
index = obj.ui.re_actTypeComboBox.currentIndex()
|
||||||
|
|
||||||
|
type = None
|
||||||
|
if index == 0:
|
||||||
|
type = "all"
|
||||||
|
|
||||||
|
elif index == 1:
|
||||||
|
type = "nurbsCurve"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print("index is now:",index,".type is now:",type)
|
||||||
|
return type
|
1512
Scripts/Animation/MotionCapHelper/bin/mocaphelperui.ui
Normal file
1512
Scripts/Animation/MotionCapHelper/bin/mocaphelperui.ui
Normal file
File diff suppressed because it is too large
Load Diff
139
Scripts/Animation/MotionCapHelper/bin/mocaphelperutility.py
Normal file
139
Scripts/Animation/MotionCapHelper/bin/mocaphelperutility.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
import maya.api.OpenMaya as om
|
||||||
|
import maya.cmds as cmds
|
||||||
|
import maya.mel as mel
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from sys import version as sysver
|
||||||
|
|
||||||
|
def getPythonVersion():
|
||||||
|
return int(sysver[0])
|
||||||
|
|
||||||
|
|
||||||
|
def selectNodes(nodelist,visible = False):
|
||||||
|
cmds.select(cl=True)
|
||||||
|
if visible == True:
|
||||||
|
cmds.select(nodelist,vis = True)
|
||||||
|
else:
|
||||||
|
cmds.select(nodelist)
|
||||||
|
|
||||||
|
def addSelectNodes(nodelist):
|
||||||
|
for node in nodelist:
|
||||||
|
cmds.select(node,add = True)
|
||||||
|
|
||||||
|
def orderSelectNodes(nodelist):
|
||||||
|
cmds.select(cl=True)
|
||||||
|
for node in nodelist:
|
||||||
|
cmds.select(node,add = True)
|
||||||
|
|
||||||
|
def getSelectedNodes(nodetype = "all",longname = True):
|
||||||
|
selectednodes = cmds.ls(selection = True,type = "dagNode",long = longname)
|
||||||
|
if nodetype != "all":
|
||||||
|
selectednodes = filterCertainTypeInList(selectednodes,nodetype)
|
||||||
|
return selectednodes
|
||||||
|
|
||||||
|
def getChildNodes(parents,nodetype = "all",combine = True):
|
||||||
|
list = []
|
||||||
|
|
||||||
|
for parent in parents:
|
||||||
|
childlist = cmds.listRelatives(parent, ad=True, type = "transform",fullPath = True)
|
||||||
|
|
||||||
|
if childlist == None:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if nodetype == "all":
|
||||||
|
list += childlist
|
||||||
|
|
||||||
|
else:
|
||||||
|
list += filterCertainTypeInList(childlist,nodetype)
|
||||||
|
|
||||||
|
if list != None:
|
||||||
|
if combine == True:
|
||||||
|
return list+parents
|
||||||
|
else:
|
||||||
|
return list
|
||||||
|
else:
|
||||||
|
raise Exception("error when getting child")
|
||||||
|
|
||||||
|
def filterCertainTypeInList(list,type = "nurbsCurve"):
|
||||||
|
matchlist = []
|
||||||
|
for node in list:
|
||||||
|
if getShapeType(node) == type:
|
||||||
|
matchlist.append(node)
|
||||||
|
|
||||||
|
return matchlist
|
||||||
|
|
||||||
|
def getShapeType( node = "" ):
|
||||||
|
shape = cmds.listRelatives(node,shapes = True,fullPath = True)
|
||||||
|
if shape != None:
|
||||||
|
shape = shape[0]
|
||||||
|
return cmds.nodeType(shape)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def objExist(obj):
|
||||||
|
if len(cmds.ls(obj)) == 0:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def getCurrentFrame():
|
||||||
|
return cmds.currentTime(q = True)
|
||||||
|
|
||||||
|
def getTimeRange(local = False):
|
||||||
|
#local means time slider range in maya time line
|
||||||
|
if local == True:
|
||||||
|
return cmds.playbackOptions(q = True,min = True),cmds.playbackOptions(q = True,max = True)
|
||||||
|
else:
|
||||||
|
return cmds.playbackOptions(q = True,ast = True),cmds.playbackOptions(q = True,aet = True)
|
||||||
|
|
||||||
|
|
||||||
|
def getWorldPos(obj):
|
||||||
|
return cmds.xform(obj,q = True,ws = True,t = True)
|
||||||
|
|
||||||
|
def getWorldRot(obj):
|
||||||
|
return cmds.xform(obj,q = True,ws = True,ro = True)
|
||||||
|
|
||||||
|
def getRotOrder(obj):
|
||||||
|
return cmds.xform(obj,q = True,roo = True)
|
||||||
|
|
||||||
|
def setWorldPos(obj,cd = (0.0,0.0,0.0)):
|
||||||
|
cmds.xform(obj,ws = True,t = cd)
|
||||||
|
|
||||||
|
def setWorldRot(obj,rot = (0.0,0.0,0.0),targetRotOrder = "xyz"):
|
||||||
|
originOrder = cmds.xform(obj,q = True,roo = True)
|
||||||
|
if originOrder == targetRotOrder:
|
||||||
|
cmds.xform(obj,ws = True,ro = rot)
|
||||||
|
else:
|
||||||
|
if targetRotOrder in ['xyz', 'yzx','zxy','xzy','yxz','zyx']:
|
||||||
|
cmds.xform(obj,ws = True,ro = rot,roo = targetRotOrder)
|
||||||
|
cmds.xform(obj,ws = True,roo = originOrder)
|
||||||
|
else:
|
||||||
|
raise Exception("rot order does not exist.")
|
||||||
|
|
||||||
|
def cutKey(objlist,mintime,maxtime,insertside = False):
|
||||||
|
if insertside:
|
||||||
|
cmds.cutKey(objlist,t =(mintime,maxtime),cl = True,option = "curve")
|
||||||
|
else:
|
||||||
|
cmds.cutKey(objlist,t =(mintime,maxtime),cl = True)
|
||||||
|
|
||||||
|
def autoKetTangent(objs,mintime,maxtime):
|
||||||
|
cmds.keyTangent(objs,e = True,itt="auto", ott="auto", t=(mintime,maxtime))
|
||||||
|
|
||||||
|
|
||||||
|
def deleteObj(obj):
|
||||||
|
cmds.delete(obj)
|
||||||
|
|
||||||
|
def unicodeToStr(str):
|
||||||
|
return repr(str)[2:-1]
|
||||||
|
|
||||||
|
def getDir():
|
||||||
|
dir = os.path.dirname(__file__)
|
||||||
|
return dir
|
||||||
|
|
||||||
|
def openUndoChunk():
|
||||||
|
return cmds.undoInfo(openChunk=True)
|
||||||
|
|
||||||
|
def closeUndoChunk():
|
||||||
|
return cmds.undoInfo(closeChunk=True)
|
13
Scripts/Animation/MotionCapHelper/bin/re_exp_preset.txt
Normal file
13
Scripts/Animation/MotionCapHelper/bin/re_exp_preset.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
torso
|
||||||
|
.ctrl.torso.
|
||||||
|
torso
|
||||||
|
.torso.ctrl.
|
||||||
|
l_arm
|
||||||
|
.ctrl.l.arm.
|
||||||
|
l_hand;l_arm
|
||||||
|
.:FKIndexFinger2_L|.:FKIndexFinger1_L|.:FKIndexFinger3_L|.:FKMiddleFinger1_L|.:FKMiddleFinger2_L|.:FKMiddleFinger3_L|.:FKRingFinger1_L|.:FKPinkyFinger1_L|.:FKPinkyFinger2_L|.:FKPinkyFinger3_L|.:FKThumbFinger2_L|.:FKThumbFinger3_L|.:FKThumbFinger1_L;.:FKElbow_L|.:FKWrist_L|.:FKShoulder_L
|
||||||
|
|
||||||
|
|
||||||
|
.
|
||||||
|
|
||||||
|
.
|
@ -0,0 +1,8 @@
|
|||||||
|
torso
|
||||||
|
.ctrl.torso.
|
||||||
|
torso
|
||||||
|
.torso.ctrl.
|
||||||
|
l_arm
|
||||||
|
.ctrl.l.arm.
|
||||||
|
r_arm
|
||||||
|
.l.arm.ctrl.
|
500
Scripts/Animation/MotionCapHelper/bin/ui.ts
Normal file
500
Scripts/Animation/MotionCapHelper/bin/ui.ts
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE TS>
|
||||||
|
<TS version="2.1" language="zh_CN" sourcelanguage="en">
|
||||||
|
<context>
|
||||||
|
<name>moCapHelper</name>
|
||||||
|
<message>
|
||||||
|
<source>Form</source>
|
||||||
|
<translation type="vanished">形状</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="81"/>
|
||||||
|
<source>SAC/FA/RE</source>
|
||||||
|
<oldsource>SAC/FA/DLC</oldsource>
|
||||||
|
<translation>平滑曲线/对齐帧/正则</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="130"/>
|
||||||
|
<source>smoothAnim</source>
|
||||||
|
<translation>平滑曲线</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="151"/>
|
||||||
|
<source>iteration:</source>
|
||||||
|
<translation>迭代次数:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="158"/>
|
||||||
|
<source>1</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="165"/>
|
||||||
|
<source>intensity:</source>
|
||||||
|
<translation>单次强度:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="172"/>
|
||||||
|
<source>1.0</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="179"/>
|
||||||
|
<source>use time unit</source>
|
||||||
|
<translation>使用时间单位</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="189"/>
|
||||||
|
<source>timeunit:</source>
|
||||||
|
<translation>时间单位:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="196"/>
|
||||||
|
<source>5.0</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="203"/>
|
||||||
|
<source>perform on:</source>
|
||||||
|
<translation>作用于:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="211"/>
|
||||||
|
<source>curves</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="216"/>
|
||||||
|
<source>selected keys</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="224"/>
|
||||||
|
<source>smooth method:</source>
|
||||||
|
<translation>平滑方法:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="235"/>
|
||||||
|
<source>3linear</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="240"/>
|
||||||
|
<source>3bell</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="245"/>
|
||||||
|
<source>3ham</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="250"/>
|
||||||
|
<source>5quad</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="255"/>
|
||||||
|
<source>5bell</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="260"/>
|
||||||
|
<source>5ham</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="271"/>
|
||||||
|
<source>smooth</source>
|
||||||
|
<translation>平滑</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="288"/>
|
||||||
|
<source>frameAlign</source>
|
||||||
|
<translation>对齐帧</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="314"/>
|
||||||
|
<source>fast record selected</source>
|
||||||
|
<translation>快速记录选择物体的帧信息</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="328"/>
|
||||||
|
<source>ref obj:</source>
|
||||||
|
<translation>参考物体:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="345"/>
|
||||||
|
<source>assign obj</source>
|
||||||
|
<translation>指定</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="359"/>
|
||||||
|
<source>align selection</source>
|
||||||
|
<translation>对齐选择</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>layerCreate</source>
|
||||||
|
<translation type="vanished">创建显示层</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="425"/>
|
||||||
|
<source>preset:</source>
|
||||||
|
<translation>预设:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="435"/>
|
||||||
|
<source>open file</source>
|
||||||
|
<translation>打开文件</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="445"/>
|
||||||
|
<source>record</source>
|
||||||
|
<translation>记录当前</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="455"/>
|
||||||
|
<source>reload</source>
|
||||||
|
<translation>重载文件</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="490"/>
|
||||||
|
<location filename="mocaphelperui.ui" line="1081"/>
|
||||||
|
<location filename="mocaphelperui.ui" line="1112"/>
|
||||||
|
<location filename="mocaphelperui.ui" line="1223"/>
|
||||||
|
<location filename="mocaphelperui.ui" line="1254"/>
|
||||||
|
<location filename="mocaphelperui.ui" line="1309"/>
|
||||||
|
<location filename="mocaphelperui.ui" line="1334"/>
|
||||||
|
<source>assign</source>
|
||||||
|
<translation>指定</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="504"/>
|
||||||
|
<source>case check</source>
|
||||||
|
<translation>大小写检测</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="546"/>
|
||||||
|
<source>prefix:</source>
|
||||||
|
<translation>前缀:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>layer name:</source>
|
||||||
|
<translation type="vanished">层名字:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="592"/>
|
||||||
|
<source>default</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="624"/>
|
||||||
|
<source>expression:</source>
|
||||||
|
<translation>正则表达式:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="631"/>
|
||||||
|
<source>.</source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="693"/>
|
||||||
|
<source>utility</source>
|
||||||
|
<translation>工具</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>select child ctrls</source>
|
||||||
|
<translation type="vanished">选择子控制器</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="831"/>
|
||||||
|
<source>selected create layer</source>
|
||||||
|
<translation>依据选集创建层</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="755"/>
|
||||||
|
<source>expression</source>
|
||||||
|
<translation>表达式工具</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="779"/>
|
||||||
|
<source>exp select</source>
|
||||||
|
<translation>表达式选择</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="821"/>
|
||||||
|
<source>exp create layer</source>
|
||||||
|
<translation>表达式创建层</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="789"/>
|
||||||
|
<source>extract layer info</source>
|
||||||
|
<translation>提取当前层信息</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="847"/>
|
||||||
|
<source>ARB</source>
|
||||||
|
<translation>动画重建</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>animRebuild</source>
|
||||||
|
<translation type="vanished">动画重建</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="944"/>
|
||||||
|
<source>basic</source>
|
||||||
|
<translation>基础工具</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="965"/>
|
||||||
|
<source>orient constraint</source>
|
||||||
|
<translation>旋转约束</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1003"/>
|
||||||
|
<source>delete constraint</source>
|
||||||
|
<translation>删除约束</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="989"/>
|
||||||
|
<source>parent constraint</source>
|
||||||
|
<translation>父子约束</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1010"/>
|
||||||
|
<source>bake key</source>
|
||||||
|
<translation>烘焙帧</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="996"/>
|
||||||
|
<source>create locator</source>
|
||||||
|
<translation>创建定位器</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="912"/>
|
||||||
|
<source>maintain offset</source>
|
||||||
|
<translation>保持偏移</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="922"/>
|
||||||
|
<source>smart bake</source>
|
||||||
|
<translation>智能烘焙(慎用)</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1017"/>
|
||||||
|
<source>point constraint</source>
|
||||||
|
<translation>点约束</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="972"/>
|
||||||
|
<source>reposition</source>
|
||||||
|
<translation>重新定位</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1024"/>
|
||||||
|
<source>only bake constraint</source>
|
||||||
|
<translation>尝试仅烘焙约束的通道</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1038"/>
|
||||||
|
<source>simpleBake</source>
|
||||||
|
<translation>简易烘焙</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1067"/>
|
||||||
|
<source>target A:</source>
|
||||||
|
<translation>目标A:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1098"/>
|
||||||
|
<source>target B:</source>
|
||||||
|
<translation>目标B:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="671"/>
|
||||||
|
<location filename="mocaphelperui.ui" line="1133"/>
|
||||||
|
<source>all</source>
|
||||||
|
<translation>所有属性</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1123"/>
|
||||||
|
<location filename="mocaphelperui.ui" line="1138"/>
|
||||||
|
<source>parent</source>
|
||||||
|
<translation>平移旋转</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="22"/>
|
||||||
|
<source>uiwindow</source>
|
||||||
|
<translation>窗口</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="378"/>
|
||||||
|
<source>regularExp</source>
|
||||||
|
<translation>正则表达式</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="511"/>
|
||||||
|
<source>children check</source>
|
||||||
|
<translation>检查子级</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="585"/>
|
||||||
|
<source>name:</source>
|
||||||
|
<translation>名称:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="648"/>
|
||||||
|
<source>act on :</source>
|
||||||
|
<translation>作用于:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="676"/>
|
||||||
|
<source>ctrl(nurbs)</source>
|
||||||
|
<translation>控制器(nurbs曲线)</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="717"/>
|
||||||
|
<source>select child</source>
|
||||||
|
<translation>选择子级</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="727"/>
|
||||||
|
<source>select main ctrls</source>
|
||||||
|
<translation>选择大圈</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="737"/>
|
||||||
|
<source>select child ctrl</source>
|
||||||
|
<translation>选择子控制器</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="747"/>
|
||||||
|
<source>select visible child ctrl</source>
|
||||||
|
<translation>选择可见子控制器</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="797"/>
|
||||||
|
<source>layercreate</source>
|
||||||
|
<translation>创建显示层</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1143"/>
|
||||||
|
<source>point</source>
|
||||||
|
<translation>平移</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1148"/>
|
||||||
|
<source>orient</source>
|
||||||
|
<translation>旋转</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1156"/>
|
||||||
|
<source>bake A into B</source>
|
||||||
|
<translation>烘焙A到B</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1163"/>
|
||||||
|
<source>bake B into A</source>
|
||||||
|
<translation>烘焙B到A</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1172"/>
|
||||||
|
<source>bake A into new locator</source>
|
||||||
|
<translation>将A烘焙到空定位器</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1180"/>
|
||||||
|
<source>fk2ik</source>
|
||||||
|
<translation>fk转ik</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1209"/>
|
||||||
|
<source>endctrl:</source>
|
||||||
|
<translation>末端:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1240"/>
|
||||||
|
<source>ctrlref:</source>
|
||||||
|
<translation>末端参考:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1283"/>
|
||||||
|
<source>twist:</source>
|
||||||
|
<translation>方向:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1320"/>
|
||||||
|
<source>twistref:</source>
|
||||||
|
<translation>方向参考:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1343"/>
|
||||||
|
<source>convert it !</source>
|
||||||
|
<translation>转换!</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1351"/>
|
||||||
|
<source>pinPos</source>
|
||||||
|
<translation>钉位</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1357"/>
|
||||||
|
<source>pin to current position</source>
|
||||||
|
<translation>钉在当前帧位置</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1364"/>
|
||||||
|
<source>parent to first obj position</source>
|
||||||
|
<translation>快速烘焙父子约束效果</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1403"/>
|
||||||
|
<source>set from</source>
|
||||||
|
<translation>设置:从</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1410"/>
|
||||||
|
<source>sync range</source>
|
||||||
|
<translation>同步范围</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1417"/>
|
||||||
|
<source>set to</source>
|
||||||
|
<translation>设置:到</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1431"/>
|
||||||
|
<source>from:</source>
|
||||||
|
<translation>从:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1441"/>
|
||||||
|
<source>to:</source>
|
||||||
|
<translation>到:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1458"/>
|
||||||
|
<source>delete inrange</source>
|
||||||
|
<translation>删除范围内</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1465"/>
|
||||||
|
<source>delete outrange</source>
|
||||||
|
<translation>删除范围外</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1479"/>
|
||||||
|
<source>offset frame</source>
|
||||||
|
<translation>偏移帧</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mocaphelperui.ui" line="1492"/>
|
||||||
|
<source>sticky delete</source>
|
||||||
|
<translation>提取帧</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>language</source>
|
||||||
|
<translation type="vanished">改变语言</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
</TS>
|
BIN
Scripts/Animation/MotionCapHelper/bin/ui_CN.qm
Normal file
BIN
Scripts/Animation/MotionCapHelper/bin/ui_CN.qm
Normal file
Binary file not shown.
23
Scripts/Animation/MotionCapHelper/bin/安装__install.txt
Normal file
23
Scripts/Animation/MotionCapHelper/bin/安装__install.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
安装:
|
||||||
|
将这个文件夹的目录添加到到对应版本的maya.env文件中的MAYA_PLUG_IN_PATH这一行。
|
||||||
|
例子:
|
||||||
|
MAYA_PLUG_IN_PATH =C:\Users\(你的用户名)\Documents\maya\2018\plug-ins\MotionCapHelper
|
||||||
|
|
||||||
|
启动maya,在maya里打开插件管理器,如果出现了这个插件的名字mocaphelper.py就说明安装
|
||||||
|
顺利,只要勾选这一个文件的加载就好,不需要勾选其他的比如mocaphelperrecore.py等等文件
|
||||||
|
|
||||||
|
勾选后maya会载入插件,之后使用mel或者python的moCapHelper_showUi -lan "CN"指令打开插件的中文界面
|
||||||
|
或者moCapHelper_showUi打开英文界面(更推荐一点,因为懒得更新汉化)
|
||||||
|
可以把这个指令新建一个工具架的工具,方面后面调用
|
||||||
|
|
||||||
|
Installation:
|
||||||
|
Add the directory of this folder to the <MAYA_PLUG_IN_PATH> in the corresponding version of the maya.env file.
|
||||||
|
Example:
|
||||||
|
MAYA_PLUG_IN_PATH =C:\Users\<username>\Documents\maya\2018\plug-ins\MotionCapHelper
|
||||||
|
|
||||||
|
Start Maya, open the plugin manager in Maya, you should see a list of mocaphelper.py/mocaphelperui.py.....
|
||||||
|
just check the load state of "mocaphelper.py" file only, no need to check any other files such as mocaphelperrecore.py....
|
||||||
|
|
||||||
|
After checking this box, maya will load the plug-in, and then you can use "moCapHelper_showUi" command in mel or python to open the interface of this plug-in.
|
||||||
|
|
||||||
|
You can create a new shelf tool with this command.
|
@ -0,0 +1,12 @@
|
|||||||
|
'''
|
||||||
|
this is an example of how you set hotkey or use scripts to drive this plugin's cmds.
|
||||||
|
if you know python and pyside2,go see codes and .ui file to find what you need.
|
||||||
|
the most simple usage is to drive a qt pushbutton.(which is exactly what you did when you hit a button in plugin ui.)
|
||||||
|
and you might need QLineEdit.setText() to set str in those text field.
|
||||||
|
anyway,go check qt wiki :https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QWidget.html#qwidget
|
||||||
|
have fun scripting.
|
||||||
|
'''
|
||||||
|
|
||||||
|
import maya.cmds as cmds
|
||||||
|
|
||||||
|
cmds.moCapHelper_eval(s ="ui.arb_stickyDelButton.click()" )
|
@ -0,0 +1,15 @@
|
|||||||
|
import maya.cmds as cmds
|
||||||
|
import maya.mel as mel
|
||||||
|
|
||||||
|
curlayer = cmds.editDisplayLayerGlobals( query=True, cdl=True )
|
||||||
|
if curlayer =="defaultLayer" :
|
||||||
|
raise Exception("using default layer!")
|
||||||
|
else:
|
||||||
|
slist = cmds.editDisplayLayerMembers(curlayer,query=True )
|
||||||
|
print(slist)
|
||||||
|
cmds.select( clear=True )
|
||||||
|
cmds.select(slist, visible=True )
|
||||||
|
|
||||||
|
mel.eval("syncChannelBoxFcurveEd;")
|
||||||
|
mel.eval("syncChannelBoxFcurveEd;")
|
||||||
|
mel.eval("syncChannelBoxFcurveEd;")
|
140
Scripts/Animation/epic_pose_wrangler/view/log_widget.py
Normal file
140
Scripts/Animation/epic_pose_wrangler/view/log_widget.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
# Copyright Epic Games, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from PySide2 import QtWidgets, QtCore, QtGui
|
||||||
|
|
||||||
|
|
||||||
|
class LogWidget(logging.Handler):
|
||||||
|
"""
|
||||||
|
Custom Log Handler with embedded QtWidgets.QDockWidget
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(LogWidget, self).__init__()
|
||||||
|
# Set default formatting
|
||||||
|
self.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s', '%Y-%m-%d %H:%M:%S'))
|
||||||
|
# Create dock
|
||||||
|
self._log_dock = QtWidgets.QDockWidget()
|
||||||
|
# Only allow it to be parented to the bottom
|
||||||
|
self._log_dock.setAllowedAreas(QtCore.Qt.BottomDockWidgetArea)
|
||||||
|
|
||||||
|
central_widget = QtWidgets.QWidget()
|
||||||
|
central_widget.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self._log_dock.setWidget(central_widget)
|
||||||
|
main_layout = QtWidgets.QVBoxLayout()
|
||||||
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
central_widget.setLayout(main_layout)
|
||||||
|
|
||||||
|
toolbar_layout = QtWidgets.QHBoxLayout()
|
||||||
|
toolbar_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
main_layout.addLayout(toolbar_layout)
|
||||||
|
|
||||||
|
self._output_log = QtWidgets.QListWidget()
|
||||||
|
self._output_log.setProperty("Log", True)
|
||||||
|
self._output_log.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||||
|
self._output_log.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||||
|
self._output_log.customContextMenuRequested.connect(self._show_context_menu)
|
||||||
|
main_layout.addWidget(self._output_log)
|
||||||
|
|
||||||
|
icon_size_px = 25
|
||||||
|
icon_size = QtCore.QSize(icon_size_px, icon_size_px)
|
||||||
|
btn_size_px = 30
|
||||||
|
btn_size = QtCore.QSize(btn_size_px, btn_size_px)
|
||||||
|
|
||||||
|
self._debug_btn = QtWidgets.QPushButton()
|
||||||
|
self._debug_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:debug.png")))
|
||||||
|
self._debug_btn.setIconSize(icon_size)
|
||||||
|
self._debug_btn.setProperty("LogButton", True)
|
||||||
|
self._debug_btn.setCheckable(True)
|
||||||
|
self._debug_btn.setChecked(False)
|
||||||
|
self._debug_btn.setFixedSize(btn_size)
|
||||||
|
self._debug_btn.clicked.connect(self._refresh_log)
|
||||||
|
toolbar_layout.addWidget(self._debug_btn)
|
||||||
|
|
||||||
|
self._info_btn = QtWidgets.QPushButton()
|
||||||
|
self._info_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:info.png")))
|
||||||
|
self._info_btn.setIconSize(icon_size)
|
||||||
|
self._info_btn.setProperty("LogButton", True)
|
||||||
|
self._info_btn.setCheckable(True)
|
||||||
|
self._info_btn.setChecked(True)
|
||||||
|
self._info_btn.setFixedSize(btn_size)
|
||||||
|
self._info_btn.clicked.connect(self._refresh_log)
|
||||||
|
toolbar_layout.addWidget(self._info_btn)
|
||||||
|
|
||||||
|
self._warning_btn = QtWidgets.QPushButton()
|
||||||
|
self._warning_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:warning.png")))
|
||||||
|
self._warning_btn.setIconSize(icon_size)
|
||||||
|
self._warning_btn.setProperty("LogButton", True)
|
||||||
|
self._warning_btn.setCheckable(True)
|
||||||
|
self._warning_btn.setChecked(True)
|
||||||
|
self._warning_btn.setFixedSize(btn_size)
|
||||||
|
self._warning_btn.clicked.connect(self._refresh_log)
|
||||||
|
toolbar_layout.addWidget(self._warning_btn)
|
||||||
|
|
||||||
|
self._error_btn = QtWidgets.QPushButton()
|
||||||
|
self._error_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:error.png")))
|
||||||
|
self._error_btn.setIconSize(icon_size)
|
||||||
|
self._error_btn.setProperty("LogButton", True)
|
||||||
|
self._error_btn.setCheckable(True)
|
||||||
|
self._error_btn.setChecked(True)
|
||||||
|
self._error_btn.setFixedSize(btn_size)
|
||||||
|
self._error_btn.clicked.connect(self._refresh_log)
|
||||||
|
toolbar_layout.addWidget(self._error_btn)
|
||||||
|
toolbar_layout.addStretch(0)
|
||||||
|
|
||||||
|
self._clear_log_btn = QtWidgets.QPushButton()
|
||||||
|
self._clear_log_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:clear.png")))
|
||||||
|
self._clear_log_btn.setIconSize(icon_size)
|
||||||
|
self._clear_log_btn.setProperty("LogButton", True)
|
||||||
|
self._clear_log_btn.setFixedSize(btn_size)
|
||||||
|
self._clear_log_btn.clicked.connect(self._output_log.clear)
|
||||||
|
toolbar_layout.addWidget(self._clear_log_btn)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def log_dock(self):
|
||||||
|
return self._log_dock
|
||||||
|
|
||||||
|
def emit(self, record):
|
||||||
|
level_colour_map = {
|
||||||
|
logging.DEBUG: QtGui.QColor(91, 192, 222),
|
||||||
|
logging.INFO: QtGui.QColor(247, 247, 247),
|
||||||
|
logging.WARNING: QtGui.QColor(240, 173, 78),
|
||||||
|
logging.ERROR: QtGui.QColor(217, 83, 79)
|
||||||
|
}
|
||||||
|
msg = self.format(record)
|
||||||
|
item = QtWidgets.QListWidgetItem(msg)
|
||||||
|
item.setData(QtCore.Qt.UserRole, record.levelno)
|
||||||
|
item.setForeground(QtGui.QBrush(level_colour_map[record.levelno]))
|
||||||
|
self._output_log.addItem(item)
|
||||||
|
self._refresh_log()
|
||||||
|
|
||||||
|
def _refresh_log(self):
|
||||||
|
level_btn_map = {
|
||||||
|
logging.DEBUG: self._debug_btn,
|
||||||
|
logging.INFO: self._info_btn,
|
||||||
|
logging.WARNING: self._warning_btn,
|
||||||
|
logging.ERROR: self._error_btn
|
||||||
|
}
|
||||||
|
for i in range(0, self._output_log.count()):
|
||||||
|
item = self._output_log.item(i)
|
||||||
|
data = item.data(QtCore.Qt.UserRole)
|
||||||
|
item.setHidden(not level_btn_map[data].isChecked())
|
||||||
|
|
||||||
|
def _copy_to_clipboard(self):
|
||||||
|
clipboard_text = ""
|
||||||
|
for item in self._output_log.selectedItems():
|
||||||
|
text = item.text()
|
||||||
|
clipboard_text += text
|
||||||
|
if text:
|
||||||
|
clipboard_text += "\n"
|
||||||
|
clipboard = QtWidgets.QApplication.clipboard()
|
||||||
|
clipboard.setText(clipboard_text)
|
||||||
|
|
||||||
|
def _show_context_menu(self, pos):
|
||||||
|
if not self._output_log.selectedItems():
|
||||||
|
return
|
||||||
|
menu = QtWidgets.QMenu(parent=self._output_log)
|
||||||
|
copy_action = menu.addAction("Copy")
|
||||||
|
copy_action.triggered.connect(self._copy_to_clipboard)
|
||||||
|
menu.exec_(QtGui.QCursor.pos())
|
6
Scripts/Animation/keyframe_pro/__init__.py
Normal file
6
Scripts/Animation/keyframe_pro/__init__.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import keyframe_pro
|
||||||
|
from . import keyframe_pro_maya
|
||||||
|
|
4
Scripts/Animation/keyframe_pro/keyframe_pro/__init__.py
Normal file
4
Scripts/Animation/keyframe_pro/keyframe_pro/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import *
|
@ -0,0 +1,686 @@
|
|||||||
|
import json
|
||||||
|
import socket
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
class KeyframeProClient(object):
|
||||||
|
"""
|
||||||
|
Client API for Keyframe Pro
|
||||||
|
"""
|
||||||
|
|
||||||
|
API_VERSION = "1.0.1"
|
||||||
|
|
||||||
|
PORT = 18181
|
||||||
|
|
||||||
|
HEADER_SIZE = 10
|
||||||
|
|
||||||
|
kpro_socket = None
|
||||||
|
kpro_initialized = False
|
||||||
|
|
||||||
|
def __init__(self, timeout=2):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
self.timeout = timeout
|
||||||
|
self.show_timeout_errors = True
|
||||||
|
|
||||||
|
def connect(self, port=-1, display_errors=True):
|
||||||
|
"""
|
||||||
|
Create a connection with the application.
|
||||||
|
|
||||||
|
:param port: The port Keyframe Pro is listening on.
|
||||||
|
:return: True if connection was successful (or already exists). False otherwise.
|
||||||
|
"""
|
||||||
|
if self.is_connected():
|
||||||
|
return True
|
||||||
|
|
||||||
|
if port < 0:
|
||||||
|
port = self.__class__.PORT
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.__class__.kpro_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.__class__.kpro_socket.connect(("localhost", port))
|
||||||
|
self.__class__.kpro_socket.setblocking(0)
|
||||||
|
|
||||||
|
self.__class__.kpro_initialized = False
|
||||||
|
|
||||||
|
except:
|
||||||
|
self.__class__.kpro_socket = None
|
||||||
|
if display_errors:
|
||||||
|
traceback.print_exc()
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
"""
|
||||||
|
Disconnect from the application.
|
||||||
|
|
||||||
|
:return: True if the existing connection was disconnect successfully. False otherwise.
|
||||||
|
"""
|
||||||
|
result = False
|
||||||
|
if self.__class__.kpro_socket:
|
||||||
|
try:
|
||||||
|
self.__class__.kpro_socket.close()
|
||||||
|
result = True
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
self.__class__.kpro_socket = None
|
||||||
|
self.__class__.kpro_initialized = False
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def is_connected(self):
|
||||||
|
"""
|
||||||
|
Test if a connection exists.
|
||||||
|
|
||||||
|
:return: True if a connection exists. False otherwise.
|
||||||
|
"""
|
||||||
|
self.show_timeout_errors = False
|
||||||
|
connected = self.__class__.kpro_socket and self.echo("conn")
|
||||||
|
self.show_timeout_errors = True
|
||||||
|
|
||||||
|
if connected:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
self.disconnect()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def send(self, cmd):
|
||||||
|
"""
|
||||||
|
Send a command to the application and wait for a processed reply.
|
||||||
|
|
||||||
|
:param cmd: Dictionary containing the cmd and args
|
||||||
|
:return: Variable depending on cmd.
|
||||||
|
"""
|
||||||
|
json_cmd = json.dumps(cmd)
|
||||||
|
|
||||||
|
message = []
|
||||||
|
message.append("{:10d}".format(len(json_cmd))) # header
|
||||||
|
message.append(json_cmd)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.__class__.kpro_socket.sendall("".join(message))
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.recv(cmd)
|
||||||
|
|
||||||
|
def recv(self, cmd):
|
||||||
|
"""
|
||||||
|
Wait for the application to reply to a previously sent cmd.
|
||||||
|
|
||||||
|
:param cmd: Dictionary containing the cmd and args
|
||||||
|
:return: Variable depending on cmd.
|
||||||
|
"""
|
||||||
|
total_data = []
|
||||||
|
data = ""
|
||||||
|
reply_length = 0
|
||||||
|
bytes_remaining = self.__class__.HEADER_SIZE
|
||||||
|
|
||||||
|
begin = time.time()
|
||||||
|
while time.time() - begin < self.timeout:
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = self.__class__.kpro_socket.recv(bytes_remaining)
|
||||||
|
except:
|
||||||
|
time.sleep(0.01)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if data:
|
||||||
|
total_data.append(data)
|
||||||
|
|
||||||
|
bytes_remaining -= len(data)
|
||||||
|
if(bytes_remaining <= 0):
|
||||||
|
|
||||||
|
if reply_length == 0:
|
||||||
|
header = "".join(total_data)
|
||||||
|
reply_length = int(header)
|
||||||
|
bytes_remaining = reply_length
|
||||||
|
total_data = []
|
||||||
|
else:
|
||||||
|
reply_json = "".join(total_data)
|
||||||
|
return json.loads(reply_json)
|
||||||
|
|
||||||
|
if self.show_timeout_errors:
|
||||||
|
if "cmd" in cmd.keys():
|
||||||
|
cmd_name = cmd["cmd"]
|
||||||
|
print('[KPRO][ERROR] "{0}" timed out.'.format(cmd_name))
|
||||||
|
else:
|
||||||
|
print('[KPRO][ERROR] Unknown cmd timed out.')
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_valid_reply(self, reply):
|
||||||
|
"""
|
||||||
|
Test if a reply from the application is valid. Output any messages.
|
||||||
|
|
||||||
|
:param reply: Dictionary containing the response to a cmd
|
||||||
|
:return: True if valid. False otherwise.
|
||||||
|
"""
|
||||||
|
if not reply:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not reply["success"]:
|
||||||
|
print('[KPRO][ERROR] "{0}" failed: {1}'.format(reply["cmd"], reply["msg"]))
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
"""
|
||||||
|
One time initialization required by the application.
|
||||||
|
|
||||||
|
:return: True if successfully initalized. False otherwise.
|
||||||
|
"""
|
||||||
|
if self.__class__.kpro_initialized:
|
||||||
|
return True
|
||||||
|
|
||||||
|
cmd = {
|
||||||
|
"cmd": "initialize",
|
||||||
|
"api_version": self.__class__.API_VERSION
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if reply and reply["success"] and reply["result"] == 0:
|
||||||
|
self.__class__.kpro_initialized = True
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print('[KPRO][ERROR] Initialization failed: {0}'.format(reply["msg"]))
|
||||||
|
self.disconnect()
|
||||||
|
return False
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# COMMANDS
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
def echo(self, text):
|
||||||
|
"""
|
||||||
|
Get an echo response from the application.
|
||||||
|
|
||||||
|
:param text: The string to be sent to the application.
|
||||||
|
:return: A string containing the text on success. None otherwise.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "echo",
|
||||||
|
"text": text
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["result"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_config(self):
|
||||||
|
"""
|
||||||
|
Get the configuration settings for the application.
|
||||||
|
|
||||||
|
:return: Dictionary containing the config values.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_config"
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def new_project(self, empty=False):
|
||||||
|
"""
|
||||||
|
Create a new project.
|
||||||
|
|
||||||
|
:param empty: Create an empty project.
|
||||||
|
:return: True if new project created. False otherwise.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "new_project",
|
||||||
|
"empty": empty
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def open_project(self, file_path):
|
||||||
|
"""
|
||||||
|
Open an existing project.
|
||||||
|
|
||||||
|
:param file_path: Path to the project.
|
||||||
|
:return: True if the project is opened. False otherwise.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "open_project",
|
||||||
|
"file_path": file_path
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def save_project(self, file_path):
|
||||||
|
"""
|
||||||
|
Save the current project.
|
||||||
|
|
||||||
|
:param file_path: Path to the project.
|
||||||
|
:return: True if the project is saved. False otherwise.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "save_project",
|
||||||
|
"file_path": file_path
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_project_path(self):
|
||||||
|
"""
|
||||||
|
Get the path to the current project.
|
||||||
|
|
||||||
|
:return: The path to the project. None if there is an error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_project_path"
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["project_path"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def import_file(self, file_path, name="", range_start=-1, range_end=-1, parent_id=""):
|
||||||
|
"""
|
||||||
|
Import a source file into the project.
|
||||||
|
|
||||||
|
:param file_path: Path to the source
|
||||||
|
:param name: Name of the source
|
||||||
|
:param range_start: Range start frame
|
||||||
|
:param range_end: Range end frame
|
||||||
|
:param parent_id: Parent folder of the source
|
||||||
|
:return: Dictionary representing the source object. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "import_file",
|
||||||
|
"file_path": file_path,
|
||||||
|
"name": name,
|
||||||
|
"range_start": range_start,
|
||||||
|
"range_end": range_end,
|
||||||
|
"parent_id": parent_id
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["source"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_folder(self, name="", parent_id=""):
|
||||||
|
"""
|
||||||
|
Add a folder to the project.
|
||||||
|
|
||||||
|
:param name: Name of the folder
|
||||||
|
:param parent_id: Parent folder of the folder
|
||||||
|
:return: Dictionary representing the folder object. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "add_folder",
|
||||||
|
"name": name,
|
||||||
|
"parent_id": parent_id
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["folder"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_timeline(self, name="", parent_id=""):
|
||||||
|
"""
|
||||||
|
Add a timeline to the project.
|
||||||
|
|
||||||
|
:param name: Name of the timeline
|
||||||
|
:param parent_id: Parent folder of the timeline
|
||||||
|
:return: Dictionary representing the timeline object. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "add_timeline",
|
||||||
|
"name": name,
|
||||||
|
"parent_id": parent_id
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["timeline"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def remove(self, id, force=False):
|
||||||
|
"""
|
||||||
|
Remove a folder, timeline or source from the project.
|
||||||
|
|
||||||
|
:param id: ID for the object to be removed.
|
||||||
|
:param force: (Source only) Force removal if the source is in use in one or more timelines.
|
||||||
|
:return: True on successful removal. False otherwise.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "remove",
|
||||||
|
"id": id,
|
||||||
|
"force": force
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def update(self, obj):
|
||||||
|
"""
|
||||||
|
Update the folder, timeline or source object with the values contained in the obj dict.
|
||||||
|
Editable obj values that are different will be modified.
|
||||||
|
|
||||||
|
:param obj: Dictionary representing the object to be updated.
|
||||||
|
:return: Dictionary representing the updated object. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "update",
|
||||||
|
"object": obj
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["updated"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def insert_element_in_timeline(self, source_id, timeline_id, index=-1):
|
||||||
|
"""
|
||||||
|
Insert a source element into a timeline.
|
||||||
|
|
||||||
|
:param source_id: ID of the source to be added to the timeline.
|
||||||
|
:param timeline_id: ID of the timeline.
|
||||||
|
:param index: Index to insert source at. Inserted at the end if index is out of range.
|
||||||
|
:return: True on successful insertion. False otherwise.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "insert_element_in_timeline",
|
||||||
|
"source_id": source_id,
|
||||||
|
"timeline_id": timeline_id,
|
||||||
|
"index": index
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def remove_element_from_timeline(self, timeline_id, index):
|
||||||
|
"""
|
||||||
|
Remove a source element from a timeline.
|
||||||
|
|
||||||
|
:param timeline_id: ID of the timeline.
|
||||||
|
:param index: Index of the element to be removed.
|
||||||
|
:return: True on successful removal. False otherwise.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "remove_element_from_timeline",
|
||||||
|
"timeline_id": timeline_id,
|
||||||
|
"index": index
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_timeline_elements(self, timeline_id):
|
||||||
|
"""
|
||||||
|
Get an ordered list of the sources in a timeline.
|
||||||
|
|
||||||
|
:param timeline_id: ID of the timeline.
|
||||||
|
:return: An ordered list of dictionaries representing the sources in a timeline. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_timeline_elements",
|
||||||
|
"timeline_id": timeline_id
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["sources"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_folders(self):
|
||||||
|
"""
|
||||||
|
Get an unordered list of the folders in the project.
|
||||||
|
|
||||||
|
:return: An unordered list of dictionaries representing the folders in the project. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_folders"
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["folders"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_timelines(self):
|
||||||
|
"""
|
||||||
|
Get an unordered list of timelines in the project.
|
||||||
|
|
||||||
|
:return: An unordered list of dictionaries representing the timelines in the project. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_timelines"
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["timelines"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_sources(self):
|
||||||
|
"""
|
||||||
|
Get an unordered list of sources in the project.
|
||||||
|
|
||||||
|
:return: An unordered list of dictionaries representing the sources in the project. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_sources"
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["sources"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_frame(self):
|
||||||
|
"""
|
||||||
|
Get the current frame of the (primary) active timeline.
|
||||||
|
|
||||||
|
:return: The frame of the (primary) active timeline. Zero on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_frame"
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["frame"]
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def set_frame(self, frame, audio=False):
|
||||||
|
"""
|
||||||
|
Set the current frame of the (primary) active timeline.
|
||||||
|
|
||||||
|
:param frame: Requested frame number
|
||||||
|
:param audio: Play audio for the frame after setting it.
|
||||||
|
:return: The frame of the (primary) active timeline. Zero on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "set_frame",
|
||||||
|
"frame": frame,
|
||||||
|
"audio": audio
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["frame"]
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def get_range(self):
|
||||||
|
"""
|
||||||
|
Get the current range of the (primary) active timeline.
|
||||||
|
|
||||||
|
:return: Tuple containing the range of the (primary) active timeline. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_range"
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return (reply["start_frame"], reply["end_frame"])
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_range(self, start_frame, end_frame):
|
||||||
|
"""
|
||||||
|
Set the current range of the (primary) active timeline.
|
||||||
|
|
||||||
|
:param start_frame: Requested range start frame number.
|
||||||
|
:param end_frame: Requested range end frame number.
|
||||||
|
:return: Tuple containing the range of the (primary) active timeline. None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "set_range",
|
||||||
|
"start_frame": start_frame,
|
||||||
|
"end_frame": end_frame
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return (reply["start_frame"], reply["end_frame"])
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_default_timeline(self):
|
||||||
|
"""
|
||||||
|
Get the project default timeline.
|
||||||
|
|
||||||
|
Imported files (sources) are automatically added to this timeline.
|
||||||
|
|
||||||
|
:return: Dictionary representing the timeline object (may be empty if unassigned). None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_default_timeline"
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["timeline"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_default_timeline(self, id):
|
||||||
|
"""
|
||||||
|
Set the project default timeline. An empty 'id' string will result unassign the default timeline.
|
||||||
|
|
||||||
|
Imported files (sources) are automatically added to this timeline.
|
||||||
|
|
||||||
|
:return: Dictionary representing the timeline object (may be empty if unassigned). None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "set_default_timeline",
|
||||||
|
"id": id
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_active_in_viewer(self, index):
|
||||||
|
"""
|
||||||
|
Get the source/timeline assigned to a viewer.
|
||||||
|
|
||||||
|
:param index: Viewer index. (0 - Viewer A, 1 - Viewer B)
|
||||||
|
:return: Dictionary representing the timeline object (may be empty if unassigned). None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "get_active_in_viewer",
|
||||||
|
"index": index
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return reply["timeline"]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_active_in_viewer(self, id, index):
|
||||||
|
"""
|
||||||
|
Set the source/timeline assigned to a viewer.
|
||||||
|
|
||||||
|
An empty 'id' string will unassign a timeline from the viewer.
|
||||||
|
|
||||||
|
:param index: Viewer index. (0 - Viewer A, 1 - Viewer B)
|
||||||
|
:return: Dictionary representing the timeline object (may be empty if unassigned). None on error.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "set_active_in_viewer",
|
||||||
|
"id": id,
|
||||||
|
"index": index
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def set_viewer_layout(self, layout="single"):
|
||||||
|
"""
|
||||||
|
Set the viewer layout to single, split horizontal or split vertical.
|
||||||
|
|
||||||
|
:param layout: Desired layout ("single", "horizontal" or "vertical")
|
||||||
|
:return: True on success. False otherwise.
|
||||||
|
"""
|
||||||
|
cmd = {
|
||||||
|
"cmd": "set_viewer_layout",
|
||||||
|
"layout": layout,
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = self.send(cmd)
|
||||||
|
if self.is_valid_reply(reply):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
kpro = KeyframeProClient()
|
||||||
|
if kpro.connect():
|
||||||
|
print("Connected successfully.")
|
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import *
|
@ -0,0 +1,556 @@
|
|||||||
|
import datetime
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
import maya.cmds as cmds
|
||||||
|
import maya.mel as mel
|
||||||
|
import maya.OpenMaya as om
|
||||||
|
|
||||||
|
from keyframe_pro.keyframe_pro_client import KeyframeProClient
|
||||||
|
|
||||||
|
|
||||||
|
class MayaToKeyframePro:
|
||||||
|
|
||||||
|
WINDOW_NAME = "MayaToKeyframeProWindow"
|
||||||
|
WINDOW_TITLE = "Keyframe Pro"
|
||||||
|
|
||||||
|
VERSION = "1.0.1"
|
||||||
|
|
||||||
|
KEYFRAME_PRO_PATH = "C:/Program Files/Keyframe Pro/bin/KeyframePro.exe"
|
||||||
|
PORT = 18181
|
||||||
|
|
||||||
|
SYNC_SCRIPT_NODE_NAME = "MayaToKeyframeProScriptNode"
|
||||||
|
|
||||||
|
CACHED_TEMP_DIR_OPTION_VAR = "MayaToKeyframeProCachedTempDir"
|
||||||
|
COLLAPSE_STATE_OPTION_VAR = "MayaToKeyframeProCollapseState"
|
||||||
|
SYNC_OFFSET_OPTION_VAR = "MayaToKeyframeProSyncOffset"
|
||||||
|
FROM_RANGE_START_OPTION_VAR = "MayaToKeyframeProFromRangeStart"
|
||||||
|
|
||||||
|
WAIT_FOR_OPEN_DURATION = 1 # Seconds to sleep after trying to open the application
|
||||||
|
|
||||||
|
BUTTON_COLOR_01 = (0.5, 0.5, 0.5)
|
||||||
|
BUTTON_COLOR_02 = (0.361, 0.361, 0.361)
|
||||||
|
|
||||||
|
SYNC_ACTIVE_COLOR = (0.0, 0.5, 0.0)
|
||||||
|
|
||||||
|
kpro_client = None
|
||||||
|
|
||||||
|
main_window = None
|
||||||
|
sync_layout = None
|
||||||
|
viewer_layout = None
|
||||||
|
playblast_layout = None
|
||||||
|
|
||||||
|
sync_from_range_start_cb = None
|
||||||
|
sync_offset_ifg = None
|
||||||
|
playblast_viewer_rbg = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def open_keyframe_pro(cls, application_path=""):
|
||||||
|
if not application_path:
|
||||||
|
application_path = cls.KEYFRAME_PRO_PATH
|
||||||
|
|
||||||
|
if not application_path:
|
||||||
|
om.MGlobal.displayError("Keyframe Pro application path not set.")
|
||||||
|
elif not os.path.exists(application_path):
|
||||||
|
om.MGlobal.displayError("Keyframe Pro application path does not exist: {0}".format(application_path))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subprocess.Popen(cls.KEYFRAME_PRO_PATH, shell=False, stdin=None, stdout=None, stderr=None)
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
om.MGlobal.displayError("Failed to open Keyframe Pro. See script editor for details.")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_initialized(cls, display_errors=True):
|
||||||
|
if not cls.kpro_client:
|
||||||
|
cls.kpro_client = KeyframeProClient()
|
||||||
|
|
||||||
|
if cls.kpro_client.connect(port=cls.PORT, display_errors=display_errors):
|
||||||
|
if cls.kpro_client.initialize():
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
if display_errors:
|
||||||
|
om.MGlobal.displayError("Connection failed. Application may be closed or the port may be in use ({0}).".format(cls.PORT))
|
||||||
|
|
||||||
|
if display_errors:
|
||||||
|
om.MGlobal.displayError("Failed to connect to Keyframe Pro. See script editor for details.")
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def toggle_sync(cls):
|
||||||
|
if not cls.sync_script_node_exists() and cls.is_initialized():
|
||||||
|
cls.create_sync_script_node()
|
||||||
|
if cls.sync_script_node_exists():
|
||||||
|
cls.update_sync_time()
|
||||||
|
else:
|
||||||
|
cls.delete_sync_script_node()
|
||||||
|
|
||||||
|
cls.update_sync_state()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update_sync_time(cls):
|
||||||
|
if cls.is_initialized():
|
||||||
|
frame = cmds.currentTime(q=True) + cls.get_sync_offset()
|
||||||
|
|
||||||
|
if cls.get_from_range_start():
|
||||||
|
range = cls.kpro_client.get_range()
|
||||||
|
if range:
|
||||||
|
frame += range[0] - 1
|
||||||
|
|
||||||
|
cls.kpro_client.set_frame(frame)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_viewer_layout(cls, layout):
|
||||||
|
if cls.is_initialized():
|
||||||
|
cls.kpro_client.set_viewer_layout(layout)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def swap_timelines(cls):
|
||||||
|
if cls.is_initialized():
|
||||||
|
a = cls.kpro_client.get_active_in_viewer(0)
|
||||||
|
b = cls.kpro_client.get_active_in_viewer(1)
|
||||||
|
if b:
|
||||||
|
cls.kpro_client.set_active_in_viewer(b["id"], 0)
|
||||||
|
if a:
|
||||||
|
cls.kpro_client.set_active_in_viewer(a["id"], 1)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def playblast(cls):
|
||||||
|
|
||||||
|
format = cls.get_option_var("playblastFormat", "avi")
|
||||||
|
ext = ""
|
||||||
|
if format == "avi":
|
||||||
|
ext = "avi"
|
||||||
|
elif format == "qt":
|
||||||
|
ext = "mov"
|
||||||
|
else:
|
||||||
|
om.MGlobal.displayError("Current playblast format is image. Images are not supported in the current version of Keyframe Pro")
|
||||||
|
return
|
||||||
|
|
||||||
|
temp_dir = cls.get_temp_dir()
|
||||||
|
if not temp_dir:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not os.path.exists(temp_dir):
|
||||||
|
os.makedirs(temp_dir)
|
||||||
|
|
||||||
|
name = "blast"
|
||||||
|
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
file_path = "{0}/{1}_{2}.{3}".format(temp_dir, name, timestamp, ext)
|
||||||
|
|
||||||
|
clear_cache = cls.get_option_var("playblastClearCache", True)
|
||||||
|
show_ornaments = cls.get_option_var("playblastShowOrnaments", False)
|
||||||
|
compression = cls.get_option_var("playblastCompression", "none")
|
||||||
|
quality = cls.get_option_var("playblastQuality", 70)
|
||||||
|
percent = cls.get_option_var("playblastScale", 0.5) * 100
|
||||||
|
padding = cls.get_option_var("playblastPadding", 4)
|
||||||
|
display_source_size = cls.get_option_var("playblastDisplaySizeSource", 1)
|
||||||
|
playblast_width = cls.get_option_var("playblastWidth", 720)
|
||||||
|
playblast_height = cls.get_option_var("playblastHeight", 480)
|
||||||
|
|
||||||
|
args = {"format": format,
|
||||||
|
"clearCache": clear_cache,
|
||||||
|
"viewer": False,
|
||||||
|
"showOrnaments": show_ornaments,
|
||||||
|
"fp": padding,
|
||||||
|
"percent": percent,
|
||||||
|
"compression": compression,
|
||||||
|
"quality": quality,
|
||||||
|
"filename": file_path
|
||||||
|
}
|
||||||
|
|
||||||
|
if display_source_size == 2:
|
||||||
|
args["widthHeight"] = [cmds.getAttr("defaultResolution.w"), cmds.getAttr("defaultResolution.h")]
|
||||||
|
elif display_source_size == 3:
|
||||||
|
args["widthHeight"] = [playblast_width, playblast_height]
|
||||||
|
|
||||||
|
playback_slider = mel.eval("$tempVar = $gPlayBackSlider")
|
||||||
|
if(cmds.timeControl(playback_slider, q=True, rv=True)):
|
||||||
|
range = cmds.timeControl(playback_slider, q=True, ra=True)
|
||||||
|
args["startTime"] = range[0]
|
||||||
|
args["endTime"] = range[1]
|
||||||
|
|
||||||
|
sound = cmds.timeControl(playback_slider, q=True, sound=True)
|
||||||
|
if sound:
|
||||||
|
args["sound"] = sound
|
||||||
|
|
||||||
|
file_path = cmds.playblast(**args)
|
||||||
|
om.MGlobal.displayInfo(file_path)
|
||||||
|
|
||||||
|
# Open in viewer
|
||||||
|
viewer_index = cmds.radioButtonGrp(cls.playblast_viewer_rbg, q=True, select=True) - 1
|
||||||
|
if viewer_index <= 1:
|
||||||
|
if not cls.is_initialized(False):
|
||||||
|
cls.open_keyframe_pro()
|
||||||
|
time.sleep(cls.WAIT_FOR_OPEN_DURATION)
|
||||||
|
|
||||||
|
if not cls.is_initialized():
|
||||||
|
om.MGlobal.displayError("Failed to open in viewer. See script editor for details.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if viewer_index >= 0 and viewer_index <= 1:
|
||||||
|
# On import, source may be loaded into A. Restore current A if source is to be in B
|
||||||
|
source_in_a = None
|
||||||
|
if viewer_index > 0:
|
||||||
|
source_in_a = cls.kpro_client.get_active_in_viewer(0)
|
||||||
|
|
||||||
|
# Swap
|
||||||
|
source = cls.kpro_client.import_file(file_path)
|
||||||
|
if source:
|
||||||
|
cls.kpro_client.set_active_in_viewer(source["id"], viewer_index)
|
||||||
|
if source_in_a:
|
||||||
|
cls.kpro_client.set_active_in_viewer(source_in_a["id"], 0)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_option_var(cls, name, default):
|
||||||
|
if cmds.optionVar(exists=name):
|
||||||
|
return cmds.optionVar(q=name)
|
||||||
|
else:
|
||||||
|
return default
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def open_temp_dir(cls):
|
||||||
|
temp_dir = cls.get_temp_dir()
|
||||||
|
if temp_dir:
|
||||||
|
if sys.platform == "win32":
|
||||||
|
os.startfile(temp_dir, 'explore')
|
||||||
|
else:
|
||||||
|
om.MGlobal.displayError("Open temp dir is not supported on the current platform ({0})".format(sys.platform))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def clear_temp_dir(cls):
|
||||||
|
result = cmds.confirmDialog(title='Confirm',
|
||||||
|
message='Clear temporary directory?',
|
||||||
|
button=['Yes', 'No'],
|
||||||
|
defaultButton='Yes',
|
||||||
|
cancelButton='No',
|
||||||
|
dismissString='No')
|
||||||
|
if result == "Yes":
|
||||||
|
temp_dir = cls.get_temp_dir()
|
||||||
|
if temp_dir:
|
||||||
|
errors_occurred = False
|
||||||
|
|
||||||
|
for the_file in os.listdir(temp_dir):
|
||||||
|
file_path = os.path.join(temp_dir, the_file)
|
||||||
|
try:
|
||||||
|
if os.path.isfile(file_path):
|
||||||
|
os.unlink(file_path)
|
||||||
|
elif os.path.isdir(file_path):
|
||||||
|
shutil.rmtree(file_path)
|
||||||
|
except:
|
||||||
|
om.MGlobal.displayWarning("Failed to remove file: {0}".format(file_path))
|
||||||
|
om.MGlobal.displayWarning("File may be open in an application")
|
||||||
|
errors_occurred = True
|
||||||
|
|
||||||
|
if errors_occurred:
|
||||||
|
om.MGlobal.displayWarning("Unable to remove all files. See script editor for details.")
|
||||||
|
else:
|
||||||
|
om.MGlobal.displayInfo("Temporary directory cleared: {0}".format(temp_dir))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_temp_dir(cls):
|
||||||
|
if cls.is_initialized(display_errors=False):
|
||||||
|
config = cls.kpro_client.get_config()
|
||||||
|
if config:
|
||||||
|
cmds.optionVar(sv=[cls.CACHED_TEMP_DIR_OPTION_VAR, config["temp_dir"]])
|
||||||
|
return config["temp_dir"]
|
||||||
|
|
||||||
|
temp_dir = cls.get_option_var(cls.CACHED_TEMP_DIR_OPTION_VAR, "")
|
||||||
|
if not temp_dir:
|
||||||
|
om.MGlobal.displayWarning("Unable to get temporary directory.")
|
||||||
|
|
||||||
|
return temp_dir
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sync_script_node_exists(cls):
|
||||||
|
return cmds.objExists(cls.SYNC_SCRIPT_NODE_NAME)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_sync_script_node(cls):
|
||||||
|
if not cls.sync_script_node_exists():
|
||||||
|
cmds.scriptNode(scriptType=7,
|
||||||
|
beforeScript="try: MayaToKeyframePro.update_sync_time()\nexcept: pass",
|
||||||
|
name=cls.SYNC_SCRIPT_NODE_NAME,
|
||||||
|
sourceType="python")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def delete_sync_script_node(cls):
|
||||||
|
if cls.sync_script_node_exists():
|
||||||
|
cmds.delete(cls.SYNC_SCRIPT_NODE_NAME)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_sync_offset(cls):
|
||||||
|
if cmds.optionVar(exists=cls.SYNC_OFFSET_OPTION_VAR):
|
||||||
|
return cmds.optionVar(q=cls.SYNC_OFFSET_OPTION_VAR)
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_sync_offset(cls, value):
|
||||||
|
cmds.intFieldGrp(cls.sync_offset_ifg, e=True, value1=value)
|
||||||
|
cmds.optionVar(iv=[cls.SYNC_OFFSET_OPTION_VAR, value])
|
||||||
|
if (cls.sync_script_node_exists()):
|
||||||
|
cls.update_sync_time()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sync_offset_to_current(cls):
|
||||||
|
cls.set_sync_offset(-cmds.currentTime(q=True) + 1)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sync_offset_changed(cls):
|
||||||
|
cls.set_sync_offset(cmds.intFieldGrp(cls.sync_offset_ifg, q=True, value1=True))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_from_range_start(cls):
|
||||||
|
if cmds.optionVar(exists=cls.FROM_RANGE_START_OPTION_VAR):
|
||||||
|
return cmds.optionVar(q=cls.FROM_RANGE_START_OPTION_VAR)
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update_from_range_start(cls):
|
||||||
|
value = cmds.checkBox(cls.sync_from_range_start_cb, q=True, value=True)
|
||||||
|
cmds.optionVar(iv=[cls.FROM_RANGE_START_OPTION_VAR, value])
|
||||||
|
|
||||||
|
if cls.sync_script_node_exists():
|
||||||
|
cls.update_sync_time()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_collapse_state(cls):
|
||||||
|
if cmds.optionVar(exists=cls.COLLAPSE_STATE_OPTION_VAR):
|
||||||
|
collapse_state = cmds.optionVar(q=cls.COLLAPSE_STATE_OPTION_VAR)
|
||||||
|
if len(collapse_state) == 3:
|
||||||
|
for value in collapse_state:
|
||||||
|
if value < 0 or value > 1:
|
||||||
|
return [0, 1, 1]
|
||||||
|
|
||||||
|
return collapse_state
|
||||||
|
|
||||||
|
return [0, 1, 1]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update_collapse_state(cls):
|
||||||
|
cmds.optionVar(clearArray=cls.COLLAPSE_STATE_OPTION_VAR)
|
||||||
|
layouts = [cls.sync_layout, cls.viewer_layout, cls.playblast_layout]
|
||||||
|
for layout in layouts:
|
||||||
|
collapse = cmds.frameLayout(layout, q=True, cl=True)
|
||||||
|
cmds.optionVar(iva=[cls.COLLAPSE_STATE_OPTION_VAR, collapse])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def display(cls):
|
||||||
|
|
||||||
|
if cmds.window(cls.WINDOW_NAME, exists=True):
|
||||||
|
cmds.deleteUI(cls.WINDOW_NAME, window=True)
|
||||||
|
|
||||||
|
collapse_state = cls.get_collapse_state()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# Main layout
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
cls.main_window = cmds.window(cls.WINDOW_NAME, title=cls.WINDOW_TITLE, s=True, tlb=False, rtf=True, mnb=False, mxb=False)
|
||||||
|
main_layout = cmds.formLayout(parent=cls.main_window)
|
||||||
|
|
||||||
|
cls.sync_layout = cmds.frameLayout(parent=main_layout,
|
||||||
|
label="Sync", collapsable=True,
|
||||||
|
cl=collapse_state[0],
|
||||||
|
cc=lambda *args: cmds.evalDeferred("MayaToKeyframePro.on_collapse_changed()"),
|
||||||
|
ec=lambda *args: cmds.evalDeferred("MayaToKeyframePro.on_collapse_changed()"))
|
||||||
|
sync_form_layout = cmds.formLayout(parent=cls.sync_layout)
|
||||||
|
|
||||||
|
cls.viewer_layout = cmds.frameLayout(parent=main_layout,
|
||||||
|
label="Viewer",
|
||||||
|
collapsable=True,
|
||||||
|
cl=collapse_state[1],
|
||||||
|
cc=lambda *args: cmds.evalDeferred("MayaToKeyframePro.on_collapse_changed()"),
|
||||||
|
ec=lambda *args: cmds.evalDeferred("MayaToKeyframePro.on_collapse_changed()"))
|
||||||
|
viewer_form_layout = cmds.formLayout(parent=cls.viewer_layout)
|
||||||
|
|
||||||
|
cls.playblast_layout = cmds.frameLayout(parent=main_layout,
|
||||||
|
label="Playblast",
|
||||||
|
collapsable=True,
|
||||||
|
cl=collapse_state[2],
|
||||||
|
cc=lambda *args: cmds.evalDeferred("MayaToKeyframePro.on_collapse_changed()"),
|
||||||
|
ec=lambda *args: cmds.evalDeferred("MayaToKeyframePro.on_collapse_changed()"))
|
||||||
|
playblast_form_layout = cmds.formLayout(parent=cls.playblast_layout)
|
||||||
|
|
||||||
|
cmds.formLayout(main_layout, e=True, af=(cls.sync_layout, "top", 0))
|
||||||
|
cmds.formLayout(main_layout, e=True, af=(cls.sync_layout, "left", 0))
|
||||||
|
cmds.formLayout(main_layout, e=True, af=(cls.sync_layout, "right", 0))
|
||||||
|
|
||||||
|
cmds.formLayout(main_layout, e=True, ac=(cls.viewer_layout, "top", 0, cls.sync_layout))
|
||||||
|
cmds.formLayout(main_layout, e=True, af=(cls.viewer_layout, "left", 0))
|
||||||
|
cmds.formLayout(main_layout, e=True, af=(cls.viewer_layout, "right", 0))
|
||||||
|
|
||||||
|
cmds.formLayout(main_layout, e=True, ac=(cls.playblast_layout, "top", 0, cls.viewer_layout))
|
||||||
|
cmds.formLayout(main_layout, e=True, af=(cls.playblast_layout, "left", 0))
|
||||||
|
cmds.formLayout(main_layout, e=True, af=(cls.playblast_layout, "right", 0))
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# Sync layout
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
cls.sync_offset_ifg = cmds.intFieldGrp(label="Offset: ",
|
||||||
|
value1=MayaToKeyframePro.get_sync_offset(),
|
||||||
|
columnWidth2=(40, 48),
|
||||||
|
cl2=("left", "right"),
|
||||||
|
cc=lambda *args: MayaToKeyframePro.sync_offset_changed(),
|
||||||
|
parent=sync_form_layout)
|
||||||
|
|
||||||
|
cls.sync_from_range_start_cb = cmds.checkBox(label="From Range Start",
|
||||||
|
value=MayaToKeyframePro.get_from_range_start(),
|
||||||
|
cc=lambda *args: MayaToKeyframePro.update_from_range_start(),
|
||||||
|
parent=sync_form_layout)
|
||||||
|
|
||||||
|
sync_offset_to_current_btn = cmds.button(label="Current",
|
||||||
|
bgc=cls.BUTTON_COLOR_01,
|
||||||
|
c=lambda *args: MayaToKeyframePro.sync_offset_to_current(),
|
||||||
|
parent=sync_form_layout)
|
||||||
|
|
||||||
|
reset_sync_offset_btn = cmds.button(label=" Reset ",
|
||||||
|
bgc=cls.BUTTON_COLOR_01,
|
||||||
|
c=lambda *args: MayaToKeyframePro.set_sync_offset(0),
|
||||||
|
parent=sync_form_layout)
|
||||||
|
|
||||||
|
cls.sync_btn = cmds.button(label="SYNC", c=lambda *args: MayaToKeyframePro.toggle_sync(), parent=sync_form_layout)
|
||||||
|
|
||||||
|
top_offset = 1
|
||||||
|
bottom_offset = 4
|
||||||
|
left_position = 1
|
||||||
|
right_position = 99
|
||||||
|
spacing = 2
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, af=(cls.sync_offset_ifg, "top", top_offset))
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, ap=(cls.sync_offset_ifg, "left", 0, left_position))
|
||||||
|
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, af=(sync_offset_to_current_btn, "top", top_offset))
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, ac=(sync_offset_to_current_btn, "left", 0, cls.sync_offset_ifg))
|
||||||
|
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, af=(reset_sync_offset_btn, "top", top_offset))
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, ac=(reset_sync_offset_btn, "left", spacing, sync_offset_to_current_btn))
|
||||||
|
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, ac=(cls.sync_from_range_start_cb, "top", top_offset, sync_offset_to_current_btn))
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, ap=(cls.sync_from_range_start_cb, "left", 0, left_position))
|
||||||
|
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, ac=(cls.sync_btn, "top", 2 * spacing, cls.sync_from_range_start_cb))
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, af=(cls.sync_btn, "bottom", bottom_offset))
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, ap=(cls.sync_btn, "left", 0, left_position))
|
||||||
|
cmds.formLayout(sync_form_layout, e=True, ap=(cls.sync_btn, "right", 0, right_position))
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# Viewer layout
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
single_viewer_btn = cmds.button(label="Single",
|
||||||
|
bgc=cls.BUTTON_COLOR_01,
|
||||||
|
c=lambda *args: MayaToKeyframePro.set_viewer_layout('single'),
|
||||||
|
parent=viewer_form_layout)
|
||||||
|
|
||||||
|
hori_viewer_btn = cmds.button(label="Horizontal",
|
||||||
|
bgc=cls.BUTTON_COLOR_01,
|
||||||
|
c=lambda *args: MayaToKeyframePro.set_viewer_layout('horizontal'),
|
||||||
|
parent=viewer_form_layout)
|
||||||
|
|
||||||
|
vert_viewer_btn = cmds.button(label=" Vertical ",
|
||||||
|
bgc=cls.BUTTON_COLOR_01,
|
||||||
|
c=lambda *args: MayaToKeyframePro.set_viewer_layout('vertical'),
|
||||||
|
parent=viewer_form_layout)
|
||||||
|
|
||||||
|
swap_timelines_btn = cmds.button(label="Swap Timelines",
|
||||||
|
bgc=cls.BUTTON_COLOR_01,
|
||||||
|
c=lambda *args: MayaToKeyframePro.swap_timelines(),
|
||||||
|
parent=viewer_form_layout)
|
||||||
|
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, af=(single_viewer_btn, "top", top_offset))
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, ap=(single_viewer_btn, "left", 0, left_position))
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, ap=(single_viewer_btn, "right", 0, 38))
|
||||||
|
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, af=(hori_viewer_btn, "top", top_offset))
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, ac=(hori_viewer_btn, "left", spacing, single_viewer_btn))
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, ap=(hori_viewer_btn, "right", 0, 68))
|
||||||
|
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, af=(vert_viewer_btn, "top", top_offset))
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, ac=(vert_viewer_btn, "left", spacing, hori_viewer_btn))
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, ap=(vert_viewer_btn, "right", 0, right_position))
|
||||||
|
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, ac=(swap_timelines_btn, "top", spacing, single_viewer_btn))
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, af=(swap_timelines_btn, "bottom", bottom_offset))
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, ap=(swap_timelines_btn, "left", 0, left_position))
|
||||||
|
cmds.formLayout(viewer_form_layout, e=True, ap=(swap_timelines_btn, "right", 0, right_position))
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# Playblast layout
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
cls.playblast_viewer_rbg = cmds.radioButtonGrp(label='Open in Viewer: ',
|
||||||
|
labelArray3=['A', 'B', 'None'],
|
||||||
|
numberOfRadioButtons=3,
|
||||||
|
select=1,
|
||||||
|
cw4=(100, 40, 40, 40),
|
||||||
|
cl4=("left", "left", "left", "left"),
|
||||||
|
parent=playblast_form_layout)
|
||||||
|
|
||||||
|
playblast_btn = cmds.button(label="PLAYBLAST",
|
||||||
|
bgc=cls.BUTTON_COLOR_01,
|
||||||
|
c=lambda *args: MayaToKeyframePro.playblast(),
|
||||||
|
parent=playblast_form_layout)
|
||||||
|
|
||||||
|
open_temp_dir_btn = cmds.button(label="Open Temp Folder",
|
||||||
|
bgc=cls.BUTTON_COLOR_01,
|
||||||
|
c=lambda *args: MayaToKeyframePro.open_temp_dir(),
|
||||||
|
parent=playblast_form_layout)
|
||||||
|
|
||||||
|
clear_temp_dir_btn = cmds.button(label="Clear Temp Folder",
|
||||||
|
bgc=cls.BUTTON_COLOR_01,
|
||||||
|
c=lambda *args: MayaToKeyframePro.clear_temp_dir(),
|
||||||
|
parent=playblast_form_layout)
|
||||||
|
|
||||||
|
version_label = cmds.text(label="v{0}".format(cls.VERSION), align="right")
|
||||||
|
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, af=(cls.playblast_viewer_rbg, "top", top_offset))
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ap=(cls.playblast_viewer_rbg, "left", 0, left_position))
|
||||||
|
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ac=(playblast_btn, "top", spacing, cls.playblast_viewer_rbg))
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ap=(playblast_btn, "left", 0, left_position))
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ap=(playblast_btn, "right", 0, right_position))
|
||||||
|
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ac=(open_temp_dir_btn, "top", spacing, playblast_btn))
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ap=(open_temp_dir_btn, "left", 0, left_position))
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ap=(open_temp_dir_btn, "right", 1, 50))
|
||||||
|
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ac=(clear_temp_dir_btn, "top", spacing, playblast_btn))
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ap=(clear_temp_dir_btn, "left", 1, 50))
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ap=(clear_temp_dir_btn, "right", 0, right_position))
|
||||||
|
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ac=(version_label, "top", spacing, open_temp_dir_btn))
|
||||||
|
cmds.formLayout(playblast_form_layout, e=True, ap=(version_label, "right", 0, right_position))
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# Update and show
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
cls.update_sync_state()
|
||||||
|
cls.on_collapse_changed()
|
||||||
|
cmds.setFocus(cls.sync_btn)
|
||||||
|
|
||||||
|
cmds.showWindow(cls.main_window)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def on_collapse_changed(cls):
|
||||||
|
total_height = 0
|
||||||
|
layouts = [cls.sync_layout, cls.viewer_layout, cls.playblast_layout]
|
||||||
|
for layout in layouts:
|
||||||
|
total_height += cmds.frameLayout(layout, q=True, h=True)
|
||||||
|
|
||||||
|
cmds.window(MayaToKeyframePro.main_window, e=True, h=total_height)
|
||||||
|
cls.update_collapse_state()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update_sync_state(cls):
|
||||||
|
if cls.sync_script_node_exists():
|
||||||
|
cmds.button(cls.sync_btn, e=True, bgc=cls.SYNC_ACTIVE_COLOR, label="SYNCED")
|
||||||
|
else:
|
||||||
|
cmds.button(cls.sync_btn, e=True, bgc=cls.BUTTON_COLOR_01, label="SYNC")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
MayaToKeyframePro.display()
|
1480
Scripts/Animation/mog_ikFkSwitchFree.py
Normal file
1480
Scripts/Animation/mog_ikFkSwitchFree.py
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user