This commit is contained in:
2025-04-17 04:52:48 +08:00
commit 9985b73dc1
3708 changed files with 2387532 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Modified: Michael Klimenko
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
import importlib
import os
from maya import cmds
from maya import mel
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod; importlib.reload(uiMod)
from aTools.commonMods import utilMod; importlib.reload(utilMod)
from aTools.commonMods import animMod; importlib.reload(animMod)
MODULES = ["align","selectSets","mirror","spaceSwitch","tempCustomPivot","animationCopier","fakeConstrain", "microTransform", "transformAll"]
# import subUI modules
for loopMod in MODULES:
exec("from aTools.animTools.animBar.subUIs.specialTools_subUIs import %s; importlib.reload(%s)"%(loopMod, loopMod))
class SpecialTools_Gui(uiMod.BaseSubUI):
def createLayout(self):
cmds.rowLayout(numberOfColumns=20, parent=self.parentLayout)
#SELECTION SETS
SelectSets = selectSets.SelectSets()
cmds.iconTextButton("selectSetsBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_select_sets"), highlightImage= uiMod.getImagePath("specialTools_select_sets copy"), w=self.wb, h=self.hb, command=SelectSets.toggleToolbar, annotation="Quick select set groups\nRight click for options")
SelectSets.popupMenu()
#ALIGN
Align = align.Align()
cmds.iconTextButton(style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_align"), highlightImage= uiMod.getImagePath("specialTools_align copy"), w=self.wb, h=self.hb, command=Align.alignSelection, annotation="Align selection\nSelect the slaves and a master object\nRight click for options")
Align.popupMenu()
#MIRROR
Mirror = mirror.Mirror()
cmds.iconTextButton("mirrorBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_mirror"), highlightImage= uiMod.getImagePath("specialTools_mirror copy"), w=self.wb, h=self.hb, command=Mirror.start, annotation="Mirror values to opposite ctrls\nHighlight the timeline for applying on a range\nRight click for options\n\nCtrl+click: Select mirror objects\nShift+click: Add mirror objects to selection")
Mirror.popupMenu()
#SPACE SWITCH
SpaceSwitch = spaceSwitch.SpaceSwitch()
cmds.iconTextButton(style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_space_switcher"), highlightImage= uiMod.getImagePath("specialTools_space_switcher copy"), w=self.wb, h=self.hb, annotation="Space switcher\nIf the constraint controller is not the same as the attribute controller, select it too")
SpaceSwitch.popupMenu()
#TEMP CUSTOM PIVOT
TempCustomPivot = tempCustomPivot.TempCustomPivot()
cmds.iconTextButton("TempCustomPivotBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_create_temp_custom_pivot"), highlightImage= uiMod.getImagePath("specialTools_create_temp_custom_pivot copy"), w=self.wb, h=self.hb, command=TempCustomPivot.create, annotation="Temporary custom pivot\nRight click for options")
TempCustomPivot.popupMenu()
#ANIMATION COPIER
AnimationCopier = animationCopier.AnimationCopier()
cmds.iconTextButton(style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_copy_animation"), highlightImage= uiMod.getImagePath("specialTools_copy_animation copy"), w=self.wb, h=self.hb, command=AnimationCopier.copyAnimation, annotation="Animation Copier\nRight click for options")
AnimationCopier.popupMenu()
#FAKE CONSTRAIN
FakeConstrain = fakeConstrain.FakeConstrain()
cmds.iconTextButton("fakeConstrainBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_fake_constrain"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain copy"), w=self.wb, h=self.hb, command=FakeConstrain.copyPaste, annotation="Fake Constrain\nClick once to copy objects position relative to the last selected\nGo to another frame or select a range and click again to paste\nChanging the current selection will flush the copy cache\n\nRight click for options")
FakeConstrain.popupMenu()
# motion trail is disabled, please use the built-in
# #MOTION TRAIL
# MotionTrail = motionTrail.MotionTrail()
# MotionTrail.toolBarButton = cmds.iconTextButton("motionTrailBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_motion_trail"), highlightImage= uiMod.getImagePath("specialTools_motion_trail copy"), w=self.wb, h=self.hb, command=MotionTrail.switch, annotation="Motion trail\nRight click for options")
# MotionTrail.popupMenu()
# #cmds.iconTextButton("motionTrailBtnOLD", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_motion_trail"), highlightImage= uiMod.getImagePath("specialTools_motion_trail copy"), w=self.wb, h=self.hb, command=self.motionTrail, annotation="Motion trail")
#MICRO TRANSFORM
MicroTransform = microTransform.MicroTransform()
cmds.iconTextButton("microTransformBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_micro_transform"), highlightImage= uiMod.getImagePath("specialTools_micro_transform copy"), w=self.wb, h=self.hb, command=MicroTransform.switch, annotation="Enable micro transform\nRight click for options")
MicroTransform.popupMenu()
#TRANSFORM ALL
TransformAll = transformAll.TransformAll()
cmds.iconTextButton ("transformAllBtn", style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("specialTools_transform_all"), highlightImage= uiMod.getImagePath("specialTools_transform_all copy"), command=TransformAll.switch, annotation="Enable transform all keys\nWill affect selected range or all keys if no range is selected\nCtrl+click will toggle blend range mode")
#TransformAll.popupMenu()
# end createLayout

View File

@ -0,0 +1,177 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import utilMod
from aTools.commonMods import animMod
class Align(object):
def __init__(self):
if G.aToolsBar.align: return
G.aToolsBar.align = self
def popupMenu(self):
cmds.popupMenu()
cmds.menuItem(label="All Keys", command=self.alignAllKeys)
cmds.menuItem( divider=True )
cmds.menuItem(label="Align Position", command=lambda *args: self.alignSelection(True, False))
cmds.menuItem(label="Align Rotation", command=lambda *args: self.alignSelection(False, True))
def alignAllKeys(self, *args):
self.alignSelection(translate=True, rotate=True, all=True)
def alignSelection(self, translate=True, rotate=True, all=False):
selection = cmds.ls(selection=True)
if len(selection) < 2:
cmds.warning("You need to select at least 2 objects.")
return
sourceObjs = selection[0:-1]
targetObj = selection[-1]
frames = None
currFrame = cmds.currentTime(query=True)
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
showProgress = all
if animCurves:
if all: keysSel = animMod.getTarget("keyTimes", animCurves, getFrom)
else: keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
frames = utilMod.mergeLists(keysSel)
if frames == []:
frames = [currFrame]
else:
frames = [currFrame]
self.align(sourceObjs, targetObj, frames, translate, rotate, showProgress, selectSorceObjs=True)
def align(self, sourceObjs, targetObj, frames=None, translate=True, rotate=True, showProgress=False, selectSorceObjs=False):
if not sourceObjs or not targetObj: return
cmds.refresh(suspend=True)
currFrame = cmds.currentTime(query=True)
constraints = []
setValues = []
modes = []
status = "aTools - Aligning nodes..."
if translate: modes.append({"mode":"translate", "constrain":"pointConstraint"})
if rotate: modes.append({"mode":"rotate", "constrain":"orientConstraint"})
if showProgress: utilMod.startProgressBar(status)
if not frames:
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves:
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
frames = utilMod.mergeLists(keysSel)
if frames == []:
frames = [currFrame]
else:
frames = [currFrame]
if showProgress:
totalSteps = len(sourceObjs + frames)
firstStep = 0
thisStep = 0
estimatedTime = None
startChrono = None
#get values
for thisStep, loopSourceObj in enumerate(sourceObjs):
if showProgress: startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
setValues.append({"modes":[], "values":[], "skips":[]})
for loopMode in modes:
mode = loopMode["mode"]
constrainType = loopMode["constrain"]
allAttrs = cmds.listAttr(loopSourceObj, settable=True, keyable=True)
skip = [loopXyz for loopXyz in ["x", "y", "z"] if "%s%s"%(mode, loopXyz.upper()) not in allAttrs]
contrainFn = eval("cmds.%s"%constrainType)
with G.aToolsBar.createAToolsNode: constraints.append(contrainFn(targetObj, loopSourceObj, skip=skip)[0])
setValues[-1]["modes"].append(mode)
setValues[-1]["values"].append([cmds.getAttr("%s.%s"%(loopSourceObj, mode), time=loopKey)[0] for loopKey in frames])
setValues[-1]["skips"].append(skip)
if showProgress: estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
#del constraints
for loopConstrain in constraints: cmds.delete(loopConstrain)
for n, loopKey in enumerate(frames):
if showProgress:
thisStep = thisStep + n + 1
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
for nn, loopSourceObj in enumerate(sourceObjs):
loopSetValue = setValues[nn]
values = loopSetValue["values"]
skips = loopSetValue["skips"]
for nnn, loopMode in enumerate(modes):
mode = loopMode["mode"]
xyz = [loopXyz for loopXyz in ["x", "y", "z"] if loopXyz not in skips[nnn]]
for nnnn, loopXyz in enumerate(xyz):
attr = "%s%s"%(mode, loopXyz.upper())
value = values[nnn][n][nnnn]
if len(frames) > 1:
cmds.setKeyframe(loopSourceObj, attribute=attr, time=(loopKey,loopKey), value=value)
if currFrame == loopKey: cmds.setAttr("%s.%s"%(loopSourceObj, attr), value)
#euler filter
if n == len(frames)-1 and rotate:
animCurves = utilMod.mergeLists([cmds.keyframe(loopSourceObj, query=True, name=True) for loopSourceObj in sourceObjs])
animMod.eulerFilterCurve(animCurves)
if showProgress: estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
if showProgress: utilMod.setProgressBar(endProgress=True)
if selectSorceObjs: cmds.select(sourceObjs)
cmds.refresh(suspend=False)

View File

@ -0,0 +1,116 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod
from aTools.commonMods import utilMod
from aTools.commonMods import animMod
from aTools.commonMods import aToolsMod
class AnimationCopier(object):
def popupMenu(self):
cmds.popupMenu()
cmds.menuItem( label="Copy All Animation", command=lambda *args: self.copyAnimation(range="all"))
cmds.menuItem( divider=True )
cmds.menuItem("onlySelectedNodesMenu", label="Paste To Selected", checkBox=False)
cmds.menuItem( label="Paste Animation in Place", command=lambda *args: self.pasteAnimation(pasteInPlace=True))
cmds.menuItem( label="Paste Original Animation", command=lambda *args: self.pasteAnimation(pasteInPlace=False))
cmds.menuItem( divider=True )
cmds.menuItem( label="Paste To Another Character", command=self.remapNamespaces)
def copyAnimation(self, range="selected", *args):
cmds.waitCursor(state=True)
if range == "all":
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
animData = animMod.getAnimData(animCurves, showProgress=True)
else:
animData = animMod.getAnimData(showProgress=True)
aToolsMod.saveInfoWithUser("copyPasteAnim", "animData", animData)
if cmds.window("remapNamespacesWindow", query=True, exists=True): self.remapNamespaces()
cmds.waitCursor(state=False)
def pasteAnimation(self, animData=None, pasteInPlace=True, onlySelectedNodes=None, *args):
cmds.waitCursor(state=True)
if not onlySelectedNodes: onlySelectedNodes = cmds.menuItem("onlySelectedNodesMenu", query=True, checkBox=True)
if not animData: animData = aToolsMod.loadInfoWithUser("copyPasteAnim", "animData")
animMod.applyAnimData(animData, pasteInPlace, onlySelectedNodes, showProgress=True)
cmds.waitCursor(state=False)
def remapNamespaces(self, *args):
winName = "remapNamespacesWindow"
if cmds.window(winName, query=True, exists=True): cmds.deleteUI(winName)
window = cmds.window( winName, title = "Remap Namespaces")
cmds.columnLayout(adjustableColumn=True)
cmds.rowColumnLayout( numberOfColumns=3)
animData = aToolsMod.loadInfoWithUser("copyPasteAnim", "animData")
inputNameSpaces = list(set(utilMod.getNameSpace(animData["objects"])[0]))
outputNameSpaces = utilMod.listAllNamespaces()
for loopNameSpace in inputNameSpaces:
nameSpace = loopNameSpace[:-1]
eval("cmds.text('input%s', align='right', w=150, h=26, label='%s: ')"%(nameSpace, nameSpace))
eval("cmds.textField('output%s', w=150, h=26, text='%s')"%(nameSpace, nameSpace))
eval("cmds.button('output%s', w=26, h=26, label='...')"%(nameSpace))
if outputNameSpaces:
cmds.popupMenu(button=1)
for loopOutput in outputNameSpaces:
cmds.menuItem ("menu%s"%loopOutput, label=str(loopOutput), command=lambda x, loopOutput=loopOutput, nameSpace=nameSpace, *args: self.setOutputValue(loopOutput, nameSpace))
cmds.setParent( '..' )
cmds.button(label="Paste Animation in Place", command=lambda *args: self.remapAndPasteAnimation(animData, inputNameSpaces, pasteInPlace=True))
cmds.button(label="Paste Original Animation", command=lambda *args: self.remapAndPasteAnimation(animData, inputNameSpaces, pasteInPlace=False))
cmds.showWindow( window )
def setOutputValue(self, output, nameSpace):
cmds.textField('output%s'%nameSpace, edit=True, text=str(output))
def remapAndPasteAnimation(self, animData, nameSpaces, pasteInPlace):
separator = ":"
for loopNameSpace in nameSpaces:
nameSpace = loopNameSpace[:-1]
input = nameSpace
output = cmds.textField('output%s'%nameSpace, query=True, text=True)
animStr = str(animData)
animData = eval(animStr.replace("%s%s"%(input, separator), "%s%s"%(output, separator)))
self.pasteAnimation(animData, pasteInPlace)

View File

@ -0,0 +1,236 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod
from aTools.commonMods import utilMod
from aTools.commonMods import animMod
class FakeConstrain(object):
def __init__(self):
self.copyCache = []
self.locators = []
self.locatorGroup = ""
self.locatorGroupName = "fakeConstrain_group"
self.selection = None
def popupMenu(self):
cmds.popupMenu(postMenuCommand=self.populateMenu)
def populateMenu(self, menu, *args):
uiMod.clearMenuItems(menu)
if self.copyCache != []:
cmds.menuItem(label='Copy', command=self.copy, parent=menu)
cmds.menuItem(label='Paste to All Frames' , command=lambda *args: self.paste('allFrames'), parent=menu)
cmds.menuItem(divider=True, parent=menu)
cmds.menuItem(label='Copy Relative to World' , command=self.copyWorld, parent=menu)
def copyPaste(self):
if len(self.copyCache) > 0: self.paste()
else: self.copy()
def copy(self, *args):
#print "copy"
self.selection = cmds.ls(selection=True)
if len(self.selection) < 1:
cmds.warning("You need to select at least 2 objects.")
return
if len(self.selection) == 1:
self.copyWorld()
return
if len(self.selection) > 20:
message = "Too many objects selected, continue?"
confirm = cmds.confirmDialog( title='Confirm', message=message, button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No' )
if confirm != 'Yes': return
cmds.refresh(suspend=True)
cmds.undoInfo(stateWithoutFlush=False)
self.flushCopyCache(force=True)
self.scriptJob()
self.sourceObjs = self.selection[0:-1]
self.targetObj = self.selection[-1]
selObjects = utilMod.getNameSpace(self.selection)[1]
self.locators = []
self.locatorGroup = animMod.group(name=self.locatorGroupName)
G.aToolsBar.align.align([self.locatorGroup], self.targetObj)
self.locators.append(self.locatorGroup)
for loopObj in self.sourceObjs:
nameSpace = utilMod.getNameSpace([loopObj])
loopSelName = "%s_%s"%(nameSpace[0][0], nameSpace[1][0])
locatorName = "fakeConstrain_%s"%loopSelName
locator = animMod.createNull(locatorName)
self.locators.append(locator)
with G.aToolsBar.createAToolsNode: cmds.parent(locator, self.locatorGroup)
G.aToolsBar.align.align([locator], loopObj)
matrix = cmds.xform(locator, query=True, matrix=True)
self.copyCache.append(matrix)
self.clearLocators()
cmds.select(self.selection)
cmds.iconTextButton("fakeConstrainBtn", edit=True, image= uiMod.getImagePath("specialTools_fake_constrain_active"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain_active copy"))
cmds.refresh(suspend=False)
cmds.undoInfo(stateWithoutFlush=True)
def copyWorld(self, *args):
#print "copyworld"
self.selection = cmds.ls(selection=True)
if len(self.selection) < 1: return
if len(self.selection) > 20:
message = "Too many objects selected, continue?"
confirm = cmds.confirmDialog( title='Confirm', message=message, button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No' )
if confirm != 'Yes': return
cmds.refresh(suspend=True)
cmds.undoInfo(stateWithoutFlush=False)
self.flushCopyCache(force=True)
self.scriptJob()
self.sourceObjs = self.selection
self.targetObj = "world"
for loopObj in self.sourceObjs:
matrix = cmds.xform(loopObj, query=True, ws=True, matrix=True)
self.copyCache.append(matrix)
cmds.iconTextButton("fakeConstrainBtn", edit=True, image= uiMod.getImagePath("specialTools_fake_constrain_active"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain_active copy"))
cmds.refresh(suspend=False)
cmds.undoInfo(stateWithoutFlush=True)
def paste(self, type="onlyKeys"):
cmds.refresh(suspend=True)
selObjects = utilMod.getNameSpace(self.selection)[1]
self.locators = []
if self.targetObj != "world":
#CREATE
self.locatorGroup = animMod.group(name=self.locatorGroupName)
for n, loopObj in enumerate(self.sourceObjs):
nameSpace = utilMod.getNameSpace([loopObj])
loopSelName = "%s_%s"%(nameSpace[0][0], nameSpace[1][0])
locatorName = "fakeConstrain_%s"%loopSelName
locator = animMod.createNull(locatorName)
self.locators.append(locator)
with G.aToolsBar.createAToolsNode: cmds.parent(locator, self.locatorGroup)
self.locators.append(self.locatorGroup)
currFrame = cmds.currentTime(query=True)
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves:
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
keysSel = utilMod.mergeLists(keysSel)
if keysSel == []:
keysSel = [currFrame]
else:
keysSel = [currFrame]
frames = keysSel
if type == "allFrames":
frameRange = animMod.getTimelineRange(float=False)
frames = list(range(int(frameRange[0]),int(frameRange[1])))
if self.targetObj != "world":
G.aToolsBar.align.align([self.locatorGroup], self.targetObj, frames=frames)
for n, loopObj in enumerate(self.sourceObjs):
matrix = self.copyCache[n]
if self.targetObj != "world":
cmds.xform(self.locators[n], matrix=matrix)
G.aToolsBar.align.align([loopObj], self.locators[n], frames=frames, showProgress=True)
else:
for loopFrame in frames:
cmds.currentTime(loopFrame)
cmds.xform(loopObj, ws=True, matrix=matrix)
cmds.currentTime(currFrame)
for loopFrame in frames:
for loopAttr in ["translate", "rotate"]:
breakdown = (loopFrame not in keysSel)
cmds.keyframe(loopObj, edit=True, attribute=loopAttr, time=(loopFrame, loopFrame), breakdown=breakdown)
if self.targetObj != "world":
self.clearLocators()
cmds.select(self.selection)
cmds.refresh(suspend=False)
def clearLocators(self):
for loopLocator in self.locators:
if cmds.objExists(loopLocator): cmds.delete(loopLocator)
if cmds.objExists(self.locatorGroup): cmds.delete(self.locatorGroup)
def flushCopyCache(self, force=False):
if not force and cmds.ls(selection=True) == self.selection:
self.scriptJob()
return
cmds.iconTextButton("fakeConstrainBtn", edit=True, image= uiMod.getImagePath("specialTools_fake_constrain"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain copy"))
self.clearLocators()
self.copyCache = []
def scriptJob(self):
#scriptjob
cmds.scriptJob(runOnce = True, killWithScene = True, event =('SelectionChanged', self.flushCopyCache))

View File

@ -0,0 +1,321 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Modified: Michael Klimenko
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from maya import mel
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod
from aTools.commonMods import utilMod
from aTools.commonMods import animMod
from aTools.commonMods import aToolsMod
import maya.OpenMaya as om
#============================================================================================================
class MicroTransform(object):
utilMod.killScriptJobs("G.microTransformScriptJobs")
def __init__(self):
G.deferredManager.removeFromQueue("MT_blinking")
if G.aToolsBar.microTransform: return
G.aToolsBar.microTransform = self
self.attributes = ['translate', 'translateX','translateY','translateZ','rotate', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scaleX','scaleY','scaleZ']
self.multiplierValues = [ {"name":"ultraSlow", "value":.05
},{"name":"superSlow", "value":.2
},{"name":"slow", "value":.5
},{"name":"medium", "value":1
}]
self.defaultMultiplier = "slow"
self.microTransformStartTimer = {}
self.microTransformValues = {}
self.onOff = False
self.rotationOrientMode = cmds.manipRotateContext('Rotate', query=True, mode=True)
self.setMultiplier(self.getMultiplier())
self.removeMicroTransform()
self.blinkingButton(self.onOff)
def blinkingButton(self, onOff):
if onOff: G.aToolsBar.timeoutInterval.setInterval(self.toggleButtonActive, .3, id="MT_blinking")
else: G.aToolsBar.timeoutInterval.stopInterval("MT_blinking")
def toggleButtonActive(self):
onOff = "active" in cmds.iconTextButton("microTransformBtn", query=True, image=True)
self.setButtonImg(not onOff)
def setButtonImg(self, onOff):
if onOff:
cmds.iconTextButton("microTransformBtn", edit=True, image=uiMod.getImagePath("specialTools_micro_transform_active"), highlightImage= uiMod.getImagePath("specialTools_micro_transform_active"))
else:
cmds.iconTextButton("microTransformBtn", edit=True, image=uiMod.getImagePath("specialTools_micro_transform"), highlightImage= uiMod.getImagePath("specialTools_micro_transform copy"))
def switch(self):
self.onOff = (not self.onOff)
self.setButtonImg(self.onOff)
self.blinkingButton(self.onOff)
self.setMode(self.onOff)
def setMode(self, onOff):
utilMod.killScriptJobs("G.microTransformScriptJobs")
if onOff:
self.rotationOrientMode = cmds.manipRotateContext('Rotate', query=True, mode=True)
cmds.manipRotateContext('Rotate', edit=True, mode=2)#gimbal
#update values on turning on
self.addMicroTransform()
G.microTransformScriptJobs = []
# get the current selected object values
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.addMicroTransform )))
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('timeChanged', self.updateValues )))
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('Undo', self.updateValues )))
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('Redo', self.updateValues )))
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('DragRelease', self.release )))
#print "microTransform is ON."
else:
cmds.manipRotateContext('Rotate', edit=True, mode=self.rotationOrientMode)
self.removeMicroTransform()
#print "microTransform is OFF."
def changedMicroTransform(self, msg, mplug, otherMplug, clientData):
#cmds.undoInfo(stateWithoutFlush=False)
if om.MNodeMessage.kAttributeSet == (om.MNodeMessage.kAttributeSet & msg) and not om.MGlobal.isUndoing() and not om.MGlobal.isRedoing():
nodeName, attrName = mplug.name().split('.')
#print "changed!"
if attrName not in self.attributes: return
nodeAttr = mplug.name()
val = cmds.getAttr(nodeAttr)
mtValue = self.microTransformValues["%s_%s"%(nodeName, attrName)]
if str(val) != str(mtValue):
#timer
if "%s"%nodeName not in self.microTransformStartTimer:
self.microTransformStartTimer["%s"%nodeName] = cmds.timerX()
microTransformTimer = cmds.timerX(startTime=self.microTransformStartTimer["%s"%nodeName])
self.microTransformStartTimer["%s"%nodeName] = cmds.timerX()
microTransformTimer *= 50
if microTransformTimer == 0: microTransformTimer = 1000
mult = self.multiplier/microTransformTimer
if mult >= self.multiplier: mult = self.multiplier
self.undoChunkFn("open")
#print "changedMicroTransform"
if type(val) is list:
temp = ()
for n, loopVal in enumerate(val[0]):
dif = loopVal-mtValue[0][n]
temp = temp + (mtValue[0][n]+(dif*mult),)
newVal = [temp]
self.microTransformValues["%s_%s"%(nodeName, attrName)] = newVal
#xyz
self.microTransformValues["%s_%sX"%(nodeName, attrName)] = newVal[0][0]
self.microTransformValues["%s_%sY"%(nodeName, attrName)] = newVal[0][1]
self.microTransformValues["%s_%sZ"%(nodeName, attrName)] = newVal[0][2]
eval("cmds.setAttr(nodeAttr, %s,%s,%s)"%(newVal[0][0],newVal[0][1],newVal[0][2]))
#xyz
cmds.setAttr("%sX"%nodeAttr, newVal[0][0])
cmds.setAttr("%sY"%nodeAttr, newVal[0][1])
cmds.setAttr("%sZ"%nodeAttr, newVal[0][2])
else:
dif = val-mtValue
newVal = mtValue+(dif*mult)
self.microTransformValues["%s_%s"%(nodeName, attrName)] = newVal
#xyz inverse
val = cmds.getAttr("%s.%s"%(nodeName, attrName[:-1]))
self.microTransformValues["%s_%s"%(nodeName, attrName[:-1])] = val
cmds.setAttr(nodeAttr, newVal)
else:
self.microTransformValues["%s_%s"%(nodeName, attrName)] = cmds.getAttr(nodeAttr)
if type(val) is list:
valX = cmds.getAttr("%s.%sX"%(nodeName, attrName))
valY = cmds.getAttr("%s.%sY"%(nodeName, attrName))
valZ = cmds.getAttr("%s.%sZ"%(nodeName, attrName))
#xyz
self.microTransformValues["%s_%sX"%(nodeName, attrName)] = valX
self.microTransformValues["%s_%sY"%(nodeName, attrName)] = valY
self.microTransformValues["%s_%sZ"%(nodeName, attrName)] = valZ
else:
#xyz inverse
val = cmds.getAttr("%s.%s"%(nodeName, attrName[:-1]))
self.microTransformValues["%s_%s"%(nodeName, attrName[:-1])] = val
#cmds.undoInfo(stateWithoutFlush=True)
def release(self):
self.undoChunkFn("close")
self.updateValues()
self.microTransformStartTimer = {}
def undoChunkFn(self, openClose):
if openClose == "open":
if self.undoChunk == "closed":
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
self.undoChunk = "open"
#print "openChunk"
else:
if self.undoChunk == "open":
cmds.undoInfo(closeChunk=True)
self.undoChunk = "closed"
#print "closeChunk"
def addMicroTransform(self):
self.updateValues()
cmds.undoInfo(stateWithoutFlush=False)
sel = cmds.ls(selection=True)
if G.MT_lastSel:
graphEditorFocus = cmds.getPanel(withFocus=True) == "graphEditor1"
if sel == G.MT_lastSel and graphEditorFocus:
cmds.undoInfo(stateWithoutFlush=True)
return
G.MT_lastSel = sel
if len(sel) <= 0:
cmds.undoInfo(stateWithoutFlush=True)
return
self.removeMicroTransform()
G.microTransformIds = []
self.undoChunk = "closed"
MSelectionList = om.MSelectionList()
om.MGlobal.getActiveSelectionList(MSelectionList)
node = om.MObject()
for n, loopSel in enumerate(sel):
MSelectionList.getDependNode(n, node)
clientData = None
G.microTransformIds.append(om.MNodeMessage.addAttributeChangedCallback(node, self.changedMicroTransform, clientData))
cmds.undoInfo(stateWithoutFlush=True)
def removeMicroTransform(self):
try:
for loopId in G.microTransformIds:
om.MNodeMessage.removeCallback(loopId)
except: pass
G.microTransformIds = None
def updateValues(self):
#print "updateValues"
self.microTransformValues = {}
sel = cmds.ls(selection=True)
for loopSel in sel:
for loopAttr in self.attributes:
val = cmds.getAttr("%s.%s"%(loopSel, loopAttr))
self.microTransformValues["%s_%s"%(loopSel, loopAttr)] = val
def setMultiplier(self, option):
name = None
for loopOption in self.multiplierValues:
if loopOption["name"] == option:
value = loopOption["value"]
name = loopOption["name"]
if not name: #in case file is corrupt
self.setMultiplier(self.defaultMultiplier)
return
self.multiplier = value
aToolsMod.saveInfoWithUser("userPrefs", "microTransform", name)
def getMultiplier(self):
name = aToolsMod.loadInfoWithUser("userPrefs", "microTransform")
if name == None: name = self.defaultMultiplier
return name
def popupMenu(self, *args):
menu = cmds.popupMenu()
cmds.popupMenu(menu, edit=True, postMenuCommand=self.populateMenu, postMenuCommandOnce=True)
def populateMenu(self, menu, *args):
cmds.radioMenuItemCollection(parent=menu)
for loopOption in self.multiplierValues:
radioSelected = (self.multiplier == loopOption["value"])
option = loopOption["name"]
cmds.menuItem (label=utilMod.toTitle(loopOption["name"]), radioButton=radioSelected, command=lambda x, option=option, *args: self.setMultiplier(option), parent=menu)

