''' ======================================================================================================================== 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 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 commandsMod; from aTools.commonMods import aToolsMod from aTools.animTools.animBar.subUIs import tangents; importlib.reload(tangents) from aTools.animTools.animBar.subUIs.specialTools_subUIs import mirror; importlib.reload(mirror) Mirror = mirror.Mirror() G.KT_pushClick = False G.KT_sliderMode = None class KeyTransform_Gui(uiMod.BaseSubUI): def createLayout(self): keyTransform = KeyTransform() nudge = Nudge() ts = KeyTransformSlider_Gui() valueList = [0.01, 0.05, "", 0.10, 0.20, 0.50, "", 1.00, 1.50, 2.00, 3.00, 5.00, "", 10.00, 20.00] cmds.rowLayout(numberOfColumns=22, parent=self.parentLayout) # precision transform cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("keyTransform_-"), highlightImage= uiMod.getImagePath("keyTransform_- copy"), command=lambda *args: keyTransform.applyPrecise(keyTransform.getPrecisionValue()*-1), annotation="Decrease precise transform") cmds.floatField ("precisionNumber", minValue=0.01, precision=2, step=.05, value=0.5, annotation="Set precise transform value\nRight click for pre-defined values") cmds.popupMenu() for loopValueList in valueList: if loopValueList == "": cmds.menuItem( divider=True ) else: cmds.menuItem ("menu%s"%loopValueList, label=str(loopValueList), command=lambda loopValueList=loopValueList, *args: keyTransform.setPrecisionValue(loopValueList)) cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("keyTransform_+"), highlightImage= uiMod.getImagePath("keyTransform_+ copy"), command=lambda *args: keyTransform.applyPrecise(keyTransform.getPrecisionValue()), annotation="Increase precise transform") #reset cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("keyTransform_reset"), highlightImage= uiMod.getImagePath("keyTransform_reset copy"), command=keyTransform.resetValue, annotation="Reset value to default\nRight click for options") cmds.popupMenu() cmds.menuItem (label="Translate", command=lambda *args: keyTransform.resetValue(["Translate"])) cmds.menuItem (label="Rotate", command=lambda *args: keyTransform.resetValue(["Rotate"])) cmds.menuItem (label="Scale", command=lambda *args: keyTransform.resetValue(["Scale"])) cmds.menuItem( divider=True ) cmds.menuItem (label="Translate, Rotate and Scale", command=lambda *args: keyTransform.resetValue(["Translate", "Rotate", "Scale"])) #key cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("keyTransform_keykey"), highlightImage= uiMod.getImagePath("keyTransform_keykey copy"), command=keyTransform.shareEachOtherKeys, annotation="Share each other keys\nRight click for options") cmds.popupMenu() cmds.menuItem (label="All Keys", command=lambda *args: keyTransform.shareEachOtherKeys("all")) #nudge cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("keyTransform_nudge_left"), highlightImage= uiMod.getImagePath("keyTransform_nudge_left copy"), command=lambda *args: nudge.nudgeKey(-1), annotation="Nudge key left\nRight click for options") nudge.popupMenu("left") cmds.floatField ("nudgeEnterField", minValue=1, precision=0, step=1, value=10, annotation="Set precise nudge value", visible=False, w=1) cmds.popupMenu() cmds.menuItem (label="Hide", command=lambda *args:nudge.toggleEnterField(False)) cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("keyTransform_nudge_right"), highlightImage= uiMod.getImagePath("keyTransform_nudge_right copy"), command=lambda *args: nudge.nudgeKey(1), annotation="Nudge key right\nRight click for options") nudge.popupMenu("right") #slider cmds.text( label=' ', h=1 ) ts.populateSlider() cmds.text( label=' ', h=1 ) ts.setSliderMode(ts.getSliderMode()) # set the saved slider mode ts.delWindows() # delete if open # end createLayout class KeyTransformSlider_Gui(object): def __init__(self): self.winName = "keyTransformSliderWin" self.toolbarName = "keyTransformSliderToolbar" self.allWin = [self.winName, self.toolbarName] self.barOffset = 0 self.height = 60 self.defaultValues = {} self.optimizedValues = {} self.invertRules = None self.maxSelObjs = 1 self.blendToFramelabelA = ' A ' self.blendToFramelabelB = ' B ' self.blendToFrameValuesA = [] self.blendToFrameValuesB = [] self.blendToFrameCurrentValueA = None self.blendToFrameCurrentValueB = None self.defaultMode = "blendToFrame" self.defaultModifiers = {"shift" :"blendToNeighbors", "ctrl" :"scaleFromNeighborLeft", "alt" :"scaleFromNeighborRight", "ctrlShift" :"blendToDefault", "altShift" :"pullPush", "altCtrl" :"easeInOut", "altCtrlShift" :"blendToMirror" } self.modifiers = self.getModifiers() self.modeDividers = [3, 7] self.modesDict = [ { "mode": "pullPush", "icon": "pp", "function": "setPushValues" },{ "mode": "noise", "icon": "no", "function": "setNoiseValues" },{ "mode": "easeInOut", "icon": "ea", "function": "setEaseInOut" },{ "mode": "blendToDefault", "icon": "bd", "function": "setBlendScaleValues" },{ "mode": "blendToNeighbors", "icon": "bn", "function": "setBlendScaleValues" },{ "mode": "blendToMirror", "icon": "bm", "function": "setBlendScaleValues" },{ "mode": "blendToFrame", "icon": "bf", "function": "setBlendScaleValues" },{ "mode": "scaleFromDefault", "icon": "sd", "function": "setBlendScaleValues" },{ "mode": "scaleFromAverage", "icon": "sa", "function": "setBlendScaleValues" },{ "mode": "scaleFromNeighborLeft", "icon": "sl", "function": "setBlendScaleValues" },{ "mode": "scaleFromNeighborRight", "icon": "sr", "function": "setBlendScaleValues" } ] def createWin(self): self.mainWin = cmds.window(self.winName, sizeable=True) self.buttonHeight = self.height -10 # Main frame cmds.frameLayout("mainFrameLayout", labelVisible=False, w=10, borderVisible=False) cmds.rowLayout(numberOfColumns=2, adjustableColumn=1, columnAttach=([2, 'right', self.barOffset])) cmds.text(label="") cmds.rowLayout("keyTransformSliderParentLayout", numberOfColumns=100) self.populateButtons() # shows toolbar cmds.toolBar(self.toolbarName, area='bottom', content=self.mainWin, allowedArea=['bottom'], height=self.height) def populateSlider(self, mode="default"): keySliderW = 137 if mode=="default" else 111 imageW = 30 buttPerc = ((imageW/2)/(keySliderW/100.)) blendToFrameTxtA = None blendToFrameAnn = "Left click: pick current frame\nRight click: pick from history or current objects keys" labelA = self.blendToFramelabelA labelB = self.blendToFramelabelB if self.blendToFrameCurrentValueA: labelA = " %s"%self.blendToFrameCurrentValueA if self.blendToFrameCurrentValueB: labelB = "%s "%self.blendToFrameCurrentValueB cmds.formLayout ("keyTransformSliderFormLayout%s"%mode, h=32, w=keySliderW) if mode == "default": textValue = cmds.text("keyTransformSliderText", label="100", visible=False) else: textValue = cmds.text("keyTransformSliderText_%s"%mode, label="100", visible=False) slider = cmds.floatSlider ('keyTransformSlider%s'%mode, w=keySliderW-1, min=0, max=2, value=1, dragCommand=lambda x, mode=mode, *args: self.applyKeyTransform('keyTransformSlider%s'%mode, mode), changeCommand=lambda x, mode=mode, *args: self.releaseKeyTransform('keyTransformSlider%s'%mode, mode)) if mode == "default": modeButton = cmds.iconTextButton ("keyTransformSliderButton", style='iconAndTextVertical', w=imageW, h=16, annotation="Key Transform Slider Mode") self.popUpModes() blendToFrameTxtA = cmds.iconTextButton("keyTransformSliderBlendToFrameA", font="smallPlainLabelFont", style='iconAndTextCentered', w=45, label=labelA, align="left", command=lambda *args:self.blendToFrameSet('A'), ann=blendToFrameAnn); self.blendToFramePopUp('A') blendToFrameTxtB = cmds.iconTextButton("keyTransformSliderBlendToFrameB", font="smallPlainLabelFont", style='iconAndTextCentered', w=45, label=labelB, align="right", command=lambda *args:self.blendToFrameSet('B'), ann=blendToFrameAnn); self.blendToFramePopUp('B') else: icon = self.getIcon(mode) modeButton = cmds.iconTextButton("keyTransformSliderButton_%s"%mode, style='iconAndTextVertical', w=imageW, h=16, image= uiMod.getImagePath("keyTransform_%s"%icon), highlightImage= uiMod.getImagePath("keyTransform_%s copy"%icon), command=lambda mode=mode, *args:self.setSliderMode(mode), annotation="Set this mode in the main toolbar") if mode == "blendToFrame": blendToFrameTxtA = cmds.iconTextButton("keyTransformSliderBlendToFrameToolbarA", font="smallPlainLabelFont", style='iconAndTextCentered', w=45, label=labelA, align="left", command=lambda *args:self.blendToFrameSet('A'), ann=blendToFrameAnn); self.blendToFramePopUp('A') blendToFrameTxtB = cmds.iconTextButton("keyTransformSliderBlendToFrameToolbarB", font="smallPlainLabelFont", style='iconAndTextCentered', w=45, label=labelB, align="right", command=lambda *args:self.blendToFrameSet('B'), ann=blendToFrameAnn); self.blendToFramePopUp('B') #pre set buttons preSetDict = {"values":[1., .50, .15, .05], "buttonPositions":[0,10,20,30]} topPos = 60 if mode == "default" else 35 for n, loopValue in enumerate(preSetDict["values"]): value = loopValue buttonPosition = preSetDict["buttonPositions"][n] b = cmds.iconTextButton(style='iconAndTextVertical', w=13, h=13, command=lambda value=value, mode=mode, slider=slider, *args: self.tickKeyTransform(slider, mode, (1.+(value*-1))), ann=int(value*100), image= uiMod.getImagePath('keyTransform_dot_a'), highlightImage= uiMod.getImagePath('keyTransform_dot_a copy')) cmds.formLayout ("keyTransformSliderFormLayout%s"%mode, edit=True, attachPosition=[(b, 'top', 0, topPos), (b, 'left', 0, buttonPosition)]) b = cmds.iconTextButton(style='iconAndTextVertical', w=13, h=13, command=lambda value=value, mode=mode, slider=slider, *args: self.tickKeyTransform(slider, mode, (1.+value)), ann=int(value*100), image= uiMod.getImagePath('keyTransform_dot_a'), highlightImage= uiMod.getImagePath('keyTransform_dot_a copy')) cmds.formLayout ("keyTransformSliderFormLayout%s"%mode, edit=True, attachPosition=[(b, 'top', 0, topPos), (b, 'right', 0, 100-buttonPosition)]) cmds.formLayout ("keyTransformSliderFormLayout%s"%mode, edit=True, attachPosition=[ (modeButton, 'left', 0, 50-buttPerc), (modeButton, 'right', 0, 100-(50-buttPerc)), (modeButton, 'top', -5, 0), (textValue, 'left', 0, 50-buttPerc), (textValue, 'right', 0, 100-(50-buttPerc)), (textValue, 'top', 21, 0), (slider, 'top', -4, 45) ]) # blend to frame if blendToFrameTxtA: cmds.formLayout ("keyTransformSliderFormLayout%s"%mode, edit=True, attachPosition=[ (blendToFrameTxtA, 'left', 0, 0), (blendToFrameTxtB, 'right', 0, 100), (blendToFrameTxtA, 'top', 0, 0), (blendToFrameTxtB, 'top', 0, 0) ]) #ALT SHIFT CTRL if mode != "default": label = utilMod.toTitle(mode).replace("Right", "R").replace("Left", "L") t1 = cmds.text( label=label, align='center', font="smallPlainLabelFont") modButton = cmds.iconTextButton("keyTransformSliderModButton_%s"%mode, style='textOnly', font="smallObliqueLabelFont", label=" ", align="center") self.popUpModifiers(mode) cmds.formLayout ("keyTransformSliderFormLayout%s"%mode, edit=True, h=65, attachPosition=[ (t1, 'left', 0, 0), (t1, 'right', 0, 100), (t1, 'bottom', 15, 100), (modButton, 'left', 0, 0), (modButton, 'right', 0, 100), (modButton, 'bottom', -5, 100), (slider, 'top', 0, 18) ]) cmds.setParent('..') def populateButtons(self): for n, loopMode in enumerate(self.modesDict): mode = loopMode["mode"] divider = n in self.modeDividers if divider: cmds.image(image=uiMod.getImagePath("keyTransform_divider")) cmds.text( label=' ', h=1 ) self.populateSlider(mode) cmds.text( label=' ', h=1 ) self.refreshModifiersButtons() cmds.iconTextButton(style='iconOnly', h=25, w=25, image=uiMod.getImagePath("keyTransform_x"), highlightImage=uiMod.getImagePath("keyTransform_x copy"), command=self.toggleAllModesToolbar, annotation="Hide toolbar") def delWindows(self): for loopWin in self.allWin: if cmds.window(loopWin, query=True, exists=True): cmds.deleteUI(loopWin) if cmds.toolBar(loopWin, query=True, exists=True): cmds.deleteUI(loopWin) def toggleAllModesToolbar(self, *args): if cmds.toolBar(self.toolbarName, query=True, exists=True): self.delWindows() else: self.createWin() #================================= def setBlendToFrameTxtVisible(self, mode, mod=False): visible = (mode == "blendToFrame" and not mod) cmds.iconTextButton("keyTransformSliderBlendToFrameA", edit=True, visible=visible) cmds.iconTextButton("keyTransformSliderBlendToFrameB", edit=True, visible=visible) def blendToFrameSet(self, aB, frame=None): if not frame: frame = int(cmds.currentTime(query=True)) exec("if %s not in self.blendToFrameValues%s: self.blendToFrameValues%s.append(%s)"%(frame, aB, aB, frame)) exec("self.blendToFrameCurrentValue%s = %s"%(aB, frame)) cmds.iconTextButton("keyTransformSliderBlendToFrame%s"%aB, edit=True, label=frame) if cmds.iconTextButton("keyTransformSliderBlendToFrameToolbar%s"%aB, query=True, exists=True): cmds.iconTextButton("keyTransformSliderBlendToFrameToolbar%s"%aB, edit=True, label=frame) def blendToFrameClearHistory(self, *args): self.blendToFrameValuesA = [] self.blendToFrameValuesB = [] self.blendToFrameCurrentValueA = None self.blendToFrameCurrentValueB = None labelA = self.blendToFramelabelA labelB = self.blendToFramelabelB cmds.iconTextButton("keyTransformSliderBlendToFrameA", edit=True, label=labelA) if cmds.iconTextButton("keyTransformSliderBlendToFrameToolbarA", query=True, exists=True): cmds.iconTextButton("keyTransformSliderBlendToFrameToolbarA", edit=True, label=labelA) cmds.iconTextButton("keyTransformSliderBlendToFrameB", edit=True, label=labelB) if cmds.iconTextButton("keyTransformSliderBlendToFrameToolbarB", query=True, exists=True): cmds.iconTextButton("keyTransformSliderBlendToFrameToolbarB", edit=True, label=labelB) def blendToFramePopUp(self, aB): menu = cmds.popupMenu() cmds.popupMenu(menu, edit=True, postMenuCommand=lambda *args:self.populateBlendToFrameHistory(menu, aB)) def populateBlendToFrameHistory(self, menu, aB, *args): uiMod.clearMenuItems(menu) items = sorted(list(set(self.blendToFrameValuesA + self.blendToFrameValuesB))) for loopItem in items: cmds.menuItem(label=loopItem, command=lambda x, aB=aB, loopItem=loopItem, *args: self.blendToFrameSet(aB, loopItem), parent=menu) getCurves = animMod.getAnimCurves() animCurves = getCurves[0] getFrom = getCurves[1] if animCurves: keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom) keyTimes = sorted(utilMod.mergeLists(keyTimes)) if len(keyTimes) > 0: cmds.menuItem(divider=True, parent=menu) subMenu = cmds.menuItem(label="Select Key", subMenu=True, command=self.blendToFrameClearHistory, parent=menu) divider = None currFrame = cmds.currentTime(query=True) for loopItem in keyTimes: loopItem = int(loopItem) if not divider: if loopItem == currFrame: cmds.menuItem(divider=True, parent=subMenu) elif loopItem > currFrame: divider = cmds.menuItem(divider=True, parent=subMenu) cmds.menuItem(label=loopItem, command=lambda x, aB=aB, loopItem=loopItem, *args: self.blendToFrameSet(aB, loopItem), parent=subMenu) if len(items) > 0: cmds.menuItem(divider=True, parent=menu) cmds.menuItem(label="Clear History", command=self.blendToFrameClearHistory, parent=menu) #=================================================================== def getIcon(self, mode): for loopMode in self.modesDict: if mode == loopMode["mode"]: return loopMode["icon"] def popUpModes(self): cmds.popupMenu(postMenuCommand=self.populateModes, button=1) cmds.popupMenu(postMenuCommand=self.populateModes, button=3) def populateModes(self, menu, *args): uiMod.clearMenuItems(menu) cmds.radioMenuItemCollection(parent=menu) sliderMode = self.getSliderMode() for n, loopMode in enumerate(self.modesDict): mode = loopMode["mode"] label = utilMod.toTitle(mode) icon = loopMode["icon"] radioSelected = (sliderMode == mode) divider = n in self.modeDividers if divider: cmds.menuItem(divider=True, parent=menu) cmds.menuItem(label=label, radioButton=radioSelected, command=lambda x, mode=mode, *args: self.setSliderMode(mode), parent=menu) cmds.menuItem(divider=True, parent=menu) cmds.menuItem(label="Toggle All Modes Toolbar", command=self.toggleAllModesToolbar, parent=menu) def popUpModifiers(self, mode): menu = cmds.popupMenu(button=1) cmds.popupMenu(menu, edit=True, postMenuCommand=lambda menu=menu, *args:self.populateModifiers(menu, mode)) menu = cmds.popupMenu(button=3) cmds.popupMenu(menu, edit=True, postMenuCommand=lambda menu=menu, *args:self.populateModifiers(menu, mode)) def populateModifiers(self, menu, mode, *args): uiMod.clearMenuItems(menu) cmds.radioMenuItemCollection(parent=menu) mod = "" radioSelected = (self.getModeModifier(mode) == mod) cmds.menuItem(label="None", radioButton=radioSelected, command=lambda x, mode=mode, mod=mod, *args: self.setModifier(mode, mod), parent=menu) for loopKey in list(self.defaultModifiers.keys()): mod = loopKey label = utilMod.toTitle(mod).replace(" ", "+") radioSelected = (self.getModeModifier(mode) == mod) cmds.menuItem(label=label, radioButton=radioSelected, command=lambda x, mode=mode, mod=mod, *args: self.setModifier(mode, mod), parent=menu) cmds.menuItem(divider=True, parent=menu) cmds.menuItem(label="Load Defaults", command=self.loadDefaultModifiers, parent=menu) def getSliderMode(self, *args): if not G.KT_sliderMode: G.KT_sliderMode = aToolsMod.loadInfoWithUser("userPrefs", "sliderMode") if not G.KT_sliderMode: G.KT_sliderMode = self.defaultMode return G.KT_sliderMode def setModifier(self, mode, mod): for loopKey in list(self.defaultModifiers.keys()): if self.modifiers[loopKey] == mode: self.modifiers[loopKey] = "" self.modifiers[mod] = mode aToolsMod.saveInfoWithUser("userPrefs", "sliderModifiers", self.modifiers) self.refreshModifiersButtons() def loadDefaultModifiers(self, *args): for loopMod in list(self.defaultModifiers.keys()): mode = self.defaultModifiers[loopMod] mod = loopMod self.setModifier(mode, mod) def refreshModifiersButtons(self): for loopMode in self.modesDict: mode = loopMode["mode"] label = "(%s)"%utilMod.toTitle(self.getModeModifier(mode)).replace(" ", "+") if self.getModeModifier(mode) else "..." cmds.iconTextButton("keyTransformSliderModButton_%s"%mode, edit=True, label=label) self.setModifiersAnn() def getModifiers(self): modifiers = aToolsMod.loadInfoWithUser("userPrefs", "sliderModifiers") if not modifiers: modifiers = self.defaultModifiers return modifiers def getModeModifier(self, mode, *args): for loopKey in list(self.defaultModifiers.keys()): if self.modifiers[loopKey] == mode: return loopKey return "" def setModifiersAnn(self): ann = "" for loopKey in list(self.defaultModifiers.keys()): loopMode = self.modifiers[loopKey] if loopMode != "": ann += "%s: %s\n"%(utilMod.toTitle(loopKey).replace(" ", "+"), utilMod.toTitle(loopMode)) sliderAnnotation = "%s\n\n%s\nRight click for options"%(utilMod.toTitle(G.KT_sliderMode), ann) cmds.iconTextButton ("keyTransformSliderButton", edit=True, ann=sliderAnnotation) def getIndex(self, mode): for n, loopMode in enumerate(self.modesDict): if mode in loopMode["mode"]: return n def setSliderMode(self, mode, *args): index = self.getIndex(mode) if not index: index = 0 mode = self.modesDict[index]["mode"] label = utilMod.toTitle(mode) icon = self.modesDict[index]["icon"] G.KT_sliderMode = mode cmds.iconTextButton ("keyTransformSliderButton", edit=True, image= uiMod.getImagePath("keyTransform_%s"%icon), highlightImage= uiMod.getImagePath("keyTransform_%s copy"%icon)) self.setBlendToFrameTxtVisible(mode) self.setModifiersAnn() aToolsMod.saveInfoWithUser("userPrefs", "sliderMode", mode) def getKeyTransformValue(self, slider): value = cmds.floatSlider(slider, query=True, value=True) rValue = 1+((value-1)*abs(value-1)) return rValue def tickKeyTransform(self, slider, mode, tValue, *args): self.applyKeyTransform(slider, mode, tValue, unselectObjects=False) #G.KT_pushClick = False self.releaseKeyTransform(slider, mode) def delayIcon(self, mode): if mode == "default": index = self.getIndex(G.KT_sliderMode) icon = self.modesDict[index]["icon"] cmds.text ("keyTransformSliderText", edit=True, visible=False) cmds.iconTextButton ("keyTransformSliderButton", edit=True, image= uiMod.getImagePath("keyTransform_%s"%icon), highlightImage= uiMod.getImagePath("keyTransform_%s copy"%icon)) self.setBlendToFrameTxtVisible(G.KT_sliderMode, False) else: index = self.getIndex(mode) icon = self.modesDict[index]["icon"] cmds.text ("keyTransformSliderText_%s"%mode, edit=True, visible=False) cmds.iconTextButton ("keyTransformSliderButton_%s"%mode, edit=True, image= uiMod.getImagePath("keyTransform_%s"%icon)) def releaseKeyTransform(self, slider, mode, *args): function = lambda *args:self.releaseKeyTransformDef(slider, mode) G.deferredManager.sendToQueue(function, 1, "KT_release") def releaseKeyTransformDef(self, slider, mode, *args): cmds.floatSlider(slider, edit=True, value=1) mel.eval("toggleAutoLoad graphEditor1OutlineEd true;") G.aToolsBar.timeoutInterval.setTimeout((lambda mode=mode, *args: self.delayIcon(mode)), .5) cmds.undoInfo(stateWithoutFlush=False) #round flat numbers if G.KT_flatKeys: tValue = int(G.KT_lastTValue) G.KT_function(G.KT_gMode, G.KT_animCurves, G.KT_indexes, G.KT_keyValues, G.KT_keyTimes, G.KT_keysSel, G.KT_keyTangentsY, G.KT_keyTangentsX, tValue, G.KT_pushClick) #reset stored values self.optimizedValues = {} G.KT_pushClick = False if len(self.selObjs) > 0: cmds.select(self.selObjs) #cmds.undoInfo(closeChunk=True) cmds.undoInfo(stateWithoutFlush=True) def applyKeyTransform(self, slider, mode, tValue=None, unselectObjects=True, *args): tValue = tValue if tValue is not None else self.getKeyTransformValue(slider) if G.KT_pushClick: if tValue == 0 or tValue == 2: G.KT_lockZero = True if G.KT_lockZero and (.97 < tValue < 1.03): cmds.floatSlider(slider, edit=True, value=1) tValue = 1.0000001 showValue = abs(round((tValue-1.)*100., 2)) if showValue >= 1 or showValue == 0: showValue = int(round(showValue)) if mode == "default": cmds.text ("keyTransformSliderText", edit=True, label=showValue) else: cmds.text ("keyTransformSliderText_%s"%mode, edit=True, label=showValue) if not G.KT_pushClick: #first time mel.eval("toggleAutoLoad graphEditor1OutlineEd false;") G.KT_pushClickDef = False G.KT_lockZero = False G.KT_openChunk = True if mode == "default": cmds.text ("keyTransformSliderText", edit=True, visible=True) else: cmds.text ("keyTransformSliderText_%s"%mode, edit=True, visible=True) mod = uiMod.getModKeyPressed() if mode == "default": mode = self.getSliderMode() if mod: allModifiers = self.getModifiers() modeMod = allModifiers[mod] if modeMod != "": mode = modeMod index = self.getIndex(mode) icon = self.modesDict[index]["icon"] cmds.iconTextButton ("keyTransformSliderButton", edit=True, image=uiMod.getImagePath("keyTransform_%s"%icon)) self.setBlendToFrameTxtVisible(mode, mod) G.KT_gMode = mode index = self.getIndex(mode) function = self.modesDict[index]["function"] G.KT_function = eval("self.%s"%function) G.KT_animCurves = G.KT_indexes = G.KT_keyValues = G.KT_keyTimes = G.KT_keysSel = G.KT_keyTangentsY = G.KT_keyTangentsX = None cmds.undoInfo(openChunk=True) getCurves = animMod.getAnimCurves() G.KT_animCurves = getCurves[0] getFrom = getCurves[1] self.selObjs = [] G.KT_keysSel = animMod.getTarget("keysSel", G.KT_animCurves, getFrom) if G.KT_animCurves: #create key if utilMod.mergeLists(G.KT_keysSel) == []: commandsMod.setSmartKey(animCurves=G.KT_animCurves) G.KT_keysSel = animMod.getTarget("keysSel", G.KT_animCurves, getFrom) G.KT_keyTimes = animMod.getTarget("keyTimes", G.KT_animCurves) G.KT_keyValues = animMod.getTarget("keyValues", G.KT_animCurves) lists = ["G.KT_animCurves", "G.KT_indexes", "G.KT_keyValues", "G.KT_keyTimes", "G.KT_keysSel"] if function not in ["setBlendScaleValues", "setEaseInOut"] : G.KT_keyTangentsY = animMod.getTarget("keyTangentsY", G.KT_animCurves) G.KT_keyTangentsX = animMod.getTarget("keyTangentsX", G.KT_animCurves) lists.extend(["G.KT_keyTangentsY", "G.KT_keyTangentsX"]) #unselect if multiple objects (faster) if getFrom == "timeline": self.selObjs = cmds.ls(selection=True) if len(self.selObjs) > self.maxSelObjs and unselectObjects: cmds.select(self.selObjs[-1]) else: self.selObjs = [] # add tail and head keys for values and times for n, loopCurve in enumerate(G.KT_animCurves): if len(G.KT_keyTimes[n]) == 1: inOffsetTime = 1 inOffsetVal = 0 outOffsetTime = 1 outOffsetVal = 0 else: inOffsetTime = (G.KT_keyTimes[n][1]-G.KT_keyTimes[n][0]) inOffsetVal = (G.KT_keyValues[n][1]-G.KT_keyValues[n][0]) outOffsetTime = (G.KT_keyTimes[n][-1]-G.KT_keyTimes[n][-2]) outOffsetVal = (G.KT_keyValues[n][-1]-G.KT_keyValues[n][-2]) #head keys G.KT_keyValues[n].insert(0, G.KT_keyValues[n][0]-inOffsetVal) G.KT_keyTimes[n].insert(0, G.KT_keyTimes[n][0]-inOffsetTime) G.KT_keyValues[n].insert(0, G.KT_keyValues[n][0]-inOffsetVal) G.KT_keyTimes[n].insert(0, G.KT_keyTimes[n][0]-inOffsetTime) #tail keys G.KT_keyValues[n].append(G.KT_keyValues[n][-1]+outOffsetVal) G.KT_keyTimes[n].append(G.KT_keyTimes[n][-1]+outOffsetTime) G.KT_keyValues[n].append(G.KT_keyValues[n][-1]+outOffsetVal) G.KT_keyTimes[n].append(G.KT_keyTimes[n][-1]+outOffsetTime) G.KT_indexes = [] keysSelTmp = list(G.KT_keysSel) for i, loopCurves in enumerate(G.KT_animCurves): G.KT_indexes.append([]) firstTime = True keysSelTmp[i] = list(G.KT_keysSel[i]) for n, loopkeyTimes in enumerate(G.KT_keyTimes[i]): for loopKeySel in keysSelTmp[i]: if keysSelTmp[i][0] == loopkeyTimes: if firstTime: G.KT_indexes[i].append([]) firstTime = False G.KT_indexes[i][-1].append(n) keysSelTmp[i].pop(0) break else: firstTime = True #add head and tail for G.KT_indexes for i, loopA in enumerate(G.KT_indexes):#each curve for ii, loopB in enumerate(loopA):#each segment G.KT_indexes[i][ii].insert(0, ((G.KT_indexes[i][ii][0])-1)) G.KT_indexes[i][ii].append((G.KT_indexes[i][ii][-1])+1) #===OPTIMIZATION===== #optimize filter keys sel """ if not mode in ["blendToDefault", "scaleFromDefault", "blendToMirror", "blendToFrame"]: for n, loopCurve in enumerate(G.KT_animCurves): for s, segment in enumerate(G.KT_indexes[n]): fi = G.KT_indexes[n][s][0] li = G.KT_indexes[n][s][-1] ti = li - fi fv = G.KT_keyValues[n][fi] lv = G.KT_keyValues[n][li] for x in range(ti-2, -1, -1): v = G.KT_keyValues[n][fi+x+1] if v == fv == lv: del G.KT_keysSel[n][x] #delete empty G.KT_animCurves based on G.KT_keysSel indexToDelete = [] keysSelTmp = list(G.KT_keysSel) for n, loopKeysSel in enumerate(keysSelTmp): if len(loopKeysSel) == 0: indexToDelete.append(n) for loopList in lists: for loopIndex in sorted(indexToDelete, reverse=True): exec("del %s[%s]"%(loopList, loopIndex)) #=============================== """ if G.KT_animCurves: G.KT_pushClick = True function = lambda *args:self.defApply(G.KT_function, [G.KT_gMode, G.KT_animCurves, G.KT_indexes, G.KT_keyValues, G.KT_keyTimes, G.KT_keysSel, G.KT_keyTangentsY, G.KT_keyTangentsX, tValue, G.KT_pushClickDef]) G.deferredManager.removeFromQueue("KT") G.deferredManager.sendToQueue(function, 1, "KT") def defApply(self, function, args): functionStr = "function(" for n, loopArg in enumerate(args): functionStr += "args[%s]"%n if n == len(args)-1: functionStr += ")" else: functionStr += ", " if not G.KT_openChunk: cmds.undoInfo(stateWithoutFlush=False) exec(functionStr) if G.KT_openChunk: cmds.undoInfo(closeChunk=True) #cmds.undoInfo(stateWithoutFlush=False) G.KT_openChunk = False else: cmds.undoInfo(stateWithoutFlush=True) G.KT_pushClickDef = True def setPushValues(self, mode, animCurves, indexes, keyValues, keyTimes, keysSel, keyTangentsY, keyTangentsX, tValue, pushClick): # set values for n, loopCurve in enumerate(animCurves): for s, segment in enumerate(indexes[n]): fv = keyValues[n][indexes[n][s][0]] lv = keyValues[n][indexes[n][s][-1]] tv = lv - fv ff = keyTimes[n][indexes[n][s][0]] lf = keyTimes[n][indexes[n][s][-1]] tf = lf - ff # angle when the slider value is 0 angle = animMod.getAngle(ff, lf, fv, lv) p = tValue for i, loopKeySel in enumerate(indexes[n][s]): if 1 <= i <= len(indexes[n][s])-2: index = indexes[n][s][i]-2 #key v = keyValues[n][index+2] #optimization #if fv == lv == v: continue f = keyTimes[n][index+2] a = ((tv/tf)*(f-ff))+fv nv = ((v-a)*p)+a #tangent iy = keyTangentsY[n][(index)*2] oy = keyTangentsY[n][((index)*2)+1] ix = keyTangentsX[n][(index)*2] ox = keyTangentsX[n][((index)*2)+1] inTangentType = cmds.keyTangent(loopCurve, query=True, index=(index, index), inTangentType=True)[0] outTangentType = cmds.keyTangent(loopCurve, query=True, index=(index, index), outTangentType=True)[0] if inTangentType == "fixed": cmds.keyTangent(loopCurve, index=(index, index), inAngle=angle) if outTangentType == "fixed": cmds.keyTangent(loopCurve, index=(index, index), outAngle=angle) zeroY = cmds.keyTangent(loopCurve, query=True, index=(index, index), iy=True, oy=True) ziy = zeroY[0] zoy = zeroY[1] zeroX = cmds.keyTangent(loopCurve, query=True, index=(index, index), ix=True, ox=True) zix = zeroX[0] zox = zeroX[1] if p <= 1: niy = ziy + (iy * p) - (ziy * p) noy = zoy + (oy * p) - (zoy * p) nix = zix + (ix * p) - (zix * p) nox = zox + (ox * p) - (zox * p) else: niy = iy * p noy = oy * p nix = ix nox = ox # apply cmds.keyframe(loopCurve, index=(index, index), valueChange=nv) if inTangentType == "fixed": cmds.keyTangent(loopCurve, index=(index, index), iy=niy, ix=nix) if outTangentType == "fixed": cmds.keyTangent(loopCurve, index=(index, index), oy=noy, ox=nox) def setNoiseValues(self, mode, animCurves, indexes, keyValues, keyTimes, keysSel, keyTangentsY, keyTangentsX, tValue, pushClick): # set values for n, loopCurve in enumerate(animCurves): for s, segment in enumerate(indexes[n]): p = tValue if p <=1: p=.5+(p/2) for i, loopKeySel in enumerate(indexes[n][s]): if 1 <= i <= len(indexes[n][s])-2: index = indexes[n][s][i]-2 if index < len(keyValues[n])-4: fv = keyValues[n][index+1] lv = keyValues[n][index+3] tv = lv - fv ff = keyTimes[n][index+1] lf = keyTimes[n][index+3] tf = lf - ff #key v = keyValues[n][index+2] f = keyTimes[n][index+2] a = ((tv/tf)*(f-ff))+fv newv = ((v-a)*p)+a #calculate previous and next key pfv = keyValues[n][index-1] plv = keyValues[n][index+2-1] ptv = plv - pfv pff = keyTimes[n][index-1] plf = keyTimes[n][index+2-1] ptf = plf - pff #key pv = keyValues[n][index+2-1] pf = keyTimes[n][index+2-1] pa = ((ptv/ptf)*(pf-pff))+pfv pnv = ((pv-pa)*.5)+pa nfv = keyValues[n][index+1] nlv = keyValues[n][index+2+1] ntv = nlv - nfv nff = keyTimes[n][index+1] nlf = keyTimes[n][index+2+1] ntf = nlf - nff #key nv = keyValues[n][index+2+1] nf = keyTimes[n][index+2+1] na = ((ntv/ntf)*(nf-nff))+nfv nnv = ((nv-na)*.5)+na # angle when the slider value is 0 angle = animMod.getAngle(pf, nf, pnv, nnv) #tangent iy = keyTangentsY[n][(index)*2] oy = keyTangentsY[n][((index)*2)+1] ix = keyTangentsX[n][(index)*2] ox = keyTangentsX[n][((index)*2)+1] inTangentType = cmds.keyTangent(loopCurve, query=True, index=(index, index), inTangentType=True)[0] outTangentType = cmds.keyTangent(loopCurve, query=True, index=(index, index), outTangentType=True)[0] #if pushClick: cmds.undoInfo(stateWithoutFlushG.KT_pushClick if inTangentType == "fixed": cmds.keyTangent(loopCurve, index=(index, index), inAngle=angle) if outTangentType == "fixed": cmds.keyTangent(loopCurve, index=(index, index), outAngle=angle) #if pushClick: cmds.undoInfo(stateWithoutFlush=True) zeroY = cmds.keyTangent(loopCurve, query=True, index=(index, index), iy=True, oy=True) ziy = zeroY[0] zoy = zeroY[1] zeroX = cmds.keyTangent(loopCurve, query=True, index=(index, index), ix=True, ox=True) zix = zeroX[0] zox = zeroX[1] if p <= 1: niy = ziy + (iy * tValue) - (ziy * tValue) noy = zoy + (oy * tValue) - (zoy * tValue) nix = zix + (ix * tValue) - (zix * tValue) nox = zox + (ox * tValue) - (zox * tValue) else: niy = iy * p noy = oy * p nix = ix nox = ox # apply #if pushClick: cmds.undoInfo(stateWithoutFlush=False) cmds.keyframe(loopCurve, index=(index, index), valueChange=newv) if inTangentType == "fixed": cmds.keyTangent(loopCurve, index=(index, index), iy=niy, ix=nix) if outTangentType == "fixed": cmds.keyTangent(loopCurve, index=(index, index), oy=noy, ox=nox) def setBlendScaleValues(self, mode, animCurves, indexes, keyValues, keyTimes, keysSel, keyTangentsY, keyTangentsX, tValue, pushClick): # set values if pushClick: # avoid losing the middle point value if G.KT_lastTValue > 1 and tValue < 1: self.setBlendScaleValues(mode, animCurves, indexes, keyValues, keyTimes, keysSel, keyTangentsY, keyTangentsX, 1.0000001, pushClick) elif G.KT_lastTValue < 1 and tValue > 1: self.setBlendScaleValues(mode, animCurves, indexes, keyValues, keyTimes, keysSel, keyTangentsY, keyTangentsX, 1, pushClick) if mode == "default": mode = self.getSliderMode() p = tValue*2-1 if mode == "blendToMirror": mirrorCurves = animMod.getMirrorObjs(animCurves) if not pushClick: self.invertRules = Mirror.getInvertRules() if mode == "blendToFrame": if tValue <=1: if not self.blendToFrameCurrentValueA: if tValue <=.97: cmds.warning("You need to select a frame first. Please go to some frame and hit the button A") return else: if not self.blendToFrameCurrentValueB: if tValue >=1.03: cmds.warning("You need to select a frame first. Please go to some frame and hit the button B") return if "blend" in mode: if tValue <=1: p = tValue else: p = 2-tValue if p == 0 and not G.KT_flatKeys: p = 0.0000001 G.KT_flatKeys = True else: G.KT_flatKeys = False if pushClick: # second time on if G.KT_lastValue == 0: G.KT_scaleValue = p else: G.KT_scaleValue = 1/G.KT_lastValue*p else: #just first time G.KT_scaleValue = p for n, loopCurve in enumerate(animCurves): if mode == "blendToFrame": if tValue <=1: f = self.blendToFrameCurrentValueA else: f = self.blendToFrameCurrentValueB if loopCurve not in self.optimizedValues: self.optimizedValues[loopCurve] = {} if f not in self.optimizedValues[loopCurve]: self.optimizedValues[loopCurve][f] = cmds.keyframe(loopCurve, query=True, eval=True, time=(f,f), valueChange=True)[0] pivot = self.optimizedValues[loopCurve][f] if mode == "blendToDefault": if loopCurve not in self.defaultValues: pivot = animMod.getDefaultValue(loopCurve) self.defaultValues[loopCurve] = pivot else: pivot = self.defaultValues[loopCurve] if mode == "blendToMirror": mCurve = mirrorCurves[n] isCenterCurve = (mCurve == None) if isCenterCurve: mCurve = loopCurve if not cmds.objExists(mCurve): continue if not pushClick: mirrorInvertValue = Mirror.mirrorInvert(loopCurve, isCenterCurve, self.invertRules) if mode == "scaleFromDefault": if loopCurve not in self.defaultValues: pivot = animMod.getDefaultValue(loopCurve) self.defaultValues[loopCurve] = pivot else: pivot = self.defaultValues[loopCurve] for s, segment in enumerate(indexes[n]): if mode == "blendToNeighbors": fv = keyValues[n][indexes[n][s][0]] lv = keyValues[n][indexes[n][s][-1]] if mode == "scaleFromAverage": segValues = [] for loopIndex in indexes[n][s]: segValues.append(keyValues[n][loopIndex]) segValues.pop(0) segValues.remove(segValues[-1]) maxV = max(segValues) minV = min(segValues) pivot = (maxV+minV)/2 if mode == "scaleFromNeighborLeft": fv = keyValues[n][indexes[n][s][0]] pivot = fv if mode == "scaleFromNeighborRight": lv = keyValues[n][indexes[n][s][-1]] pivot = lv for i, loopKeySel in enumerate(indexes[n][s]): if 1 <= i <= len(indexes[n][s])-2: index = indexes[n][s][i]-2 v = keyValues[n][index+2] if mode == "blendToNeighbors": if tValue <=1: pivot = fv else: pivot = lv if mode == "blendToMirror": f = keyTimes[n][index+2] if not pushClick: if isCenterCurve: pivot = v * mirrorInvertValue else: pivot = cmds.keyframe(mCurve, query=True, eval=True, time=(f,f), valueChange=True)[0] * mirrorInvertValue if mCurve not in self.optimizedValues: self.optimizedValues[mCurve] = {} self.optimizedValues[mCurve][f] = pivot else: pivot = self.optimizedValues[mCurve][f] #optimization #if v == pivot: continue # apply=============================================== cmds.scaleKey(loopCurve, index=(index, index), valuePivot=pivot, valueScale=G.KT_scaleValue) G.KT_lastValue = p G.KT_lastTValue = tValue def setEaseInOut(self, mode, animCurves, indexes, keyValues, keyTimes, keysSel, keyTangentsY, keyTangentsX, tValue, pushClick): for n, loopCurve in enumerate(animCurves): for s, segment in enumerate(indexes[n]): fv = keyValues[n][indexes[n][s][0]] lv = keyValues[n][indexes[n][s][-1]] tv = lv - fv ff = keyTimes[n][indexes[n][s][0]] lf = keyTimes[n][indexes[n][s][-1]] tf = lf - ff strenght = (tValue-1)*100 for i, loopKeySel in enumerate(indexes[n][s]): if 1 <= i <= len(indexes[n][s])-2: index = indexes[n][s][i]-2 currTime = keyTimes[n][index+2] - ff timePos = currTime/tf maxStr = 10. str = (abs(strenght)/100.)*(maxStr-1)+1 outValue = tv*(((abs(timePos-1))**str)*-1 + 1) + fv inValue = tv*(timePos**str) + fv if strenght > 0: value = outValue else: value = inValue # apply #if pushClick: cmds.undoInfo(stateWithoutFlush=False) cmds.keyframe(loopCurve ,edit=True, index=(index, index), valueChange=value) #if pushClick: cmds.undoInfo(stateWithoutFlush=True) #========================================================================== class KeyTransform(object): def __init__(self): if G.aToolsBar.keyTransform: return G.aToolsBar.keyTransform = self def setPrecisionValue(self, n, *args): cmds.floatField("precisionNumber", edit=True, value=n) def getPrecisionValue(self, *args): return cmds.floatField("precisionNumber", query=True, value=True) def applyPrecise(self, tValue, *args): getCurves = animMod.getAnimCurves() animCurves = getCurves[0] getFrom = getCurves[1] keysSel = animMod.getTarget("keysSel", animCurves, getFrom) keyTimes = animMod.getTarget("keyTimes", animCurves) if animCurves: for n, loopCurve in enumerate(animCurves): if getFrom == "timeline": time = [animMod.getTimelineTime()] else: time = [(loopTime,loopTime) for loopTime in keysSel[n]] for loopTime in time: cmds.setKeyframe(loopCurve, time=loopTime, insert=True) value = cmds.keyframe(loopCurve, query=True, time=loopTime, valueChange=True)[0] cmds.keyframe(loopCurve, edit=True, time=loopTime, valueChange=value+tValue) def resetValue(self, trs=[], *args): getCurves = animMod.getAnimCurves() animCurves = getCurves[0] getFrom = getCurves[1] if animCurves: keysSel = animMod.getTarget("keysSel", animCurves, getFrom) for n, loopCurve in enumerate(animCurves): if trs != []: apply = False for loopTrs in trs: if eval("animMod.isAnimCurve%s(loopCurve)"%loopTrs): apply = True break if not apply: continue time = [(loopTime,loopTime) for loopTime in keysSel[n]] value = animMod.getDefaultValue(loopCurve) if getFrom == "timeline" and len(time) ==0: time = [animMod.getTimelineTime()] for loopTime in time: cmds.setKeyframe(loopCurve, time=loopTime, insert=False) cmds.keyframe(loopCurve, edit=True, time=loopTime, valueChange=value) tangType = cmds.keyTangent(loopCurve, query=True, time=loopTime, inTangentType=True, outTangentType=True) if tangType[1] != "step": cmds.keyTangent(loopCurve, time=loopTime, inTangentType="auto", outTangentType="auto") else: objects = animMod.getObjsSel() if objects: channelboxSelObjs = animMod.channelBoxSel() if channelboxSelObjs: for loopObjAttr in channelboxSelObjs: value = animMod.getDefaultValue(loopObjAttr) cmds.setAttr(loopObjAttr, value) else: allChannels = animMod.getAllChannels(objects) for n, loopObj in enumerate(allChannels): if not loopObj or len(loopObj) == 0: continue for loopAttr in loopObj: objAttr = "%s.%s"%(objects[n], loopAttr) if not cmds.objExists(objAttr):continue if not cmds.getAttr(objAttr, settable=True): continue value = animMod.getDefaultValue(objAttr) cmds.setAttr(objAttr, value) def shareEachOtherKeys(self, keys="selected", *args): cmds.waitCursor(state=True) getCurves = animMod.getAnimCurves() animCurves = getCurves[0] getFrom = getCurves[1] if keys == "selected": keysSel = animMod.getTarget("keysSel", animCurves, getFrom) else: keysSel = animMod.getTarget("keyTimes", animCurves, getFrom) blendKeys = utilMod.mergeLists(keysSel) animMod.createDummyKey(select=True) getCurves = animMod.getAnimCurves(True) animCurves = getCurves[0] #key for loopKey in blendKeys: if animCurves: time = (loopKey, loopKey) cmds.setKeyframe(animCurves, time=time, insert=True) animMod.deleteDummyKey() cmds.waitCursor(state=False) def inbetween(self, value, mode="add", *args): getCurves = animMod.getAnimCurves() animCurves = getCurves[0] getFrom = getCurves[1] keysIndexSel = animMod.getTarget("keysIndexSel", animCurves, getFrom) keyIndexTimes = animMod.getTarget("keyIndexTimes", animCurves) currentTime = cmds.currentTime(query=True) if animCurves: for n, loopCurve in enumerate(animCurves): maxIndex = max([max(key) for key in keyIndexTimes]) if len(keysIndexSel[n]) == 0:#no keys selected prevKey = cmds.findKeyframe(loopCurve, time=(currentTime, currentTime), which="previous") prevIndex = cmds.keyframe(loopCurve, query=True, time=(prevKey, prevKey), indexValue=True)[0] keysIndexSel[n].append(prevIndex) tailIndex = keysIndexSel[n][-1]+1 if tailIndex <= maxIndex and len(keysIndexSel[n]) == 1: keysIndexSel[n].append(tailIndex) keysIndexSel[n].remove(keysIndexSel[n][0]) for loopIndex in keysIndexSel[n]: seqIndex = (loopIndex, maxIndex) if mode=="add": #check intersection cmds.keyframe(loopCurve, option="over", relative=True, index=seqIndex, timeChange=value) elif mode=="set": index = (loopIndex-1, loopIndex-1) curKey = cmds.keyframe(loopCurve, query=True, index=index, timeChange=True)[0] nextKey = cmds.findKeyframe(loopCurve, time=(curKey,curKey), which="next") setValue = value-(nextKey-curKey) cmds.keyframe(loopCurve, option="over", relative=True, index=seqIndex, timeChange=setValue) def inbetweenUI(self, *args): windowName = "setInbetweenWin" widthHeight = (90, 90) if cmds.window(windowName, query=True, exists=True): cmds.deleteUI(windowName) window = cmds.window(windowName, title="Set Inbetween", widthHeight=widthHeight) cmds.gridLayout(numberOfColumns=3, cellWidthHeight=(30, 30)) for n in range(9): num = n+1 cmds.button(label=str(num), command=lambda num=num, *args: self.inbetween(num, "set")) cmds.showWindow(window) cmds.window(window, edit=True, widthHeight=widthHeight) class Nudge(object): def __init__(self): if G.aToolsBar.nudge: return G.aToolsBar.nudge = self self.applyToEverything = False def popupMenu(self, leftRight): cmds.popupMenu(postMenuCommand=lambda *args:self.populateMenu(leftRight, args)) def populateMenu(self, leftRight, *args): menu = args[0][0] uiMod.clearMenuItems(menu) values = [2,4,10,20,50,100] for loopValue in values: if leftRight == "left": loopValue = loopValue*-1 cmds.menuItem (label=abs(loopValue), command=lambda x, loopValue=loopValue, *args: self.nudgeKey(loopValue), parent=menu) cmds.menuItem (label="Custom", command=lambda *args: self.toggleEnterField(True), parent=menu) cmds.menuItem(divider=True, parent=menu ) cmds.menuItem (label="Nudge Everything in the Scene", checkBox=self.applyToEverything, command=lambda *args: self.toggleEnterField(True, args), parent=menu) def toggleEnterField(self, onOff=True, *args): self.applyToEverything = False if len(args) > 0: onOff = args[0][0] self.applyToEverything = onOff if onOff: cmds.floatField ("nudgeEnterField", edit=True, visible=True, w=50) return cmds.floatField ("nudgeEnterField", edit=True, visible=False, w=1) def nudgeKey(self, value, *args): if cmds.floatField ("nudgeEnterField", query=True, visible=True): if abs(value) == 1: value = cmds.floatField ("nudgeEnterField", query=True, value=True) * value if self.applyToEverything: self.nudgeEverything(value) return getCurves = animMod.getAnimCurves() animCurves = getCurves[0] getFrom = getCurves[1] keyExists = None keysSel = animMod.getTarget("keysSel", animCurves, getFrom) if animCurves: if getFrom == "timeline": range = animMod.getTimelineRange() time = (range[0], range[1]) prevKey = cmds.findKeyframe(time=(range[0],range[0]), which="previous") nextKey = cmds.findKeyframe(time=(range[1]-1,range[1]-1), which="next") currentTime = cmds.currentTime(query=True) # prevents first and last keys bug if prevKey >= time[0]: prevKey -=2 if nextKey <= time[1]: nextKey +=2 #check if keySel has something for loopArray in keysSel: if len(loopArray) > 0: keyExists = True break if keyExists: if time[0]+value > prevKey and time[1]+value < nextKey: cmds.keyframe(animCurves, option="over", relative=True, time=time, timeChange=value) cmds.currentTime(currentTime+value) else: if value > 0: time = (prevKey, prevKey) value = currentTime else: time = (nextKey, nextKey) value = currentTime cmds.keyframe(animCurves, option="over", relative=False, time=time, timeChange=value) else: cmds.keyframe(animation="keys", option="over", relative=True, timeChange=value) cmds.snapKey(animation="keys") #-------- self.toggleEnterField(False) def nudgeEverything(self, value): cmds.waitCursor(state=True) allCurvesinScene = cmds.ls(type=["animCurveTA","animCurveTL","animCurveTT","animCurveTU"]) cmds.keyframe(allCurvesinScene, option="over", relative=True, timeChange=value) self.toggleEnterField(False) cmds.waitCursor(state=False)