Updated
This commit is contained in:
4
Scripts/Animation/aTools/animTools/animBar/__init__.py
Normal file
4
Scripts/Animation/aTools/animTools/animBar/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import *
|
174
Scripts/Animation/aTools/animTools/animBar/animBarUI.py
Normal file
174
Scripts/Animation/aTools/animTools/animBar/animBarUI.py
Normal file
@ -0,0 +1,174 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
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, located in the folder aTools
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
# maya modulesspecialTools
|
||||
import importlib
|
||||
from maya import cmds
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.generalTools import aToolsClasses; importlib.reload(aToolsClasses)
|
||||
from aTools.commonMods import animMod; importlib.reload(animMod)
|
||||
from aTools.generalTools import generalToolsUI; importlib.reload(generalToolsUI)
|
||||
from aTools.commonMods import utilMod; importlib.reload(utilMod)
|
||||
from aTools.commonMods import commandsMod; importlib.reload(commandsMod)
|
||||
from aTools.commonMods import aToolsMod; importlib.reload(aToolsMod)
|
||||
from aTools import setup; importlib.reload(setup)
|
||||
|
||||
# constants
|
||||
SUB_UI_MODS = ["tweenMachine", "keyTransform", "tangents", "specialTools", "tUtilities"]
|
||||
|
||||
# import subUI modules
|
||||
for loopMod in SUB_UI_MODS:
|
||||
exec("import aTools.animTools.animBar.subUIs.%s as %s; importlib.reload(%s)"%(loopMod, loopMod, loopMod))
|
||||
|
||||
def show(mode="show"):
|
||||
|
||||
G.aToolsBar = G.aToolsBar or AnimationBar_Gui()
|
||||
|
||||
if mode == False: mode = "show"
|
||||
if mode == True: mode = "toggle"
|
||||
|
||||
if mode == "launch":
|
||||
lastState = aToolsMod.loadInfoWithUser("userPrefs", "animationBarLastState")
|
||||
if lastState: show()
|
||||
return
|
||||
|
||||
|
||||
if mode == "show" or mode == "hide":
|
||||
if cmds.toolBar("aTools_Animation_Bar", query=True, exists=True):
|
||||
visible = (mode == "show")
|
||||
cmds.toolBar("aTools_Animation_Bar", edit=True, visible=visible)
|
||||
G.aToolsBar.saveLastState(visible)
|
||||
return
|
||||
elif mode == "show":
|
||||
G.aToolsBar.start()
|
||||
G.aToolsBar.saveLastState()
|
||||
return
|
||||
|
||||
|
||||
if mode == "toggle":
|
||||
if cmds.toolBar("aTools_Animation_Bar", query=True, exists=True):
|
||||
state = cmds.toolBar("aTools_Animation_Bar", query=True, visible=True)
|
||||
visible = (not state)
|
||||
G.aToolsBar.toggleToolbars(visible)
|
||||
cmds.toolBar("aTools_Animation_Bar", edit=True, visible=visible)
|
||||
G.aToolsBar.saveLastState(visible)
|
||||
return
|
||||
else:
|
||||
show()
|
||||
return
|
||||
|
||||
if mode == "refresh":
|
||||
G.aToolsBar = AnimationBar_Gui()
|
||||
G.aToolsBar.start()
|
||||
G.aToolsBar.saveLastState()
|
||||
|
||||
|
||||
|
||||
class AnimationBar_Gui(object):
|
||||
|
||||
def __init__(self):
|
||||
self.winName = "aAnimationBarWin"
|
||||
self.toolbarName = "aTools_Animation_Bar"
|
||||
self.allWin = [self.winName, self.toolbarName]
|
||||
self.buttonSize = {"small":[15, 20], "big":[25, 25]}
|
||||
self.barOffset = 0
|
||||
self.barHotkeys = {}
|
||||
G.aToolsUIs = {"toolbars":[
|
||||
|
||||
],
|
||||
"windows":[
|
||||
|
||||
]}
|
||||
|
||||
# [ SUBUIs ]
|
||||
self.uiList = None
|
||||
self.subUIs = None
|
||||
|
||||
def __getattr__(self, attr):
|
||||
return None
|
||||
|
||||
def start(self):
|
||||
|
||||
from aTools.generalTools import aToolsClasses; importlib.reload(aToolsClasses)
|
||||
self.startUpFunctions()
|
||||
self.delWindows()
|
||||
self.createWin()
|
||||
|
||||
def startUpFunctions(self):
|
||||
#wait cursor state
|
||||
n = 0
|
||||
while True:
|
||||
if not cmds.waitCursor(query=True, state=True) or n > 100: break
|
||||
cmds.waitCursor(state=False)
|
||||
n += 1
|
||||
|
||||
#refresh state
|
||||
cmds.refresh(suspend=False)
|
||||
#undo state
|
||||
if not cmds.undoInfo(query=True, stateWithoutFlush=True): cmds.undoInfo(stateWithoutFlush=True)
|
||||
#progress bar state
|
||||
utilMod.setProgressBar(status=None, progress=None, endProgress=True)
|
||||
|
||||
|
||||
def saveLastState(self, state=True):
|
||||
aToolsMod.saveInfoWithUser("userPrefs", "animationBarLastState", state)
|
||||
|
||||
def createWin(self):
|
||||
|
||||
# Creates window
|
||||
self.mainWin = cmds.window(self.winName, sizeable=True)
|
||||
|
||||
# Main frame
|
||||
cmds.frameLayout("mainFrameLayout", labelVisible=False, borderVisible=False, w=10, marginHeight=0, marginWidth=0, labelIndent=0, collapsable=False)
|
||||
cmds.rowLayout(numberOfColumns=2, adjustableColumn=1, columnAttach=([2, 'right', self.barOffset]), h=37)
|
||||
cmds.text(label="")
|
||||
self.subUIsLayout = cmds.rowLayout("mainLayout", numberOfColumns=len(SUB_UI_MODS)+2)
|
||||
|
||||
# subUIs
|
||||
self.uiList = [eval("%s.%s%s_Gui"%(loopUi, loopUi[0].upper(), loopUi[1:])) for loopUi in SUB_UI_MODS]
|
||||
# append general tools ui
|
||||
self.uiList.append(generalToolsUI.GeneralTools_Gui)
|
||||
# define subUis
|
||||
self.subUIs = [loopUi(self.subUIsLayout, self.buttonSize) for loopUi in self.uiList]
|
||||
|
||||
self.addSubUIs()
|
||||
|
||||
# shows toolbar
|
||||
cmds.toolBar(self.toolbarName, area='bottom', content=self.mainWin, allowedArea=['bottom'])
|
||||
|
||||
# end method createWin
|
||||
#---------------------------------------------------------------------
|
||||
def addSubUIs(self):
|
||||
# parent subUis to the main layout
|
||||
for loopIndex, loopSubUI in enumerate(self.subUIs):
|
||||
loopSubUI.createLayout()
|
||||
# space
|
||||
if loopIndex < len(self.subUIs) -1:
|
||||
cmds.rowLayout(numberOfColumns=2)
|
||||
cmds.text( label=' ', h=1 )
|
||||
|
||||
# end for
|
||||
|
||||
def toggleToolbars(self, visible):
|
||||
pass
|
||||
|
||||
def delWindows(self, onOff=True, forceOff=False):
|
||||
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)
|
||||
|
@ -0,0 +1 @@
|
||||
|
1490
Scripts/Animation/aTools/animTools/animBar/subUIs/keyTransform.py
Normal file
1490
Scripts/Animation/aTools/animTools/animBar/subUIs/keyTransform.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
||||
|
||||
|
305
Scripts/Animation/aTools/animTools/animBar/subUIs/tUtilities.py
Normal file
305
Scripts/Animation/aTools/animTools/animBar/subUIs/tUtilities.py
Normal 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.")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
770
Scripts/Animation/aTools/animTools/animBar/subUIs/tangents.py
Normal file
770
Scripts/Animation/aTools/animTools/animBar/subUIs/tangents.py
Normal 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)
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user