View File

@ -0,0 +1,319 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from maya import mel
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod
from aTools.commonMods import utilMod
from aTools.commonMods import animMod
from aTools.commonMods import aToolsMod
class Mirror(object):
utilMod.killScriptJobs("G.mirrorScriptJobs")
def __init__(self):
self.INVERT_RULES_PREFS = [{ "name":"invertRulesMirrorObjsTranslateX",
"default":True
},{ "name":"invertRulesMirrorObjsTranslateY",
"default":False
},{ "name":"invertRulesMirrorObjsTranslateZ",
"default":False
},{ "name":"invertRulesMirrorObjsRotateX",
"default":False
},{ "name":"invertRulesMirrorObjsRotateY",
"default":False
},{ "name":"invertRulesMirrorObjsRotateZ",
"default":False
},{ "name":"invertRulesCenterObjsTranslateX",
"default":True
},{ "name":"invertRulesCenterObjsTranslateY",
"default":False
},{ "name":"invertRulesCenterObjsTranslateZ",
"default":False
},{ "name":"invertRulesCenterObjsRotateX",
"default":False
},{ "name":"invertRulesCenterObjsRotateY",
"default":True
},{ "name":"invertRulesCenterObjsRotateZ",
"default":True
}]
def start(self):
mod = uiMod.getModKeyPressed()
if mod == "shift":
self.selectMirrorObjs(True)
elif mod == "ctrl":
self.selectMirrorObjs(False)
else:
sel = cmds.ls(selection=True)
if sel: self.applyMirror()
else: self.toggleAutoSelectMirrorObjects()
def popupMenu(self):
cmds.popupMenu()
cmds.menuItem("autoSelectMirrorObjectsMenu", label='Auto Select Mirror Objects' , checkBox=False, command=self.toggleAutoSelectMirrorObjects)
cmds.menuItem("invertRulesMenu", subMenu=True, label='Invert Rules' , tearOff=True)
for n, loopPref in enumerate(self.INVERT_RULES_PREFS):
name = loopPref["name"]
if n == 6: cmds.menuItem( divider=True )
cmds.menuItem('%sMenu'%name, label=utilMod.toTitle(name[11:]), command=lambda x, name=name, *args: aToolsMod.setPref(name, self.INVERT_RULES_PREFS), checkBox=aToolsMod.getPref(name, self.INVERT_RULES_PREFS))
cmds.menuItem( divider=True )
cmds.menuItem("loadDefaultsInvertRulesMenu", label="Load Defaults", command=lambda *args:utilMod.loadDefaultPrefs(self.INVERT_RULES_PREFS))
cmds.setParent( '..', menu=True )
cmds.menuItem( divider=True )
cmds.menuItem(label="Unselect Right", command=lambda *args: self.unselectMirrorObjs("right"))
cmds.menuItem(label="Unselect Left", command=lambda *args: self.unselectMirrorObjs("left"))
cmds.menuItem(label="Unselect Center", command=lambda *args: self.unselectMirrorObjs("center"))
cmds.menuItem( divider=True )
cmds.menuItem(label="Paste And Invert Cycle", command=lambda *args: self.applyMirror(pasteAndCycle=True))
def toggleAutoSelectMirrorObjects(self, *args):
onOff = not cmds.menuItem("autoSelectMirrorObjectsMenu", query=True , checkBox=True)
if args: onOff = not onOff #if checkbox pressed
if onOff: cmds.iconTextButton("mirrorBtn", edit=True, image=uiMod.getImagePath("specialTools_mirror_active"), highlightImage= uiMod.getImagePath("specialTools_mirror_active"))
else: cmds.iconTextButton("mirrorBtn", edit=True, image=uiMod.getImagePath("specialTools_mirror"), highlightImage= uiMod.getImagePath("specialTools_mirror copy"))
self.setAutoSelectMirrorObjects(onOff)
if not args:cmds.menuItem("autoSelectMirrorObjectsMenu", edit=True , checkBox=onOff)
def setAutoSelectMirrorObjects(self, onOff):
utilMod.killScriptJobs("G.mirrorScriptJobs")
if onOff:
self.autoSelectMirrorObjects()
G.mirrorScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.autoSelectMirrorObjects )))
def autoSelectMirrorObjects(self):
sel = cmds.ls(selection=True)
if sel: self.selectMirrorObjs(add=True, lastObj=sel[-1])
def getInvertRules(self):
invertRules = []
for loopPref in self.INVERT_RULES_PREFS:
name = loopPref["name"]
pref = aToolsMod.getPref(name, self.INVERT_RULES_PREFS)
mode = name[11:]
if pref: invertRules.append(mode)
return invertRules
def mirrorInvert(self, aCurve, isCenterCurve, invertRules):
transRot =["Translate", "Rotate"]
modes = ["x", "y", "z"]
value = 1
if isCenterCurve:
objType = "Center"
else:
objType = "Mirror"
for loopRule in invertRules:
for loopMode in modes:
for loopTransRot in transRot:
rule = "%sObjs%s%s"%(objType, loopTransRot, loopMode.title())
if loopRule == rule:
if eval("animMod.isNode%s('%s', '%s')"%(loopTransRot, aCurve, loopMode)):
value = -1
return value
def unselectMirrorObjs(self, side):
objects = animMod.getObjsSel()
if side == "center":
objs = animMod.getMirrorObjs(objects, side="left")
objects.extend(objs)
objs.extend(animMod.getMirrorObjs(objects, side="right"))
objects.extend(objs)
objs.extend(animMod.getMirrorObjs(objects, side="left"))
centerObjs = [loopObj for loopObj in objects if loopObj not in objs and loopObj and cmds.objExists(loopObj)]
if len(centerObjs) >0: cmds.select(centerObjs, deselect=True)
else:
if side == "left": side = "right"
elif side == "right": side = "left"
objs = animMod.getMirrorObjs(objects, side=side)
objs = [loopObj for loopObj in objs if loopObj and cmds.objExists(loopObj)]
if len(objs) > 0: cmds.select(objs, deselect=True)
def selectMirrorObjs(self, add, lastObj=None):
objects = animMod.getObjsSel()
mirrorObjs = animMod.getMirrorObjs(objects)
sel = []
if mirrorObjs:
for n, loopObj in enumerate(mirrorObjs):
if loopObj:
if cmds.objExists(loopObj): sel.append(loopObj)
else:
#central controller
sel.append(objects[n])
if len(sel) >0:
if lastObj:
cmds.select(sel, addFirst=add)
else:
cmds.select(sel, add=add)
def applyMirror(self, pasteAndCycle=False):
cmds.waitCursor(state=True)
range = animMod.getTimelineRange()
range[1] = int(range[1])
total = range[1]-range[0]
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
invertRules = self.getInvertRules()
if animCurves:
status = "aTools - Applying mirror..."
utilMod.startProgressBar(status)
totalSteps = len(animCurves)
firstStep = 0
thisStep = 0
estimatedTime = None
startChrono = None
mirrorCurves = animMod.getMirrorObjs(animCurves)
keyValues = animMod.getTarget("keyValues", animCurves, getFrom)
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
currValues = animMod.getTarget("currValues", animCurves, getFrom)
keysIndexSel = animMod.getTarget("keysIndexSel", animCurves, getFrom)
keyTangentsAngle = animMod.getTarget("keyTangentsAngle", animCurves, getFrom)
keyTangentsType = animMod.getTarget("keyTangentsType", animCurves, getFrom)
currTime = cmds.currentTime(query=True)
if keysIndexSel:
#create dummy key
#objects = animMod.getObjsSel()
#mirrorObjs = animMod.getMirrorObjs(objects)
#animMod.createDummyKey(mirrorObjs)
for thisStep, aCurve in enumerate(animCurves):
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
mCurve = mirrorCurves[thisStep]
isCenterCurve = (mCurve == None)
mirrorInvertValue = self.mirrorInvert(aCurve, isCenterCurve, invertRules)
if mCurve and cmds.objExists(mCurve):
tCurve = mCurve
else:
tCurve = aCurve
if not cmds.objExists(tCurve): continue
animMod.createDummyKey([tCurve])
if len(keysIndexSel[thisStep]) > 0:
#delete keys
cmds.cutKey(tCurve, time=(keyTimes[thisStep][keysIndexSel[thisStep][0]],keyTimes[thisStep][keysIndexSel[thisStep][-1]]), clear=True)
for key in keysIndexSel[thisStep]:
keyValue = keyValues[thisStep][key] * mirrorInvertValue
inTangAngleValue = keyTangentsAngle[thisStep][key][0] * mirrorInvertValue
outTangAngleValue = keyTangentsAngle[thisStep][key][1] * mirrorInvertValue
#apply keys
if pasteAndCycle:
t = keyTimes[thisStep][key] + (total/2.)
if t == range[1]:
#repeat key at first frame
t1 = t-total
time = (t1,t1)
cmds.setKeyframe(tCurve, time=time, value=keyValue)
cmds.keyTangent(tCurve, time=time, inAngle=inTangAngleValue, outAngle=outTangAngleValue)
cmds.keyTangent(tCurve, time=time, inTangentType=keyTangentsType[thisStep][key][0], outTangentType=keyTangentsType[thisStep][key][1])
elif t > range[1]:
#fist half
t -= total
time = (t,t)
else:
time = (keyTimes[thisStep][key],keyTimes[thisStep][key])
cmds.setKeyframe(tCurve, time=time, value=keyValue)
cmds.keyTangent(tCurve, time=time, inAngle=inTangAngleValue, outAngle=outTangAngleValue)
cmds.keyTangent(tCurve, time=time, inTangentType=keyTangentsType[thisStep][key][0], outTangentType=keyTangentsType[thisStep][key][1])
else: #no keys#invert translate x
keyValue = currValues[thisStep] * mirrorInvertValue
#apply keys
cmds.setKeyframe(tCurve, time=(currTime,currTime), value=keyValue)
animMod.deleteDummyKey([tCurve])
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
#delete dummy key
#animMod.deleteDummyKey(mirrorObjs)
self.selectMirrorObjs(False)
utilMod.setProgressBar(endProgress=True)
animMod.refresh()
cmds.waitCursor(state=False)

View File

@ -0,0 +1,303 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Modified: Michael Klimenko
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from maya import mel
from aTools.commonMods import uiMod
from aTools.commonMods import utilMod
from aTools.commonMods import animMod
from aTools.commonMods import aToolsMod
class SpaceSwitch(object):
def popupMenu(self):
cmds.popupMenu(postMenuCommand=self.populateMenu, button=1)
def populateMenu(self, menu, *args):
uiMod.clearMenuItems(menu)
tokenCustomDivider = False
selObjects = cmds.ls(selection=True)
if not selObjects: return
channels = animMod.getAllChannels()
channelList = {}
tokenList = []
for n, loopObjectChannel in enumerate(channels):
obj = selObjects[n]
if loopObjectChannel:
for loopChannel in loopObjectChannel:
tokens = animMod.getTokens(obj, loopChannel)
if tokens and len(tokens) > 1:
if loopChannel not in channelList: channelList[loopChannel] = {"objects":[], "tokens":[]}
channelList[loopChannel]["objects"].append(obj)
channelList[loopChannel]["tokens"].append(tokens)
for loopChannelList in channelList:
newMenu = cmds.menuItem(subMenu=True, label=utilMod.toTitle(loopChannelList), parent=menu)
objects = channelList[loopChannelList]["objects"]
tokens = channelList[loopChannelList]["tokens"]
mergedTokens = utilMod.mergeLists(tokens)
tokenDict = []
for loopMergedTokens in mergedTokens:
tokenDict.append({"token":loopMergedTokens, "objects":[]})
for n, loopObject in enumerate(objects):
t = tokens[n]
if loopMergedTokens in t:
tokenDict[-1]["objects"].append(loopObject)
cmds.radioMenuItemCollection(parent=menu)
for n, loopTokenDict in enumerate(tokenDict):
tokenCustomDivider = True
token = loopTokenDict["token"]
objects = loopTokenDict["objects"]
selectedList = [cmds.getAttr("%s.%s"%(loopObj, loopChannelList)) for loopObj in objects]
radioSelected = False
if len(set(selectedList)) == 1:
if selectedList[0] == n:
radioSelected = True
cmds.menuItem(label=utilMod.toTitle(token), radioButton=radioSelected, parent=newMenu, command=lambda x, objects=objects, channel=loopChannelList, token=token, *args:self.spaceSwitch([objects, channel, token]))
#ALL KEYS
cmds.menuItem( divider=True, parent=newMenu)
newMenu = cmds.menuItem(subMenu=True, label='All Keys', parent=newMenu)
cmds.radioMenuItemCollection(parent=newMenu)
for n, loopTokenDict in enumerate(tokenDict):
token = loopTokenDict["token"]
objects = loopTokenDict["objects"]
selectedList = [cmds.getAttr("%s.%s"%(loopObj, loopChannelList)) for loopObj in objects]
radioSelected = False
if len(set(selectedList)) == 1:
if selectedList[0] == n:
radioSelected = True
cmds.menuItem(label=utilMod.toTitle(token), radioButton=radioSelected, parent=newMenu, command=lambda x, objects=objects, channel=loopChannelList, token=token, *args:self.spaceSwitch([objects, channel, token], all=True))
# CUSTOM SWITCH
allCustomSwitch = aToolsMod.loadInfoWithUser("spaceSwitch", "customSwitch") or []
channelboxSelObjs = animMod.channelBoxSel()
if channelboxSelObjs:
obj = ".".join(channelboxSelObjs[0].split(".")[:-1])
selectedSwitch = [loopAttr.split(".")[-1] for loopAttr in channelboxSelObjs if utilMod.isDynamic(obj, loopAttr.split(".")[-1])]
if len(selectedSwitch) > 0 and selectedSwitch not in allCustomSwitch:
allCustomSwitch.append(selectedSwitch)
aToolsMod.saveInfoWithUser("spaceSwitch", "customSwitch", allCustomSwitch)
# populate menu
if len(allCustomSwitch) > 0:
divider = False
customSwitchesAdded = []
customSwitchesMenu = []
for loopObj in selObjects:
for loopCustomSwitch in sorted(allCustomSwitch, key=len, reverse=True):
if len(loopCustomSwitch) == 0: continue
switchName = utilMod.getNameSpace([loopObj])[1][0].split(".")[0]
exit = False
for loopAttr in loopCustomSwitch:
objAttr = "%s.%s"%(loopObj, loopAttr)
if not cmds.objExists(objAttr):
exit = True
break
if exit: continue
customSwitchesMenu.append({"objects":[loopObj], "switches":loopCustomSwitch})
for loopMenu in customSwitchesMenu[:-1]:
if loopObj in loopMenu["objects"] and len(loopCustomSwitch) < len(loopMenu["switches"]) and utilMod.listIntersection(loopMenu["switches"], loopCustomSwitch) == loopCustomSwitch:
customSwitchesMenu.pop()
break
if loopCustomSwitch == loopMenu["switches"]:
loopMenu["objects"].append(loopObj)
customSwitchesMenu.pop()
break
for loopSwitchMenu in customSwitchesMenu:
objects = loopSwitchMenu["objects"]
switches = loopSwitchMenu["switches"]
switchName = ", ".join(list(set(utilMod.getNameSpace(objects)[1])))
if not divider and tokenCustomDivider: divider = cmds.menuItem(divider=True, parent=menu)
cmds.radioMenuItemCollection(parent=menu)
newMenu = cmds.menuItem(subMenu=True, label=switchName, parent=menu)
radioSelected = []
for loopCustomSwitchAttr in switches:
switchAttr = loopCustomSwitchAttr.split(".")[-1]
objAttr = "%s.%s"%(objects[0], switchAttr)
minValue = cmds.addAttr(objAttr, query=True, minValue=True)
maxValue = cmds.addAttr(objAttr, query=True, maxValue=True)
currValue = cmds.getAttr(objAttr)
radioSelected.append((currValue == maxValue))
cmds.menuItem(label=switchAttr, radioButton=radioSelected[-1], parent=newMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], mode="custom"))
switchAttr = "message"
radioSelected = (list(set(radioSelected)) == [False])
cmds.menuItem(label="None", radioButton=radioSelected, parent=newMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], mode="custom"))
#ALL KEYS
cmds.menuItem( divider=True, parent=newMenu)
allMenu = cmds.menuItem(subMenu=True, label='All Keys', parent=newMenu)
radioSelected = []
cmds.radioMenuItemCollection(parent=menu)
for loopCustomSwitchAttr in switches:
switchAttr = loopCustomSwitchAttr.split(".")[-1]
objAttr = "%s.%s"%(objects[0], switchAttr)
minValue = cmds.addAttr(objAttr, query=True, minValue=True)
maxValue = cmds.addAttr(objAttr, query=True, maxValue=True)
currValue = cmds.getAttr(objAttr)
radioSelected.append((currValue == maxValue))
cmds.menuItem(label=switchAttr, radioButton=radioSelected[-1], parent=allMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], all=True, mode="custom"))
switchAttr = "message"
radioSelected = (list(set(radioSelected)) == [False])
cmds.menuItem(label="None", radioButton=radioSelected, parent=allMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], all=True, mode="custom"))
#DELETE
cmds.menuItem(label="Remove", parent=newMenu, command=lambda x, switches=switches, *args:self.removeCustomSwitch(switches))
def removeCustomSwitch(self, switch):
allCustomSwitch = aToolsMod.loadInfoWithUser("spaceSwitch", "customSwitch") or []
allCustomSwitch.remove(switch)
aToolsMod.saveInfoWithUser("spaceSwitch", "customSwitch", allCustomSwitch)
def spaceSwitch(self, args, all=False, mode="token"):
cmds.refresh(suspend=True)
if mode == "token": switch = self.spaceSwitchToken
elif mode == "custom": switch = self.spaceSwitchCustom
objects = args[0]
attr = args[1]
currSel = cmds.ls(selection=True)
currFrame = cmds.currentTime(query=True)
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves:
if all: keysSel = animMod.getTarget("keyTimes", animCurves, getFrom)
else: keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
keysSel = utilMod.mergeLists(keysSel)
if keysSel == []:
keysSel = [currFrame]
else:
keysSel = [currFrame]
frames = keysSel
for loopObj in currSel:
if loopObj not in objects: continue
if not cmds.objExists("%s.%s"%(loopObj, attr)):continue
animMod.createDummyKey([loopObj])
getCurves = animMod.getAnimCurves(True)
animCurves = getCurves[0]
animMod.deleteDummyKey([loopObj])
for loopFrame in frames:
cmds.currentTime(loopFrame)
matrix = cmds.xform(loopObj, query=True, ws=True, matrix=True)
rotation = cmds.xform(loopObj, query=True, ws=True, rotation=True)
switch(loopObj, args)
cmds.xform(loopObj, ws=True, matrix=matrix)
cmds.xform(loopObj, ws=True, rotation=rotation)
animMod.eulerFilterCurve(animCurves)
cmds.currentTime(currFrame)
cmds.refresh(suspend=False)
def spaceSwitchCustom(self, obj, args):
objects, attr, switchAttList = args
objAttr = "%s.%s"%(obj, attr)
for loopAttr in switchAttList:
loopObjAttr = "%s.%s"%(obj, loopAttr)
minValue = cmds.addAttr(loopObjAttr, query=True, minValue=True)
maxValue = cmds.addAttr(loopObjAttr, query=True, maxValue=True)
value = minValue if objAttr != loopObjAttr else maxValue
cmds.setAttr(loopObjAttr, value)
def spaceSwitchToken(self, obj, args):
objects, attr, switchTo = args
enumTokens = animMod.getTokens(obj, attr)
value = 0
switchToNum = None
for loopToken in enumTokens:
splitValue = loopToken.split("=")
if splitValue:
if len(splitValue) > 1:
loopToken = splitValue[0]
value = eval(splitValue[1])
if switchTo == loopToken:
switchToNum = value
break
value += 1
if switchToNum != None:
cmds.setAttr("%s.%s"%(obj, attr), switchToNum)

View File

@ -0,0 +1,189 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from maya import mel
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod
from aTools.commonMods import utilMod
from aTools.commonMods import animMod
from aTools.commonMods import aToolsMod
import maya.OpenMaya as om
#============================================================================================================
class TempCustomPivot(object):
def __init__(self):
self.STORE_NODE = "tempCustomPivot"
self.CONSTRAINTS = "constraintObjects"
self.LOCATORS = "locatorObjects"
self.CTRLS = "ctrlsObjects"
self.CURRENTFRAME = "currentFrame"
self.sel = []
self.deniedCtx = ["dragAttrContext", "manipMoveContext", "manipRotateContext", "manipScaleContext"]
self.clear()
def popupMenu(self, *args):
cmds.popupMenu()
cmds.menuItem(label="Clear temporary custom pivots", command=self.clear)
def create(self, *args):
img = cmds.iconTextButton("TempCustomPivotBtn", query=True, image=True)
onOff = (img[-10:-4] == "active")
if onOff:
self.clear()
cmds.select(self.sel)
return
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
self.clear()
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves:
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
self.sel = cmds.ls(selection=True)
if not self.sel: return
cmds.iconTextButton("TempCustomPivotBtn", edit=True, image= uiMod.getImagePath("specialTools_create_temp_custom_pivot_active"), highlightImage= uiMod.getImagePath("specialTools_create_temp_custom_pivot_active"))
targetObj = self.sel[-1]
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.CTRLS, self.sel)
currentFrame = cmds.currentTime(query=True)
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.CURRENTFRAME, currentFrame)
locators = []
for loopSel in self.sel:
nameSpace = utilMod.getNameSpace([loopSel])
loopSelName = "%s_%s"%(nameSpace[0][0], nameSpace[1][0])
locatorName = "tempCustomPivot_%s"%loopSelName
locator = animMod.createNull(locatorName)
locators.append(locator)
G.aToolsBar.align.align([locator], loopSel)
locatorGroup = "tempCustomPivot_group"
animMod.group(name=locatorGroup)
G.aToolsBar.align.align([locatorGroup], targetObj)
with G.aToolsBar.createAToolsNode: cmds.parent(locators, locatorGroup)
cmds.select(locatorGroup, replace=True)
locators.append(locatorGroup)
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.LOCATORS, locators)
#parent ctrls to locator
constraints = ["%s_tempCustomPivot_constraint"%loopConstraint for loopConstraint in self.sel]
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.CONSTRAINTS, constraints)
for n, loopSel in enumerate(self.sel):
with G.aToolsBar.createAToolsNode: cmds.parentConstraint(locators[n], loopSel, name=constraints[n], maintainOffset=True)
constraintNode = "%s.blendParent1"%loopSel
if not cmds.objExists(constraintNode): continue
cmds.setKeyframe(constraintNode)
if keyTimes:
for loopTime in keyTimes[0]:
cmds.setKeyframe("%s.tx"%locatorGroup, time=(loopTime,loopTime))
if loopTime != currentFrame:
cmds.setKeyframe(constraintNode, time=(loopTime,loopTime), value=0)
#enter edit mode
cmds.setToolTo(cmds.currentCtx())
cmds.ctxEditMode()
#scriptjob
cmds.scriptJob(runOnce = True, killWithScene = True, event =('SelectionChanged', self.scriptJob_SelectionChanged))
def scriptJob_SelectionChanged(self):
self.clear()
cmds.undoInfo(closeChunk=True)
def clear(self, *args):
if cmds.iconTextButton("TempCustomPivotBtn", query=True, exists=True):
cmds.iconTextButton("TempCustomPivotBtn", edit=True, image= uiMod.getImagePath("specialTools_create_temp_custom_pivot"), highlightImage= uiMod.getImagePath("specialTools_create_temp_custom_pivot copy"))
cmds.refresh(suspend=True)
currFrame = cmds.currentTime(query=True)
loadConstraints = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.CONSTRAINTS)
loadLocators = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.LOCATORS)
loadCtrls = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.CTRLS)
currentFrame = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.CURRENTFRAME)
#exit edit mode
if cmds.currentCtx() not in self.deniedCtx: cmds.setToolTo(cmds.currentCtx())
if currentFrame:
cmds.currentTime(eval(currentFrame))
#get values
"""
translation = []
rotation = []
if loadCtrls:
ctrlObjs = eval(loadCtrls)
for loopCtrl in ctrlObjs:
translation.append(cmds.xform(loopCtrl, query=True, ws=True, rotatePivot=True))
rotation.append(cmds.xform(loopCtrl, query=True, ws=True, rotation=True))
"""
if loadConstraints:
constraintObjs = eval(loadConstraints)
for loopConstraint in constraintObjs:
if cmds.objExists(loopConstraint): cmds.delete(loopConstraint)
if loadCtrls and loadLocators:
locatorObjs = eval(loadLocators)
ctrlObjs = eval(loadCtrls)
for n, loopCtrl in enumerate(ctrlObjs):
if cmds.objExists(loopCtrl) and cmds.objExists(locatorObjs[n]):
G.aToolsBar.align.align([loopCtrl], locatorObjs[n])
for loopLocator in locatorObjs:
if cmds.objExists(loopLocator): cmds.delete(loopLocator)
cmds.currentTime(currFrame)
cmds.refresh(suspend=False)

View File

@ -0,0 +1,347 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Modified: Michael Klimenko
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from maya import mel
from maya import OpenMaya
from maya import OpenMayaAnim
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod
from aTools.commonMods import utilMod
from aTools.commonMods import animMod
class TransformAll(object):
utilMod.killScriptJobs("G.transformAllScriptJobs")
def __init__(self):
G.deferredManager.removeFromQueue("transformAll")
G.deferredManager.removeFromQueue("TA_blinking")
if G.aToolsBar.transformAll: return
G.aToolsBar.transformAll = self
self.currentValues = {}
self.allValues = {}
self.range = None
self.onOff = False
self.blendRangeMode = False
self.blendImg = ""
G.TA_messages = G.TA_messages or {"anim":[], "node":[], "scene":[]}
self.killJobs()
def blinkingButton(self, onOff):
if onOff: G.aToolsBar.timeoutInterval.setInterval(self.toggleButtonActive, .3, id="TA_blinking")
else: G.aToolsBar.timeoutInterval.stopInterval("TA_blinking")
def toggleButtonActive(self):
onOff = "active" in cmds.iconTextButton("transformAllBtn", query=True, image=True)
self.setButtonImg(not onOff)
def popupMenu(self, *args):
cmds.popupMenu ()
cmds.menuItem ("blendRangeModeMenu", label="Blend Range Mode", checkBox=self.blendRangeMode, command=self.setBlendRangeMode)
def setBlendRangeMode(self, *args):
self.blendRangeMode = args[0]
if self.blendRangeMode: self.blendImg = "_blend"
else: self.blendImg = ""
self.setButtonImg(self.onOff)
self.warn()
def setButtonImg(self, onOff):
if onOff:
cmds.iconTextButton("transformAllBtn", edit=True, image=uiMod.getImagePath("specialTools_transform_all%s_active"%self.blendImg), highlightImage= uiMod.getImagePath("specialTools_transform_all%s_active"%self.blendImg))
else:
cmds.iconTextButton("transformAllBtn", edit=True, image=uiMod.getImagePath("specialTools_transform_all%s"%self.blendImg), highlightImage= uiMod.getImagePath("specialTools_transform_all%s copy"%self.blendImg))
def switch(self):
mod = uiMod.getModKeyPressed()
if mod == "ctrl":
self.setBlendRangeMode(not self.blendRangeMode)
if self.onOff: self.onOff = False
self.onOff = (not self.onOff)
self.setButtonImg(self.onOff)
self.blinkingButton(self.onOff)
self.setMode(self.onOff)
def killJobs(self):
G.deferredManager.removeFromQueue("transformAll")
self.animCurvesToSend = []
self.removeMessages()
utilMod.killScriptJobs("G.transformAllScriptJobs")
def setMode(self, onOff):
self.killJobs()
if onOff:
#self.allAnimCurves = utilMod.getAllAnimCurves()
self.allValues = {}
self.setRange()
self.updateCurrentValues()
utilMod.deselectTimelineRange()
G.transformAllScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('timeChanged', self.updateCurrentValues )))
G.transformAllScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.updateCurrentValues )))
self.warn()
else:
cmds.warning("Transform All is OFF.")
def addAnimMessages(self):
self.removeMessages()
G.TA_messages["anim"].append(OpenMayaAnim.MAnimMessage.addAnimCurveEditedCallback(self.sendToSetValues))
def removeMessages(self):
try:
for loopId in G.TA_messages["anim"]:
OpenMayaAnim.MAnimMessage.removeCallback(loopId)
except: pass
G.TA_messages["anim"] = []
def sendToSetValues(self, *args):
curveMsg = args[0]
animCurves = [OpenMaya.MFnDependencyNode(curveMsg[n]).name() for n in range(curveMsg.length())]
if OpenMaya.MGlobal.isUndoing() or OpenMaya.MGlobal.isRedoing():
self.updateCurrentValues(animCurves)
return
self.animCurvesToSend.extend(animCurves)
animCurves = list(set(self.animCurvesToSend))
G.deferredManager.removeFromQueue("transformAll")
function = lambda *args:self.setValues(animCurves)
G.deferredManager.sendToQueue(function, 1, "transformAll")
def getRange(self):
animCurves = cmds.keyframe(query=True, name=True, selected=True)
if animCurves:
keysSel = animMod.getTarget("keysSel", animCurves, "graphEditor")
keysSel = utilMod.mergeLists(keysSel)
range = [min(keysSel), max(keysSel)]
else:
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
range = cmds.timeControl(G.playBackSliderPython, query=True, rangeArray=True)
range[1] -= 1
return range
def getCurrentValues(self, animCurves):
if animCurves:
result = {"keyValues":[], "timeValues":[]}
for loopCurve in animCurves:
time = cmds.keyframe(loopCurve, selected=True, query=True, timeChange=True)
if time:
time = [time[0], time[-1]]
result["keyValues"].append(cmds.keyframe(loopCurve, query=True, time=(time[0],time[-1]), valueChange=True))
else:
time = cmds.currentTime(query=True); time = [time, time]
result["keyValues"].append(cmds.keyframe(loopCurve, query=True, eval=True, valueChange=True))
result["timeValues"].append(time)
return result
def updateCurrentValues(self, animCurves=None, *args):
cmds.undoInfo(stateWithoutFlush=False)
self.removeMessages()
if not animCurves: animCurves = utilMod.getAllAnimCurves(selection=True)
if not animCurves: return
for loopCurve in animCurves:
#if loopCurve in self.allAnimCurves:
self.currentValues[loopCurve] = self.getCurrentValues([loopCurve])["keyValues"][0]
self.allValues[loopCurve] = animMod.getTarget("keyValues", [loopCurve])[0]
self.addAnimMessages()
cmds.undoInfo(stateWithoutFlush=True)
def setValues(self, animCurves):
cmds.refresh(suspend=True)
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
self.removeMessages()
self.warn()
values = self.getCurrentValues(animCurves)
newKeyValues = values["keyValues"]
timeValues = values["timeValues"]
offsetValues = []
offsetPercentsA = []
offsetPercentsB = []
pivotAs = []
pivotBs = []
self.animCurvesToSend = []
for n, loopCurve in enumerate(animCurves):
oldVal = self.currentValues[loopCurve][0]
newVal = newKeyValues[n][0]
if self.blendRangeMode:
pivotA = cmds.keyframe(loopCurve, query=True, eval=True, time=(self.range[0],self.range[0]), valueChange=True)[0]
pivotB = cmds.keyframe(loopCurve, query=True, eval=True, time=(self.range[1],self.range[1]), valueChange=True)[0]
if oldVal == pivotA:
pivotA = newVal
offsetPercentA = 0
else:
offsetPercentA = float((newVal-pivotA)/(oldVal-pivotA))
if oldVal == pivotB:
pivotB = newVal
offsetPercentB = 0
else:
offsetPercentB = float((newVal-pivotB)/(oldVal-pivotB))
offsetPercentsA.append(offsetPercentA)
offsetPercentsB.append(offsetPercentB)
pivotAs.append(pivotA)
pivotBs.append(pivotB)
else:
offsetVal = newVal - oldVal
offsetValues.append(offsetVal)
#reset change
cmds.undoInfo(stateWithoutFlush=False)
for loopCurve in list(self.allValues.keys()):
if loopCurve in animCurves:
valueChange = self.allValues[loopCurve]
for n, loopValue in enumerate(valueChange):
cmds.keyframe(loopCurve, edit=True, index=(n,n), valueChange=loopValue)
#self.allValues[] = {}
cmds.undoInfo(stateWithoutFlush=True)
#set values for all keys
curvesToUpdate = []
if self.blendRangeMode:
for n, loopCurve in enumerate(animCurves):
time = timeValues[n]
timeOffsetA = .01
timeOffsetB = .01
if time[0] == self.range[0]: timeOffsetA = 0
if time[1] == self.range[1]: timeOffsetB = 0
if timeOffsetA != 0 and timeOffsetB != 0 and not self.range[0] < time[0] <= time[1] < self.range[1]:
cmds.warning("Selected keys out of range %s"%self.range)
continue
offsetPercentA = offsetPercentsA[n]
offsetPercentB = offsetPercentsB[n]
#if offsetPercentA != 0 or offsetPercentB != 0:
pivotA = pivotAs[n]
pivotB = pivotBs[n]
curvesToUpdate.append(loopCurve)
cmds.scaleKey(loopCurve, time=(self.range[0]+timeOffsetA, time[1]), valuePivot=pivotA, valueScale=offsetPercentA)
cmds.scaleKey(loopCurve, time=(time[1]+.01, self.range[1]-timeOffsetB), valuePivot=pivotB, valueScale=offsetPercentB)
else:
for n, loopCurve in enumerate(animCurves):
if offsetValues[n] != 0:
curvesToUpdate.append(loopCurve)
if self.range == "All Keys":
#pass
cmds.keyframe(loopCurve, edit=True, valueChange=offsetValues[n], relative=True)
else:
cmds.keyframe(loopCurve, edit=True, time=(self.range[0], self.range[1]), valueChange=offsetValues[n], relative=True)
self.updateCurrentValues(curvesToUpdate)
cmds.undoInfo(closeChunk=True)
cmds.refresh(suspend=False)
def warn(self):
if self.blendRangeMode:
blendTxt = "Blend Range Mode "
else:
blendTxt = ""
cmds.warning("Transform All %sis ON. Please remember to turn it OFF when you are done. Acting on range: %s"%(blendTxt, self.range))
def setRange(self):
self.range = self.getRange()
if self.range[1] - self.range[0] <= 1: #if only one key selected
if self.blendRangeMode: self.range = [cmds.playbackOptions(query=True, minTime=True), cmds.playbackOptions(query=True, maxTime=True)]
else: self.range = "All Keys"

View File

@ -0,0 +1,305 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds, mel
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod
from aTools.commonMods import animMod
from aTools.commonMods import utilMod
from aTools.commonMods import aToolsMod
STORE_NODE = "tUtilities"
CAMERA_ATTR = "cameraSelected"
RANGE_ATTR = "timelineRange"
G.TU_movie = None
G.TU_audioFile = None
G.TU_audioOffsetSec = None
class TUtilities_Gui(uiMod.BaseSubUI):
def createLayout(self):
cmds.rowLayout(numberOfColumns=5, parent=self.parentLayout)
timelineRange = TimelineRange()
cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("tUtilities_range"), highlightImage= uiMod.getImagePath("tUtilities_range copy"), command=timelineRange.setTimelineRange, annotation="Set timeline range\nRight click for options")
timelineRange.popupMenu()
cameraTools = CameraTools()
cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("tUtilities_camera"), highlightImage= uiMod.getImagePath("tUtilities_camera copy"), command=cameraTools.playblastCamera, annotation="Playblast camera\nRight click to select camera")
cameraTools.popupMenu()
# end createLayout
class TimelineRange(object):
def __init__(self):
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
def popupMenu(self, *args):
cmds.popupMenu("timelineRangeMenu", postMenuCommand=self.populateMenu)
def populateMenu(self, menu, *args):
uiMod.clearMenuItems(menu)
uiMod.clearMenuItems(menu)
#cmds.menuItem(label="Clear motion trails", command=self.clear)
cmds.radioMenuItemCollection(parent=menu)
currRange = [cmds.playbackOptions(query=True, minTime=True), cmds.playbackOptions(query=True, maxTime=True)]
currRangeStr = "%s - %s"%(int(currRange[0]), int(currRange[1]))
#populate list
ranges = self.getTimelineRanges()
if ranges: ranges = eval(ranges)
if ranges:
for loopRange in ranges:
loopRangeStr = "%s - %s"%(int(loopRange[0]), int(loopRange[1]-1))
radioButton = (currRangeStr == loopRangeStr)
cmds.menuItem("menu_%s"%loopRange, radioButton=radioButton, label=loopRangeStr, parent=menu, command=lambda x, loopRange=loopRange, *args: self.setTimelineRange(loopRange))
cmds.menuItem( divider=True, parent=menu)
newMenu = cmds.menuItem(subMenu=True, label='Delete', parent=menu)
cmds.menuItem( divider=True, parent=menu)
for loopRange in ranges:
loopRangeStr = "%s - %s"%(int(loopRange[0]), int(loopRange[1]-1))
cmds.menuItem("menu_%s"%loopRange, label=loopRangeStr, parent=newMenu, command=lambda x, loopRange=loopRange, *args: self.deleteTimelineRange(loopRange))
cmds.menuItem( divider=True, parent=newMenu)
cmds.menuItem("menu_deleteAll", label="Delete All", parent=newMenu, command=self.deleteAllTimelineRange)
cmds.menuItem("toggleLipSyncModeMenu", label='Lip Sync Mode', checkBox=self.isLipSyncMode(), command=self.toggleLipSyncMode, parent=menu)
def getTimelineRanges(self):
return aToolsMod.loadInfoWithScene(STORE_NODE, RANGE_ATTR)
def setTimelineRange(self, range=None, *args):
rangeVisible = cmds.timeControl( G.playBackSliderPython, query=True, rangeVisible=True )
if not rangeVisible and not range:
range = [cmds.playbackOptions(query=True, minTime=True), cmds.playbackOptions(query=True, maxTime=True)+1]
if range or rangeVisible:
if not range: range = animMod.getTimelineRange(float=False)
rFrom = range[0]
rTo = range[1]-1
cmds.playbackOptions(minTime=rFrom, maxTime=rTo)
if self.getTimelineRanges() != None:
ranges = eval(self.getTimelineRanges())
else:
ranges = []
if not range in ranges:
ranges.append(range)
aToolsMod.saveInfoWithScene(STORE_NODE, RANGE_ATTR, ranges)
utilMod.deselectTimelineRange()
def deleteTimelineRange(self, range=None, *args):
ranges = eval(self.getTimelineRanges())
if not ranges: ranges = []
if range in ranges: ranges.remove(range)
aToolsMod.saveInfoWithScene(STORE_NODE, RANGE_ATTR, ranges)
def deleteAllTimelineRange(self, *args):
aToolsMod.saveInfoWithScene(STORE_NODE, RANGE_ATTR, [])
def toggleLipSyncMode(self, *args):
if self.isLipSyncMode():
cmds.timeControl(G.playBackSliderPython, edit=True, height=28)
else:
cmds.timeControl(G.playBackSliderPython, edit=True, height=200)
def isLipSyncMode(self, *args):
timelineHeight = cmds.timeControl(G.playBackSliderPython, query=True, height=True)
return timelineHeight > 28
class CameraTools(object):
def __init__(self):
animMod.getShotCamera()
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
def popupMenu(self):
cmds.popupMenu(postMenuCommand=self.populateMenu)
def populateMenu(self, menu, *args):
uiMod.clearMenuItems(menu)
cmds.radioMenuItemCollection(parent=menu)
#populate list
for loopCamera in utilMod.getAllCameras():
radioSelected = (animMod.getShotCamera() == loopCamera)
cameraName = cmds.listRelatives(loopCamera, allParents=True)[0]
cmds.menuItem("menu_%s"%loopCamera, label=str(cameraName), radioButton=radioSelected, parent=menu, command=lambda x, loopCamera=loopCamera, *args: aToolsMod.saveInfoWithScene(STORE_NODE, CAMERA_ATTR, loopCamera))
# last playblast menu
cmds.menuItem(divider=True, parent=menu)
checkBoxSelected = aToolsMod.getUserPref("saveAfterPlayblasting", default=True)
cmds.menuItem("saveAfterPlayblastingMenu", label='Save Maya File After Playblasting', checkBox=checkBoxSelected, command=self.setSaveAfterPlayblastingPref, parent=menu)
cmds.menuItem(divider=True, parent=menu)
cmds.menuItem (label="Duplicate Selected Camera", command=self.duplicateCamera, parent=menu)
cmds.menuItem (label="Playblast Viewport", command=self.playblastViewport, parent=menu)
cmds.menuItem (label="Play Last Playblast", command=self.playLastPlayblast, parent=menu)
def setSaveAfterPlayblastingPref(self, onOff):
self.setPref("saveAfterPlayblasting", onOff)
def setPref(self, pref, onOff):
aToolsMod.setUserPref(pref, onOff)
def playblastViewport(self, *args):
currCamera = utilMod.getCurrentCamera()
if currCamera:
self.doPlayblast(currCamera)
else:
cmds.warning( "Please set focus on a viewport" )
def playblastCamera(self, *args):
camera = animMod.getShotCamera()
if camera: self.doPlayblast(camera)
def doPlayblast(self, camera):
G.TU_movie = None
G.TU_audioFile = None
G.TU_audioOffsetSec = None
winName = 'playblastWindow'
overscan = cmds.getAttr("%s.overscan"%camera)
audioTrack = cmds.timeControl(G.playBackSliderPython, query=True, sound=True)
rangeVisible = cmds.timeControl(G.playBackSliderPython, query=True, rangeVisible=True )
widthHeight = utilMod.getRenderResolution()
if cmds.window(winName, query=True, exists=True): cmds.deleteUI(winName)
window = cmds.window(winName, widthHeight=widthHeight)
form = cmds.formLayout()
editor = cmds.modelEditor()
column = cmds.columnLayout('true')
cmds.formLayout( form, edit=True, attachForm=[(column, 'top', 0), (column, 'left', 0), (editor, 'top', 0), (editor, 'bottom', 0), (editor, 'right', 0)], attachNone=[(column, 'bottom'), (column, 'right')], attachControl=(editor, 'left', 0, column))
cmds.modelEditor(editor, edit=True, camera=camera, activeView=True)
cmds.showWindow( window )
cmds.window( winName, edit=True, topLeftCorner=(0, 0), widthHeight=[200,200])
utilMod.cameraViewMode(editor)
cmds.setAttr("%s.overscan"%camera, 1)
if rangeVisible:
range = animMod.getTimelineRange(float=False)
rFrom = range[0]
rTo = range[1]-1
else:
rFrom = cmds.playbackOptions(query=True, minTime=True)
rTo = cmds.playbackOptions(query=True, maxTime=True)
if G.currentStudio == None:
G.TU_movie = cmds.playblast(format="qt", sound=audioTrack, startTime=rFrom ,endTime=rTo , viewer=1, showOrnaments=0, offScreen=True, fp=4, percent=50, compression="png", quality=70, widthHeight=widthHeight, clearCache=True)
else:
fps = mel.eval("currentTimeUnitToFPS")
if audioTrack:
G.TU_audioFile = cmds.sound(audioTrack, query=True, file=True)
audioOffset = cmds.sound(audioTrack, query=True, offset=True)
G.TU_audioOffsetSec = str((rFrom - audioOffset)/-fps)
movieName = cmds.playblast(format="image", startTime=rFrom ,endTime=rTo , viewer=0, showOrnaments=0, offScreen=True, fp=4, percent=50, compression="jpg", quality=70, widthHeight=widthHeight, clearCache=True)
if movieName:
G.TU_movie = "%s.%s-%s#.jpg"%(movieName.split(".")[0], int(rFrom), int(rTo))
if audioTrack: G.TU_audioOffsetSec = audioOffset
self.playMovie(G.TU_movie, G.TU_audioFile, G.TU_audioOffsetSec)
if cmds.window(winName, query=True, exists=True): cmds.deleteUI(winName)
cmds.setAttr("%s.overscan"%camera, overscan)
if not G.TU_movie: return
save = aToolsMod.getUserPref("saveAfterPlayblasting", default=True)
if save and not rangeVisible: cmds.file(save=True)
def playMovie(self, movie, audioFile, audioOffsetSec):
if not movie:
cmds.warning( "No movie to play." )
return
def playLastPlayblast(self, *args):
self.playMovie(G.TU_movie, G.TU_audioFile, G.TU_audioOffsetSec)
def duplicateCamera(self, *args):
sel = cmds.ls(selection=True)
camNode = utilMod.getCamFromSelection(sel)
if camNode:
dupCamNode = cmds.camera()
camTransformNode = camNode[0]
camShapeNode = camNode[1]
dupCamTransformNode = dupCamNode[0]
dupCamShapeNode = dupCamNode[1]
utilMod.transferAttributes(camTransformNode, dupCamTransformNode)
utilMod.transferAttributes(camShapeNode, dupCamShapeNode)
G.aToolsBar.align.align([dupCamTransformNode], camTransformNode)
cmds.select(dupCamTransformNode)
return
cmds.warning("No camera was created.")

View File

@ -0,0 +1,770 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Modified: Michael Klimenko
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from maya import mel
import math
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod
from aTools.commonMods import animMod
from aTools.commonMods import utilMod
class Tangents_Gui(uiMod.BaseSubUI):
def createLayout(self):
tangents = Tangents()
buttons = ["flow", "bounce", "auto", "spline", "linear", "flat", "step"]
cmds.rowLayout(numberOfColumns=8, parent=self.parentLayout)
for loopButton in buttons:
cmds.iconTextButton(style='iconAndTextVertical', image= uiMod.getImagePath("tangents_%s"%loopButton), highlightImage= uiMod.getImagePath("tangents_%s copy"%loopButton), w=self.wb, h=self.hb, command=lambda loopButton=loopButton, *args: tangents.setTangent(loopButton), annotation="%s tangent\\nRight click for options"%str.title(loopButton))
tangents.popupMenu(loopButton)
# end createLayout
class Tangents(object):
def __init__(self):
if G.aToolsBar.tangents: return
G.aToolsBar.tangents = self
def popupMenu(self, button, *args):
menu = cmds.popupMenu()
cmds.popupMenu(menu, edit=True, postMenuCommand=lambda *args:self.populateMenu(menu, button), postMenuCommandOnce=True)
def populateMenu(self, menu, button, *args):
print(("menu, button, *args", menu, button, args))
if button != "step":
cmds.menuItem(label='In Tangent', command=lambda *args: self.setTangent(button, 'in'), parent=menu)
cmds.menuItem(label='Out Tangent', command=lambda *args: self.setTangent(button, 'out'), parent=menu)
cmds.menuItem(divider=True, parent=menu)
cmds.menuItem(label='First Frame', command=lambda *args: self.setTangent(button, 'out', 'first'), parent=menu)
cmds.menuItem(label='Last Frame', command=lambda *args: self.setTangent(button, 'in', 'last'), parent=menu)
cmds.menuItem(label='Both Ends', command=lambda *args: self.setTangent(button, 'inOut', 'both'), parent=menu)
cmds.menuItem(divider=True, parent=menu)
cmds.menuItem(label='All Keys', command=lambda *args: self.setTangent(button, 'inOut', 'all'), parent=menu)
def flowAround(self, frames = 2, excludeCurrKey = False):
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves:
#if getFrom == "graphEditor":
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
tangentType = "flow"
time = None
#animMod.expandKeySelection(frames)
index = animMod.getTarget("keysIndexSel", animCurves, getFrom)
indexTimes = animMod.getTarget("keyIndexTimes", animCurves, getFrom)
#expand selection
for n, loopCurve in enumerate(index):
for x in range(frames):
if loopCurve[0] >= 1:
loopCurve.insert(0, loopCurve[0]-1)
if loopCurve[-1] < indexTimes[n][-1]:
loopCurve.append(loopCurve[-1]+1)
#if excludeCurrKey:
self.applyTangent(animCurves, tangentType, getFrom, time, index)
#select back keys
if keysSel:
cmds.selectKey(clear=True)
for n, aCurve in enumerate(animCurves):
for key in keysSel[n]:
cmds.selectKey(aCurve, addTo=True, time=(key, key))
def applyTangent(self, animCurves, tangentType, getFrom, time, index, tangentInOut="inOut"):
if self.isDefaultTangent(tangentType): #default maya tangents
if tangentType == "step":
cmds.keyTangent(animCurves, edit=True, time=time, outTangentType=tangentType)
else:
if tangentInOut =="inOut" or tangentInOut == "in":
#print "applied in", time, tangentType
cmds.keyTangent(animCurves, edit=True, time=time, inTangentType=tangentType)
if tangentInOut =="inOut" or tangentInOut == "out":
#print "applied out", time, tangentType
cmds.keyTangent(animCurves, edit=True, time=time, outTangentType=tangentType)
else: #custom tangents
keyTimes = animMod.getTarget("keyTimes", animCurves)
keyIndexTimes = animMod.getTarget("keyIndexTimes", animCurves)
keysIndexSel = index
keyValues = animMod.getTarget("keyValues", animCurves)
cycleArray = []
tangentArray = []
for n, aCurve in enumerate(animCurves):
cycleArray.append([])
tangentArray.append([])
if keysIndexSel != None and keyTimes[n] != None and keysIndexSel[n] != None and len(keyTimes[n]) >=2:
if keyValues[n][0] == keyValues[n][-1] and keysIndexSel[n] == keyIndexTimes[n]: #it's a cycle
cycleArray[n] = True
else:
cycleArray[n] = False
#define tangent array
for i in keysIndexSel[n]:
tangentArray[n].append(cmds.keyTangent(aCurve, query=True, index=(i, i), inTangentType=True, outTangentType=True, inAngle=True, outAngle=True))
passes = [self.averageTangent, self.flowTangent]
#passes = [averageTangent]
#self.fixTangentOvershoot, self.fixTangentOpposite
self.applyPass(passes, animCurves, keyTimes, keyValues, keysIndexSel, tangentType)
# put back saved in out sides
for n, aCurve in enumerate(animCurves):
if keysIndexSel != None and keyTimes[n] != None and keysIndexSel[n] != None and len(keyTimes[n]) >=2:
for nn, i in enumerate(keysIndexSel[n]):
tangent = tangentArray[n][nn]
if tangentInOut == "in":
cmds.keyTangent(aCurve, edit=True, index=(i, i), lock=False)
cmds.keyTangent(aCurve, edit=True, index=(i, i), outTangentType=tangent[3], outAngle=tangent[1])
cmds.keyTangent(aCurve, edit=True, index=(i, i), lock=True)
elif tangentInOut == "out":
cmds.keyTangent(aCurve, edit=True, index=(i, i), lock=False)
cmds.keyTangent(aCurve, edit=True, index=(i, i), inTangentType=tangent[2], inAngle=tangent[0])
cmds.keyTangent(aCurve, edit=True, index=(i, i), lock=True)
if tangentType == "flow":
# bounce ends
for n, aCurve in enumerate(animCurves):
first = None
last = None
if 0 in keysIndexSel[n]: first = True
if len(keyTimes[n])-1 in keysIndexSel[n]: last = True
if first and last:
self.bounceEnds([aCurve], "bounce", getFrom, tangentInOut, [keyTimes[n]], [keyIndexTimes[n]], "both")
elif first:
self.bounceEnds([aCurve], "bounce", getFrom, tangentInOut, [keyTimes[n]], [keyIndexTimes[n]], "first")
elif last:
self.bounceEnds([aCurve], "bounce", getFrom, tangentInOut, [keyTimes[n]], [keyIndexTimes[n]], "last")
#print "fl", first, last
# cycle?
for n, aCurve in enumerate(animCurves):
if cycleArray[n]:
angle = cmds.keyTangent(aCurve, query=True, index=(0, 0), outAngle=True)[0]
cmds.keyTangent(aCurve, time=(keyTimes[n][-1], keyTimes[n][-1]), inAngle=angle, outAngle=angle)
def applyPass(self, passes, animCurves, keyTimes, keyValues, keysIndexSel, tangentType):
newKeysIndexSel = utilMod.dupList(keysIndexSel)
for loopFunction in passes:
#utilMod.timer("s")
for n, aCurve in enumerate(animCurves):
if keysIndexSel != None and keyTimes[n] != None and keysIndexSel[n] != None and len(keyTimes[n]) >=2:
#utilMod.timer()
#unlock weights
weighted = cmds.keyTangent(aCurve, query=True, weightedTangents=True)[0]
locked = cmds.keyTangent(aCurve, query=True, lock=True)
#utilMod.timer()
if weighted: cmds.keyTangent(aCurve, edit=True, weightedTangents=False) #weight to balance in and out tangents
cmds.keyTangent(aCurve, edit=True, weightedTangents=True)
#utilMod.timer()
if loopFunction == self.fixTangentOpposite:
#remove last index
if len(keysIndexSel[n]) > 0: keysIndexSel[n].pop()
if len(newKeysIndexSel[n]) > 0: newKeysIndexSel[n].pop()
#reorder index according with size of segment
keysIndexSel[n] = self.tangentOppositeReorder(keysIndexSel[n], keyValues[n])
#utilMod.timer()
# apply the damn function
for loopIndex in keysIndexSel[n]:
curTangType = self.tangType(keyValues[n], keyTimes[n], loopIndex)
applied = loopFunction(aCurve, keyValues[n], loopIndex, tangentType, curTangType, keysIndexSel[n], keyTimes[n])
if loopFunction == self.fixTangentOvershoot and applied:
#remove the applied index to avoid changind that tangent again
if newKeysIndexSel[n]: newKeysIndexSel[n].remove(loopIndex)
#utilMod.timer()
# put back
for i, loopLocked in enumerate(locked):
cmds.undoInfo(stateWithoutFlush=False)
if loopLocked: cmds.keyTangent(aCurve, edit=True, index=(i,i), lock=loopLocked)
cmds.undoInfo(stateWithoutFlush=True)
#utilMod.timer()
if weighted: cmds.keyTangent(aCurve, edit=True, weightedTangents=False) #weight to balance in and out tangents
cmds.keyTangent(aCurve, edit=True, weightedTangents=weighted)
#utilMod.timer("e", loopFunction)
def tangentOppositeReorder(self, indexes, values):
#put bigger segments first
difList = []
for n, loopVal in enumerate(values[2:-3]):
dif = values[n+1+2] - values[n+2]
difList.append(abs(dif))
indexList = []
tmpDifList = utilMod.dupList(difList)
for n, loopDif in enumerate(tmpDifList):
maxDif = max(tmpDifList)
index = difList.index(maxDif)
tmpDifList[index] = -1
indexList.append(index)
newIndexes = []
for loopIndex in indexList:
if loopIndex in indexes:
newIndexes.append(loopIndex)
"""
print "indexList",indexList
print "values",values
print "difList",difList
print "indexes",indexes
print "newIndexes",newIndexes
"""
return newIndexes
def setTangent(self, tangentType, tangentInOut="inOut", targetKeys="selected", *args):
#utilMod.timer(mode="s", function="MAIN FUNCTION")
cmds.waitCursor(state=True)
"""
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
cmds.undoInfo(closeChunk=True)
cmds.undoInfo(openChunk=True)
"""
#tangentType = flow, bounce, auto, etc
#targetKeys = all, selected
#tangentInOut = inOut, in, out
#set default tangent type
if tangentType == "flow":
cmds.keyTangent(edit=True, g=True, inTangentType="auto", outTangentType="auto")
elif tangentType == "step":
cmds.keyTangent(edit=True, g=True, outTangentType=tangentType)
elif tangentType != "bounce":
cmds.keyTangent(edit=True, g=True, inTangentType=tangentType, outTangentType=tangentType)
# get target curves
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
#if there is no curves, exit
if animCurves:
status = "aTools - Tangents..."
utilMod.startProgressBar(status)
totalSteps = len(animCurves)
firstStep = 0
thisStep = 0
estimatedTime = None
startChrono = None
index = None
time = None
if targetKeys == "all": # apply for all keys
time = (-50000, 500000)
if not self.isDefaultTangent(tangentType):
index = animMod.getTarget("keyIndexTimes", animCurves, getFrom)
self.applyTangent(animCurves, tangentType, getFrom, time, index)
elif targetKeys == "selected": #apply on a range
if getFrom == "timeline":
time = animMod.getTimelineRange(); time = (time[0], time[1])#flow and bounce
if not self.isDefaultTangent(tangentType): index = animMod.getTarget("keysIndexSel", animCurves, getFrom)
self.applyTangent(animCurves, tangentType, getFrom, time, index, tangentInOut)
else:
if self.isDefaultTangent(tangentType): # if the tangent types are default maya types
#apply individually on each key
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
for thisStep, aCurve in enumerate(animCurves):
if cmds.progressBar(G.progBar, query=True, isCancelled=True ):
utilMod.setProgressBar(endProgress=True)
break
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
for loopKey in keysSel[thisStep] :
time = (loopKey, loopKey)
self.applyTangent(aCurve, tangentType, getFrom, time, index, tangentInOut)
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
else: #flow and bounce
index = animMod.getTarget("keysIndexSel", animCurves, getFrom)
self.applyTangent(animCurves, tangentType, getFrom, time, index, tangentInOut)
else:# first and last frame
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
keyIndexTimes = animMod.getTarget("keyIndexTimes", animCurves, getFrom)
self.bounceEnds(animCurves, tangentType, getFrom, tangentInOut, keyTimes, keyIndexTimes, targetKeys)
utilMod.setProgressBar(endProgress=True)
#cmds.undoInfo(closeChunk=True)
cmds.waitCursor(state=False)
#utilMod.timer(mode="e", function="MAIN FUNCTION")
def bounceEnds(self, animCurves, tangentType, getFrom, tangentInOut, keyTimes, keyIndexTimes, targetKeys):
for n, aCurve in enumerate(animCurves):
if targetKeys == "first" or targetKeys == "both":
firstTime = keyTimes[n][0]
firstIndex = keyIndexTimes[n][0]
time = (firstTime,firstTime)
index = [firstIndex]
self.applyTangent([aCurve], tangentType, getFrom, [time], [index], tangentInOut)
if targetKeys == "last" or targetKeys == "both":
lastTime = keyTimes[n][-1]
lastIndex = keyIndexTimes[n][-1]
time = (lastTime,lastTime)
index = [lastIndex]
self.applyTangent([aCurve], tangentType, getFrom, [time], [index], tangentInOut)
def isDefaultTangent(self, tangentType):
return (tangentType != "flow" and tangentType != "bounce")
def tangType(self, keyVal, keyTimes, index):
keyValTmp = utilMod.dupList(keyVal)
keyLocation = self.getKeyLocation(keyValTmp, index)
nKeys = len(keyValTmp)
if keyLocation == "first":
if keyValTmp[index] == keyValTmp[index+1] == keyValTmp[index+2]:
return "Zero"
elif keyLocation == "last":
if keyValTmp[index] == keyValTmp[index-1] == keyValTmp[index-2]:
return "Zero"
else:
index += 2
for x in range(2):
keyValTmp.insert(0, keyValTmp[0])
keyValTmp.append(keyValTmp[-1])
if keyValTmp[index] == keyValTmp[index+1] == keyValTmp[index+2] or keyValTmp[index] == keyValTmp[index-1] == keyValTmp[index-2] or keyValTmp[index] == keyValTmp[index+1] == keyValTmp[index-1]:
return "Zero"
#or....
return "Average"
def getAverageAngle(self, keyVal, keyTimes, index):
keyLocation = self.getKeyLocation(keyVal, index)
if keyLocation == "mid":
relTimeInA = keyTimes[index] - keyTimes[index-1]
relValInA = keyVal[index-1] - keyVal[index]
relTimeOutA = keyTimes[index+1] - keyTimes[index]
relValOutA = keyVal[index+1] - keyVal[index]
outAngleA = math.degrees(math.atan(relValOutA/relTimeOutA))
outOpp = relTimeInA*math.tan(math.radians(outAngleA))
return -math.degrees(math.atan(((relValInA-outOpp)/2)/relTimeInA))
return 0
# end getAverageAngle
def getKeyLocation(self, keyVal, index):
if index == 0:
return "first"
elif index == len(keyVal)-1:
return "last"
else:
return "mid"
def fixTangentOvershoot(self, aCurve, keyVal, index, tangentType, curTangType, keysIndexSelN, *args):
#print "qual index? ", index
if index == None: return
#fix tangent limit ----------------------------------------------------------------------------
applied = False
power = .8
#get in values
iy = cmds.keyTangent(aCurve, query=True, index=(index, index), iy=True)[0]/3*power #in tangent handle y position
oy = cmds.keyTangent(aCurve, query=True, index=(index, index), oy=True)[0]/3*power #out tangent handle y position
prevVal = keyVal[index-1]
currVal = keyVal[index]
nextVal = keyVal[index+1]
#convert to radians if rotate
isRotate = animMod.isAnimCurveRotate(aCurve)
if isRotate:
prevVal = math.radians(prevVal)
currVal = math.radians(currVal)
nextVal = math.radians(nextVal)
difNext = (nextVal-currVal)*power
difPrev = (currVal-prevVal)*power
if (difNext < 0 and oy < difNext) or (difNext > 0 and oy > difNext):
cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="auto", outTangentType="auto")
cmds.keyTangent(aCurve, edit=True, index=(index, index), oy=difNext*3)
applied = True
if (difPrev < 0 and iy < difPrev) or (difPrev > 0 and iy > difPrev):
cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="auto", outTangentType="auto")
cmds.keyTangent(aCurve, edit=True, index=(index, index), iy=difPrev*3)
#print "aplicou index:", index
if index-1 in keysIndexSelN:
cmds.keyTangent(aCurve, edit=True, index=(index-1, index-1), inTangentType="auto", outTangentType="auto")
self.flowTangent(aCurve, keyVal, index-1, tangentType)
applied = True
#print "flow index:", index-1
"""
print "--------------------------------"
print "index", index
print "iy",iy
print "oy",oy
print "difPrev",difPrev
print "prevVal",prevVal
print "nextVal",nextVal
print "currVal",currVal
"""
return applied
def fixTangentOpposite(self, aCurve, keyVal, index, tangentType, curTangType, keysIndexSelN, *args):
if index == None: return
currVal = keyVal[index]
nextVal = keyVal[index+1]
currTime = cmds.keyframe(aCurve, query=True, index=(index,index), timeChange=True)[0]#current time value
nextTime = cmds.keyframe(aCurve, query=True, index=(index+1,index+1), timeChange=True)[0]#current time value
power = 2
#get in values for next key
ix = cmds.keyTangent(aCurve, query=True, index=(index+1,index+1), ix=True)[0] #in tangent handle x position
iy = cmds.keyTangent(aCurve, query=True, index=(index+1,index+1), iy=True)[0] #in tangent handle y position
#get out values
ox = cmds.keyTangent(aCurve, query=True, index=(index,index), ox=True)[0] #out tangent handle x position
oy = cmds.keyTangent(aCurve, query=True, index=(index,index), oy=True)[0] #out tangent handle y position
#curve position at handle
valIn = nextVal - cmds.keyframe(aCurve, query=True, eval=True, time=(nextTime-ix/.125,nextTime-ix/.125), valueChange=True)[0]
valOut = cmds.keyframe(aCurve, query=True, eval=True, time=(currTime+ox/.125,currTime+ox/.125), valueChange=True)[0] - currVal
#convert to radians if rotate
isRotate = animMod.isAnimCurveRotate(aCurve)
if isRotate:
currVal = math.radians(currVal)
nextVal = math.radians(nextVal)
valIn = math.radians(valIn)
valOut = math.radians(valOut)
#difference btw val and y
difIn = iy/3 - valIn
difOut = oy/3 - valOut
#detect
if (difIn > 0 and difOut > 0) or (difIn < 0 and difOut < 0):
if abs(difIn) > abs(difOut):
inOut = "in"
else:
inOut = "out"
for x in range(5):
currVal = keyVal[index]
nextVal = keyVal[index+1]
#get in values for next key
ix = cmds.keyTangent(aCurve, query=True, index=(index+1,index+1), ix=True)[0] #in tangent handle x position
iy = cmds.keyTangent(aCurve, query=True, index=(index+1,index+1), iy=True)[0] #in tangent handle y position
#get out values
ox = cmds.keyTangent(aCurve, query=True, index=(index,index), ox=True)[0] #out tangent handle x position
oy = cmds.keyTangent(aCurve, query=True, index=(index,index), oy=True)[0] #out tangent handle y position
#curve position at handle
valIn = nextVal - cmds.keyframe(aCurve, query=True, eval=True, time=(nextTime-ix/.125,nextTime-ix/.125), valueChange=True)[0]
valOut = cmds.keyframe(aCurve, query=True, eval=True, time=(currTime+ox/.125,currTime+ox/.125), valueChange=True)[0] - currVal
#convert to radians if rotate
isRotate = animMod.isAnimCurveRotate(aCurve)
if isRotate:
currVal = math.radians(currVal)
nextVal = math.radians(nextVal)
valIn = math.radians(valIn)
valOut = math.radians(valOut)
#difference btw val and y
difIn = iy/3 - valIn
difOut = oy/3 - valOut
if inOut == "in":
#print"IN"
#if next key is is array
if index+1 in keysIndexSelN:
newY = (iy/3) + (valOut-(oy/3))*power
cmds.keyTangent(aCurve, edit=True, index=(index+1, index+1), iy=newY*3, oy=newY*3, ox=ix)
else:
#print"OUT"
newY = (oy/3) + (valIn-(iy/3))*power
cmds.keyTangent(aCurve, edit=True, index=(index, index), iy=newY*3, oy=newY*3, ix=ox)
"""
print "index",index
print "difIn",difIn
print "difOut",difOut
print "iy",iy
print "oy",oy
print "iy/3",iy/3
print "oy/3",oy/3
print "valIn",valIn
print "valOut",valOut
print "currVal",currVal
print "nextVal",nextVal
print "------------------------------"
"""
def averageTangent(self, aCurve, keyVal, index, tangentType, curTangType, keysIndexSelN, keyTimes, *args):
# average
cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="linear", outTangentType="linear")
if tangentType == "flow":
if curTangType == "Zero":
mAngle = 0
else:
mAngle = self.getAverageAngle(keyVal, keyTimes, index)
if index == 0:
cmds.keyTangent(aCurve, edit=True, index=(index, index), outTangentType="linear")
return
if index == len(keyVal)-1:
cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="linear")
return
cmds.keyTangent(aCurve, edit=True, index=(index, index), inAngle=mAngle, outAngle=mAngle)
#if tangentType == "bounce":
#cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="linear", outTangentType="linear")
def flowTangent(self, aCurve, keyVal, index, tangentType, curTangType, *args):
if curTangType == "Zero" and tangentType == "flow": return
if index == None: return
#is it first or last key?
keyLocation = self.getKeyLocation(keyVal, index)
if keyLocation != "mid" and tangentType != "bounce": return
currVal = keyVal[index]
currTime = cmds.keyframe(aCurve, query=True, index=(index,index), timeChange=True)[0]#current time value
#get in values
ix = cmds.keyTangent(aCurve, query=True, index=(index,index), ix=True)[0] #in tangent handle x position
iy = cmds.keyTangent(aCurve, query=True, index=(index,index), iy=True)[0] #in tangent handle y position
#get out values
ox = cmds.keyTangent(aCurve, query=True, index=(index,index), ox=True)[0] #out tangent handle x position
oy = cmds.keyTangent(aCurve, query=True, index=(index,index), oy=True)[0] #out tangent handle y position
cmds.undoInfo(stateWithoutFlush=False)
cmds.keyTangent(aCurve, index=(index,index), lock=False)
cmds.undoInfo(stateWithoutFlush=True)
if tangentType == "flow":
if ox>ix:
ox = ix
oy = iy
cmds.keyTangent(aCurve, edit=True, index=(index, index), ox=ox, oy=oy)
else:
ix = ox
iy = oy
cmds.keyTangent(aCurve, edit=True, index=(index, index), ix=ix, iy=iy)
#curve position at handle
valIn = cmds.keyframe(aCurve, query=True, eval=True, time=(currTime-ix/.125,currTime-ix/.125), valueChange=True)[0]
valOut = cmds.keyframe(aCurve, query=True, eval=True, time=(currTime+ox/.125,currTime+ox/.125), valueChange=True)[0]
#if the anim curve is rotate, convert to radians
isRotate = animMod.isAnimCurveRotate(aCurve)
if isRotate:
currVal = math.radians(currVal)
valIn = math.radians(valIn)
valOut = math.radians(valOut)
#print "isrotate"
#distance between the curve position and the key value
distValueIn = (valIn-currVal)
distValueOut = (valOut-currVal)
#distance between the curve position and the tangent y position
distTangIn = distValueIn+(iy/3)
distTangOut = distValueOut-(oy/3)
if tangentType == "flow":
# calculate the difference btween the distances between the curve position and the tangent y position
dif = (distTangIn-distTangOut)
newOy = (oy/3)-dif
#newIy = (iy/3)-dif
newIy = newOy
#print "newIy",newIy,"(iy/3)",(iy/3),"(oy/3)",(oy/3),"currVal",currVal,"valOut",valOut,"distIn",distTangIn,"distOut",distTangOut,"dif",dif,"distValueIn",distValueIn,"distValueOut",distValueOut
elif tangentType == "bounce":
newIy = -distValueIn+(-distValueIn-(iy/3))
newOy = distValueOut+(distValueOut-(oy/3))
"""
print "---------------------------"
print "newIy",newIy
print "newOy",newOy
print "(iy/3)",(iy/3)
print "(oy/3)",(oy/3)
print "currVal",currVal
print "valOut",valOut
print "distIn",distTangIn
print "distOut",distTangOut
print "distValueIn",distValueIn
print "distValueOut",distValueOut
"""
#apply
cmds.keyTangent(aCurve, edit=True, index=(index, index), iy=newIy*3, oy=newOy*3)

View File

@ -0,0 +1,284 @@
'''
========================================================================================================================
Author: Alan Camilo
www.alancamilo.com
Requirements: aTools Package
------------------------------------------------------------------------------------------------------------------------
To install aTools, please follow the instructions in the file how_to_install.txt
------------------------------------------------------------------------------------------------------------------------
To unistall aTools, go to menu (the last button on the right), Uninstall
========================================================================================================================
'''
from maya import cmds
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import uiMod
from aTools.commonMods import utilMod
from aTools.commonMods import animMod
from aTools.commonMods import commandsMod
from aTools.commonMods import aToolsMod
G.TM_coloredKeys = None
G.TM_lastTweenCommand = G.TM_lastTweenCommand or None
class TweenMachine_Gui(uiMod.BaseSubUI):
def createLayout(self):
tweenMachine = TweenMachine()
cmds.rowColumnLayout(numberOfColumns=100, parent=self.parentLayout)
#linear
cmds.text( label=' ', h=1 )
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_left"), highlightImage= uiMod.getImagePath("tweenMachine_left copy"), command=lambda *args: tweenMachine.setTween("linear_prev"), annotation="Overshoot linear tween")
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hb, image= uiMod.getImagePath("tweenMachine_L"), highlightImage= uiMod.getImagePath("tweenMachine_L copy"), command=lambda *args: tweenMachine.setTween("linear"), annotation="Linear tween")
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_right"), highlightImage= uiMod.getImagePath("tweenMachine_right copy"), command=lambda *args: tweenMachine.setTween("linear_next"), annotation="Overshoot linear tween")
#tween
cmds.text( label=' ', h=1 )
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_left"), highlightImage= uiMod.getImagePath("tweenMachine_left copy"), command=lambda *args: tweenMachine.setTween(-50), annotation="Overshoot 50% with previous key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(-30), annotation="Overshoot 30% with previous key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(-10), annotation="Overshoot 10% with previous key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hb, image= uiMod.getImagePath("tweenMachine_key"), highlightImage= uiMod.getImagePath("tweenMachine_key copy"), command=lambda *args: tweenMachine.setTween(0), annotation="Copy previous key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(10), annotation="Tween 90% with previous key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(20), annotation="Tween 80% with previous key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(33), annotation="Tween 66% with previous key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hb, image= uiMod.getImagePath("tweenMachine_T"), highlightImage= uiMod.getImagePath("tweenMachine_T copy"), command=lambda *args: tweenMachine.setTween(50), annotation="Tween 50%"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(66), annotation="Tween 66% with next key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(80), annotation="Tween 80% with next key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(90), annotation="Tween 90% with next key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hb, image= uiMod.getImagePath("tweenMachine_key"), highlightImage= uiMod.getImagePath("tweenMachine_key copy"), command=lambda *args: tweenMachine.setTween(100), annotation="Copy next key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(110), annotation="Overshoot 10% with next key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(130), annotation="Overshoot 30% with next key"); tweenMachine.popUpColor()
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_right"),highlightImage= uiMod.getImagePath("tweenMachine_right copy"), command=lambda *args: tweenMachine.setTween(150), annotation="Overshoot 50% with next key"); tweenMachine.popUpColor()
class TweenMachine(object):
def __init__(self):
if G.aToolsBar.tweenMachine: return
G.aToolsBar.tweenMachine = self
# end createLayout
def popUpColor(self):
cmds.popupMenu(postMenuCommand=self.populateColorMenu, postMenuCommandOnce=True)
def populateColorMenu(self, parent, *args):
cmds.menuItem(label="Color Keyframes", checkBox=self.getColoredKeys(), command=self.setColoredKeys, parent=parent)
cmds.menuItem(divider=True, parent=parent )
cmds.menuItem(label="Apply Special Key Color", command=lambda *args:self.applyTickColor(True), parent=parent)
cmds.menuItem(label="Apply Default Key Color", command=lambda *args:self.applyTickColor(False), parent=parent)
def getColoredKeys(self):
if not G.TM_coloredKeys:
r = aToolsMod.loadInfoWithUser("userPrefs", "coloredKeys")
else:
r = G.TM_coloredKeys
if r == None:
default = True
r = default
G.TM_coloredKeys = r
return r
def setColoredKeys(self, onOff):
onOff = not self.getColoredKeys()
G.TM_coloredKeys = onOff
aToolsMod.saveInfoWithUser("userPrefs", "coloredKeys", onOff)
def repeatLastCommand(self):
if G.TM_lastTweenCommand: eval(G.TM_lastTweenCommand)
def setTween(self, percent, *args):
#utilMod.timer("s")
G.TM_lastTweenCommand = "self.setTween(%s)"%percent
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves:
status = "aTools - Tween Machine..."
utilMod.startProgressBar(status)
totalSteps = len(animCurves)
firstStep = 0
thisStep = 0
estimatedTime = None
startChrono = None
cmds.waitCursor(state=True)
cmds.refresh(suspend=True)
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
keyTimes = animMod.getTarget("keyTimes", animCurves)
timelineTime = None
#keysSelMerged = utilMod.mergeLists(keysSel)
if isinstance(percent, int):
# reverse order to get ease in and out smoothly
if 0 < percent <= 50 or percent == 100:
for loopVal in keysSel:
loopVal.reverse()
#utilMod.timer()
"""
if len(keysSelMerged) == 0:
if not timelineTime: timelineTime = [animMod.getTimelineTime()]
cmds.setKeyframe(animCurves, time=timelineTime[0])
elif len(keysSelMerged) == 1:
cmds.setKeyframe(animCurves, time=keysSelMerged[0])
"""
for thisStep, loopCurve in enumerate(animCurves):
if cmds.progressBar(G.progBar, query=True, isCancelled=True ):
utilMod.setProgressBar(endProgress=True)
break
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
if not keysSel[thisStep]:
if not timelineTime: timelineTime = [animMod.getTimelineTime()]
time = timelineTime
else:
time = [(loopTime,loopTime) for loopTime in keysSel[thisStep]]
# if all keys selected, use timeline time instead
if len(time) == len(keyTimes[thisStep]):
if not timelineTime: timelineTime = [animMod.getTimelineTime()]
time = timelineTime
for loopTime in time:
prevKeyTime = cmds.findKeyframe(loopCurve, time=loopTime, which="previous")
nextKeyTime = cmds.findKeyframe(loopCurve, time=loopTime, which="next")
if prevKeyTime == nextKeyTime and prevKeyTime != loopTime[0] and percent != "linear_next" and percent != "linear_prev": # if there is no previous or next key and at least one key
cmds.setKeyframe(loopCurve, time=loopTime)
elif prevKeyTime != time[0]:
if percent == "linear_prev":
prevKeyTime = nextKeyTime
nextKeyTime = cmds.findKeyframe(loopCurve, time=(prevKeyTime,prevKeyTime), which="next")
prevKeyVal = cmds.keyframe(loopCurve, query=True, time=(prevKeyTime, prevKeyTime), valueChange=True)[0]
nextKeyVal = cmds.keyframe(loopCurve, query=True, time=(nextKeyTime, nextKeyTime), valueChange=True)[0]
if nextKeyTime == prevKeyTime:
value = prevKeyVal
else:
value = prevKeyVal + ((nextKeyVal - prevKeyVal)/(nextKeyTime - prevKeyTime)*(loopTime[0] - prevKeyTime))
elif percent == "linear_next":
nextKeyTime = prevKeyTime
prevKeyTime = cmds.findKeyframe(loopCurve, time=(nextKeyTime,nextKeyTime), which="previous")
prevKeyVal = cmds.keyframe(loopCurve, query=True, time=(prevKeyTime, prevKeyTime), valueChange=True)[0]
nextKeyVal = cmds.keyframe(loopCurve, query=True, time=(nextKeyTime, nextKeyTime), valueChange=True)[0]
if nextKeyTime == prevKeyTime:
value = prevKeyVal
else:
value = prevKeyVal + ((nextKeyVal - prevKeyVal)/(nextKeyTime - prevKeyTime)*(loopTime[0] - prevKeyTime))
else:
animMod.eulerFilterCurve([loopCurve])
prevKeyVal = cmds.keyframe(loopCurve, query=True, time=(prevKeyTime, prevKeyTime), valueChange=True)[0]
nextKeyVal = cmds.keyframe(loopCurve, query=True, time=(nextKeyTime, nextKeyTime), valueChange=True)[0]
#print "prevKeyVal", prevKeyVal, nextKeyVal
#if prevKeyVal == nextKeyVal:
#if not time[0] in keysSel[thisStep]: cmds.setKeyframe(loopCurve, time=loopTime)
#continue
if percent == "linear": value = prevKeyVal + ((nextKeyVal - prevKeyVal)/(nextKeyTime - prevKeyTime)*(loopTime[0] - prevKeyTime))
else: value = ((nextKeyVal-prevKeyVal)/100.*percent)+prevKeyVal
tangentType = cmds.keyTangent(loopCurve, query=True, outTangentType=True, time=(prevKeyTime,prevKeyTime))[0]
inTangentType = tangentType.replace("fixed", "auto").replace("step", "auto")
outTangentType = tangentType.replace("fixed", "auto")
if not time[0] in keysSel[thisStep]: cmds.setKeyframe(loopCurve, time=loopTime)
cmds.keyframe(loopCurve, edit=True, time=loopTime, valueChange=value)
cmds.keyTangent(loopCurve, edit=True, time=loopTime, inTangentType=inTangentType, outTangentType=outTangentType)
#keycolor
if (isinstance(percent, int) and (1 <= percent <= 99)) or percent == "linear": cmds.keyframe(loopCurve ,edit=True,time=loopTime, tickDrawSpecial=self.getColoredKeys())
if getFrom == "graphEditor":
#curvesToSelect.append([loopCurve, loopTime])
cmds.selectKey(loopCurve, addTo=True, time=loopTime)
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
#utilMod.timer()
"""
#APPLY
if len(curvesToKey) > 0: cmds.setKeyframe(curvesToKey)
for loopVar in curvesToValue:
cmds.keyframe(loopVar[0], edit=True, time=loopVar[1], valueChange=loopVar[2])
cmds.keyTangent(loopVar[0], edit=True, time=loopVar[1], inTangentType=loopVar[3], outTangentType=loopVar[4])
for loopVar in curvesToColor: cmds.keyframe(loopVar[0], edit=True, time=loopVar[1], tickDrawSpecial=self.getColoredKeys())
for loopVar in curvesToSelect: cmds.selectKey(loopVar[0], addTo=True, time=loopVar[1])
"""
cmds.refresh(suspend=False)
cmds.waitCursor(state=False)
utilMod.setProgressBar(endProgress=True)
#utilMod.timer("e", "tween")
#end tweenValue
def applyTickColor(self, special=True, *args):
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
if animCurves:
for n, loopCurve in enumerate(animCurves):
time = [(loopTime,loopTime) for loopTime in keysSel[n]]
for loopTime in time:
#keycolor
cmds.keyframe(loopCurve ,edit=True,time=loopTime, tickDrawSpecial=special)