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

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
# Get the current file's directory
current_dir = os.path.dirname(os.path.abspath(__file__))
# Get the Scripts directory
scripts_dir = os.path.dirname(os.path.dirname(current_dir))
# Add the Scripts and Animation directories to sys.path if they're not already there
if scripts_dir not in sys.path:
sys.path.append(scripts_dir)
if current_dir not in sys.path:
sys.path.append(current_dir)
print(f"aTools __init__.py - Current directory: {current_dir}")
print(f"aTools __init__.py - sys.path: {sys.path}")
# Import aTools submodules
try:
from . import animTools
print("Attempting to import animTools")
from . import commonMods
print("Attempting to import commonMods")
from . import generalTools
print("Attempting to import generalTools")
print("Successfully imported aTools main submodules")
# Import specific submodules
from animTools.animBar import animBarUI
from animTools import animationCrashRecovery, framePlaybackRange, jumpToSelectedKey
from commonMods import animMod, aToolsMod, commandsMod, uiMod, utilMod
from generalTools import aToolsClasses, aToolsGlobals, generalToolsUI, hotkeys, offlineInstall, tumbleOnObjects
print("Successfully imported aTools specific submodules")
except ImportError as e:
print(f"Warning: Unable to import aTools submodules: {str(e)}")
print(f"Current sys.path: {sys.path}")
# Print debug information
print(f"aTools successfully imported. Current directory: {current_dir}")
print(f"sys.path: {sys.path}")

View File

@@ -0,0 +1,175 @@
// ========================================================================================================================
// 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
//
// ========================================================================================================================
python("\n\
#aTools_install.mel\n\
\n\
from maya import cmds, mel\n\
import os, shutil, urllib.request, urllib.error, urllib.parse, shutil, zipfile, importlib\n\
\n\
def hasInternet(url):\n\
try:\n\
proxy = urllib.request.ProxyHandler({})\n\
opener = urllib.request.build_opener(proxy)\n\
urllib.request.install_opener(opener)\n\
response = urllib.request.urlopen(url, timeout=60)\n\
return True\n\
except: pass\n\
return False\n\
\n\
def launchInstall():\n\
INSTALL_URL = 'https://raw.githubusercontent.com/MKlimenko/aTools_python3/master/aToolsInstall.py' \n\
aToolsInstall = None\n\
if hasInternet(INSTALL_URL):\n\
try: \n\
aToolsInstall = urllib.request.urlopen(INSTALL_URL, timeout=60).read()\n\
except IOError: pass\n\
if aToolsInstall: exec(aToolsInstall)\n\
else: \n\
cmds.confirmDialog(title=\"aTools Install\", message=\"Internet connection not detected, offline installation will begin.\\n\\nIf you want aTools to auto update in the future, configure your firewall so that Maya can access the internet.\", button=\"Next\")\n\
offlineInstallWindow()\n\
\n\
\n\
def offlineInstallWindow():\n\
windowName = 'aToolsOfflineInstallationWindow'\n\
w = 500\n\
aToolsZipURL = 'https://github.com/MKlimenko/aTools_python3/releases/download/v2.04/aTools.zip'\n\
delWindow(windowName)\n\
window = cmds.window(windowName, title='aTools - Offline Installation')\n\
form = cmds.formLayout(numberOfDivisions=100)\n\
pos = 10 \n\
elements = [] \n\
elements.append([cmds.text( label='aTools - Offline Installation Instructions:', font='boldLabelFont'), 0])\n\
elements.append([cmds.text(label=\'1) Download <a href=\\'%s\\'>aTools.zip</a>\'%aToolsZipURL, align='left', hyperlink=True), 30])\n\
elements.append([cmds.text(label=\'In case you don\\'t have internet access at all, use the link below somewhere else.\', align='left'), 15])\n\
elements.append([cmds.textField(text=aToolsZipURL, w=w-20, editable=False), 20])\n\
elements.append([cmds.text(label=\'2) Create a folder for aTools.zip and keep the file there, aTools will remember this\\nlocation to install updates automatically. All you\\'ll need to do is replace aTools.zip when\\nnew versions come out. Subscribe in the above link to receive alerts.\', align='left'), 40])\n\
elements.append([cmds.text(label=\'If more people in your network are going to install aTools, place aTools.zip in a folder that\\neveryone has access to, so only one person will need to keep aTools.zip up-to-date.\', align='left'), 45])\n\
elements.append([cmds.text(label='3) OK, so where did you put it?', align='left'), 45])\n\
elements.append([cmds.rowLayout(numberOfColumns=3), 20])\n\
cmds.textField('aToolsZipField', text='...aTools.zip', w=w-85)\n\
cmds.button(label='Browse', command=browse, w=60)\n\
cmds.setParent('..')\n\
elements.append([cmds.button( label='Install aTools', w=150, command=lambda *args:install(windowName)), 30])\n\
\n\
for loopElement in elements:\n\
element = loopElement[0]\n\
pos += loopElement[1]\n\
cmds.formLayout(form, edit=True, attachForm=[(element, 'top', pos), (element, 'left', 10)] )\n\
\n\
cmds.showWindow(window) \n\
cmds.window(windowName, edit=True, widthHeight=(w, pos+40))\n\
\n\
\n\
def browse(*args):\n\
result = cmds.fileDialog2(fileFilter='aTools.zip', dialogStyle=2, fileMode=1, okCaption='OK')\n\
if result: cmds.textField('aToolsZipField', edit=True, text=result[0])\n\
\n\
def install(windowName):\n\
offlineFilePath = formatPath(cmds.textField('aToolsZipField', query=True, text=True))\n\
if offlineFilePath.split(os.sep)[-1] != 'aTools.zip':\n\
cmds.confirmDialog(message='Only aTools.zip is acceptable. Rename the file if needed.')\n\
return\n\
if not os.path.isfile(offlineFilePath): \n\
cmds.confirmDialog(message=\'Couldn\\'t find aTools.zip in there, please check if the path is correct.\')\n\
return\n\
delWindow(windowName)\n\
aToolsOfflineInstall(offlineFilePath)\n\
\n\
def delWindow(windowName):\n\
if cmds.window(windowName, query=True, exists=True): cmds.deleteUI(windowName)\n\
\n\
\n\
\n\
def formatPath(path):\n\
path = path.replace('/', os.sep)\n\
path = path.replace('\\\\', os.sep)\n\
return path\n\
\n\
def download(downloadUrl, saveFile):\n\
\n\
try: response = urllib.request.urlopen(downloadUrl, timeout=60) \n\
except: pass\n\
\n\
if response is None: \n\
cmds.warning('Error trying to install.')\n\
return \n\
\n\
fileSize = int(response.info().get('Content-Length')[0])\n\
fileSizeDl = 0\n\
blockSize = 128\n\
output = open(saveFile,'wb') \n\
progBar = mel.eval('$tmp = $gMainProgressBar') \n\
\n\
cmds.progressBar( progBar,\n\
edit=True,\n\
beginProgress=True,\n\
status='Downloading aTools...',\n\
progress=0,\n\
maxValue=100 ) \n\
\n\
while True:\n\
buffer = response.read(blockSize)\n\
if not buffer:\n\
output.close()\n\
cmds.progressBar(progBar, edit=True, progress=100) \n\
cmds.progressBar(progBar, edit=True, endProgress=True) \n\
break\n\
\n\
fileSizeDl += len(buffer)\n\
output.write(buffer)\n\
p = float(fileSizeDl) / fileSize *100\n\
\n\
cmds.progressBar(progBar, edit=True, progress=p) \n\
\n\
return output\n\
\n\
\n\
def aToolsOfflineInstall(offlineFilePath):\n\
\n\
mayaAppDir = mel.eval('getenv MAYA_APP_DIR') \n\
aToolsPath = mayaAppDir + os.sep + 'scripts'\n\
aToolsFolder = aToolsPath + os.sep + 'aTools' + os.sep\n\
tmpZipFile = '%s%stmp.zip'%(aToolsPath, os.sep)\n\
offlineFileUrl = r'file:///%s'%offlineFilePath\n\
\n\
if os.path.isfile(tmpZipFile): os.remove(tmpZipFile) \n\
if os.path.isdir(aToolsFolder): shutil.rmtree(aToolsFolder) \n\
\n\
output = download(offlineFileUrl, tmpZipFile) \n\
\n\
zfobj = zipfile.ZipFile(tmpZipFile)\n\
for name in zfobj.namelist():\n\
uncompressed = zfobj.read(name)\n\
\n\
filename = formatPath('%s%s%s'%(aToolsPath, os.sep, name)) \n\
d = os.path.dirname(filename)\n\
\n\
if not os.path.exists(d): os.makedirs(d)\n\
if filename.endswith(os.sep): continue\n\
\n\
output = open(filename,'wb')\n\
output.write(uncompressed)\n\
output.close()\n\
\n\
zfobj.close()\n\
if os.path.isfile(tmpZipFile): os.remove(tmpZipFile)\n\
from aTools import setup; importlib.reload(setup); setup.install([offlineFilePath, True]) \n\
cmds.confirmDialog(message=\'A file aTools_offline_install.mel has been created in the same aTools.zip location. If other people in your network are installing aTools, just ask them to drag\\'n drop this file into Maya\\'s viewport.\')\n\
cmds.evalDeferred(\"from aTools.animTools.animBar import animBarUI; importlib.reload(animBarUI); animBarUI.show(\\'refresh\\')\") \n\
\n\
\n\
launchInstall()\n\
");

View File

@@ -0,0 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from . import animBar
from . import animationCrashRecovery
from . import framePlaybackRange
from . import jumpToSelectedKey

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from . import *

View 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)

View File

@@ -0,0 +1 @@

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,971 @@
'''
========================================================================================================================
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 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
from aTools.commonMods import aToolsMod
import os
import time
import datetime
import math
class AnimationCrashRecovery(object):
def __init__(self):
G.animationCrashRecovery = self
self.deferredQueue = []
self.animCurvesNames = []
self.animCurvesInfo = {}
self.nonKeyedAttrInfo = {}
self.baseFolderName = "animationCrashRecovery"
self.baseLatestFolderName = "latest"
self.baseBackupFolderName = "backup"
self.infoDataFileName = "infoData"
self.selectedObjs = []
self.ignoreAttrs = ["visibility"]
self.curveExt = "curve"
self.attrExt = "attr"
self.curvesInFile = []
self.nonKeyedAttrsInFile = []
self.mayaFileName = None
self.pause = False
self.mayaFileName = utilMod.getMayaFileName()
self.mayaFilePath = utilMod.getMayaFileName("path")
G.ACR_messages = G.ACR_messages or {"anim":[], "node":[], "scene":[], "mdg":[]}
self.blinkingLedState = False
self.saveRecommended = True
self.checkNodeCreated = True
G.lastSaveWarning = G.lastSaveWarning or None
self.redBlinkingSecs = 300#300 = 5 minutes
self.daysToKeepOldFiles = 5*86400#5days
self.nodesCreated = []
#self.daysToKeepOldFiles = 10#TMP
self.checkForCrashLog()
self.checkAndClearOldFiles()
#G.deferredManager.removeFromQueue("ACR")#TMP
def switch(self, onOff):
self.removeMessages()
utilMod.killScriptJobs("G.animationCrashRecoveryScriptJobs")
if onOff:
#self.saveAllAnimationData(update=True)
self.addAnimSceneMessages()
self.addNodeMessages()
self.addMdgMessages()
G.animationCrashRecoveryScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.addNodeMessages )))
self.recommendSaving(True)
#self.recommendSaving(False)#TMP
else:
G.deferredManager.removeFromQueue("ACR")
self.setLed("off")
def setLed(self, state):
if not cmds.image("animationCrashRecoveryLed", query=True, exists=True): return
self.blinkingRed(False)
if state == "on":
if self.saveRecommended:
image = "ACR_red"
ann = "Animation Crash Recovery recommends you to save"
G.lastSaveWarning = time.time() if not G.lastSaveWarning else G.lastSaveWarning
if time.time() - G.lastSaveWarning >= self.redBlinkingSecs: self.blinkingRed(True)
else:
image = "ACR_green"
ann = "Animation Crash Recovery is ON"
G.lastSaveWarning = None
cmds.image("animationCrashRecoveryLed", edit=True, image= uiMod.getImagePath(image), ann=ann)
elif state == "off":
cmds.image("animationCrashRecoveryLed", edit=True, image= uiMod.getImagePath("ACR_off"), ann="Animation Crash Recovery is OFF")
elif state == "blinking":
self.blinkingLedState = not self.blinkingLedState
image = "ACR_white_half" if self.blinkingLedState else "ACR_white_bright"
cmds.image("animationCrashRecoveryLed", edit=True, image= uiMod.getImagePath(image), ann="Animation Crash Recovery is saving animation")
elif state == "blinking_red":
self.blinkingLedState = not self.blinkingLedState
image = "ACR_red_half" if self.blinkingLedState else "ACR_red_bright"
cmds.image("animationCrashRecoveryLed", edit=True, image= uiMod.getImagePath(image), ann="Animation Crash Recovery HIGHLY recommends you to save")
def blinkingRed(self, onOff):
if onOff: G.aToolsBar.timeoutInterval.setInterval(self.toggleRed, .3, id="ACR_red_blinking")
else: G.aToolsBar.timeoutInterval.stopInterval("ACR_red_blinking")
def toggleRed(self):
self.setLed("blinking_red")
def optionBoxWindow(self, *args):
sceneId = aToolsMod.getSceneId()
idFolder = "%s%s%s"%(self.baseFolderName, os.sep, sceneId)
bkpFolder = "%s%s%s"%(idFolder, os.sep, self.baseBackupFolderName)
infoData = aToolsMod.loadFileWithUser(bkpFolder, self.infoDataFileName, ext="info")
infoDataFile = "%s%s%s%s%s.info"%(G.USER_FOLDER, os.sep, bkpFolder, os.sep, self.infoDataFileName)
modDate = os.path.getmtime(infoDataFile) if os.path.isfile(infoDataFile) else None
if not infoData or not modDate:
cmds.warning("There is no crash file to restore.")
return
def loadWindow():
mayaFileName = infoData["mayaFileName"]
message = "%s\n%s\n\nWarning: Loading crash files after editing your Maya file can lead to unpredictable results."%(mayaFileName, time.ctime(modDate))
formLayout = cmds.setParent(query=True)
icon = cmds.image(image= uiMod.getImagePath("ACR_white_bright"))
titleText = cmds.text(label="Do you want to load?", font="boldLabelFont", align="left")
messageText = cmds.text(label=message, align="left")
buttonLoad = cmds.button(label='Load', command='cmds.layoutDialog(dismiss="load")')
buttonLoadSel = cmds.button(label='Load On Selection', command='cmds.layoutDialog(dismiss="load_selection")', w=110)
cmds.formLayout (formLayout, edit=True, width=300, height=170,
attachPosition = [
(icon, 'left', 10, 0),
(icon, 'top', 10, 0),
(titleText, 'top', 10, 0),
(messageText, 'left', 10, 0),
(messageText, 'top', 0, 30),
(buttonLoad, 'left', 10, 0),
(buttonLoad, 'bottom', 10, 100),
(buttonLoadSel, 'bottom', 10, 100)
],
attachForm = [
(buttonLoad, 'left', 10),
(buttonLoadSel, 'right', 10)
],
attachControl = [
(titleText, 'left', 10, icon),
(buttonLoad, 'right', 5, buttonLoadSel)
])
def window(dismiss):
if dismiss == "dismiss": return
onlySelectedNodes = True if dismiss == "load_selection" else False
self.loadData(onlySelectedNodes, self.baseBackupFolderName)
window(cmds.layoutDialog(title="aTools Animation Crash Recovery", ui=loadWindow))
def checkForAnimationSaved(self, clearDeferredQueue=False, *args):
if clearDeferredQueue: self.deferredQueue = []
sceneId = aToolsMod.getSceneId()
idFolder = "%s%s%s"%(self.baseFolderName, os.sep, sceneId)
latestFolder = "%s%s%s"%(idFolder, os.sep, self.baseLatestFolderName)
infoFile = "%s%s%s%s%s.info"%(G.USER_FOLDER, os.sep, latestFolder, os.sep, self.infoDataFileName)
mayaFile = cmds.file(query=True, sceneName=True)
if not os.path.isfile(infoFile) or not os.path.isfile(mayaFile): return
mayaFileModTime = os.path.getmtime(mayaFile)
infoFileModTime = os.path.getmtime(infoFile)
if mayaFileModTime < infoFileModTime:
infoData = aToolsMod.loadFileWithUser(latestFolder, self.infoDataFileName, ext="info")
if not infoData: return
height = 170
completed = infoData["completed"]
mayaFileModTimeStr = time.ctime(mayaFileModTime)
infoFileModTimeStr = time.ctime(infoFileModTime)
message = "This Maya file:\n%s\n\n"%(mayaFileModTimeStr)
message += "Latest Animation Crash Recovery file:\n%s"%(infoFileModTimeStr)
if not completed:
message += "\n\n*Some animation may not be loaded.\nAnimation Crash Recovery did not finish saving before Maya crashed."
height += 40
self.warningForLoading(message, height)
def warningForLoading(self, message, height):
def warningWindow():
formLayout = cmds.setParent(query=True)
icon = cmds.image(image= uiMod.getImagePath("ACR_white_bright"))
titleText = cmds.text(label="You have newer animation. Do you want to load?", font="boldLabelFont", align="left")
messageText = cmds.text(label=message, align="left")
buttonLoad = cmds.button(label='Load', command='cmds.layoutDialog(dismiss="load")')
buttonMaybe = cmds.button(label='Maybe Later', command='cmds.layoutDialog(dismiss="maybe")', w=100)
cmds.formLayout (formLayout, edit=True, width=300, height=height,
attachPosition = [
(icon, 'left', 10, 0),
(icon, 'top', 10, 0),
(titleText, 'top', 10, 0),
(messageText, 'left', 10, 0),
(messageText, 'top', 0, 30),
(buttonLoad, 'left', 10, 0),
(buttonLoad, 'bottom', 10, 100),
(buttonMaybe, 'bottom', 10, 100)
],
attachForm = [
(buttonLoad, 'left', 10),
(buttonMaybe, 'right', 10)
],
attachControl = [
(titleText, 'left', 10, icon),
(buttonLoad, 'right', 5, buttonMaybe)
])
def window(dismiss):
if dismiss == "load":
self.loadData()
else:
cmds.warning("If you want to load later, go to aTools menu/Animation Crash Recovery option box")
self.saveBackup()
window(cmds.layoutDialog(title="aTools Animation Crash Recovery", ui=warningWindow))
def saveBackup(self):
sceneId = aToolsMod.getSceneId()
idFolder = "%s%s%s"%(self.baseFolderName, os.sep, sceneId)
latestFolder = "%s%s%s"%(idFolder, os.sep, self.baseLatestFolderName)
bkpFolder = "%s%s%s"%(idFolder, os.sep, self.baseBackupFolderName)
print("henlo")
print(f"backup: {bkpFolder}")
aToolsMod.deleteFolderWithUser(bkpFolder)
aToolsMod.renameFolderWithUser(latestFolder, bkpFolder)
aToolsMod.deleteFolderWithUser(latestFolder)
def getSavedData(self, crashFolder=None, onlySelectedNodes=False, *args):
idFolder = aToolsMod.getSceneId()
crashFolder = self.baseLatestFolderName if not crashFolder else crashFolder
folder = "%s%s%s%s%s"%(self.baseFolderName, os.sep, idFolder, os.sep, crashFolder)
filePath = cmds.file(query=True, sceneName=True)
fileModTime = None
if os.path.isfile(filePath):
fileModTime = os.path.getmtime(filePath)
curveFiles = aToolsMod.readFilesWithUser(folder, ext=self.curveExt)
attrFiles = aToolsMod.readFilesWithUser(folder, ext=self.attrExt)
status = "aTools Animation Crash Recovery - Step 1/3 - Loading crash files..."
utilMod.startProgressBar(status)
totalSteps = len(curveFiles + attrFiles)
firstStep = 0
thisStep = 0
estimatedTime = None
startChrono = None
progressInfo = [startChrono, firstStep, thisStep, totalSteps, estimatedTime, status]
data = self.getDataFromFiles("anim", folder, curveFiles, fileModTime, self.curveExt, progressInfo, onlySelectedNodes)
if not data: return
animData = data[0]
progressInfo = data[1]
data = self.getDataFromFiles("attr", folder, attrFiles, fileModTime, self.attrExt, progressInfo, onlySelectedNodes)
attrData = data[0]
if not data: return
utilMod.setProgressBar(endProgress=True)
return {"fileModTime":fileModTime, "animData":animData, "attrData":attrData}
def getDataFromFiles(self, animAttr, folder, infoFiles, fileModTime, ext, progressInfo, onlySelectedNodes):
currSel = animMod.getObjsSel()
data = {"data":[], "modTime":None}
infoFileModTimeList = []
startChrono, firstStep, thisStep, totalSteps, estimatedTime, status = progressInfo
initialStep = thisStep
for n, loopFile in enumerate(infoFiles):
if cmds.progressBar(G.progBar, query=True, isCancelled=True ):
utilMod.setProgressBar(endProgress=True)
return
thisStep = n+initialStep
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
infoFileStr = loopFile.replace(":", "_aTools_")[0:-(len(ext)+1)]
infoFilePath = aToolsMod.getSaveFilePath("%s%s%s"%(folder, os.sep, infoFileStr), ext=ext)
infoFileModTimeList.append(os.path.getmtime(infoFilePath))
if infoFileModTimeList[-1] > fileModTime: #load only what is newer
object = loopFile.replace("_aTools_", ":")[0:-(len(ext)+1)]
value = aToolsMod.loadFileWithUser(folder, infoFileStr, ext=ext)
if onlySelectedNodes:
if animAttr == "anim":
obj = value["objects"][0]
else:
obj = object.split(".")[0]
if obj not in currSel: continue
data["data"].append({"_modTime":infoFileModTimeList[-1],"object":object, "value":value})
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
#file mod date
data["data"].sort() #sort newer files last
if len(infoFileModTimeList) > 0:
data["modTime"] = max(infoFileModTimeList)
progressInfo = [startChrono, firstStep, thisStep, totalSteps, estimatedTime, status]
#blend animation data=================
return [data, progressInfo]
def loadData(self, onlySelectedNodes=False, crashFolder=None, *args):
cmds.waitCursor(state=True)
cmds.refresh(suspend=True)
cmds.undoInfo(openChunk=True)
utilMod.startProgressBar("aTools Animation Crash Recovery - Loading data...")
self.pause = True
savedData = self.getSavedData(crashFolder, onlySelectedNodes)
if savedData:
animData = savedData["animData"]["data"]
attrData = savedData["attrData"]["data"]
self.applyAttrData(attrData)
self.applyAnimData(animData)
if not crashFolder: self.loadInfoData()
utilMod.setProgressBar(endProgress=True)
self.pause = False
cmds.undoInfo(closeChunk=True)
cmds.refresh(suspend=False)
cmds.waitCursor(state=False)
def blendAnimData(self, acrAnimData):
blendedAnimData = {"objects":[], "animData":[]}
for loopData in acrAnimData:
data = loopData["value"]
objects = data["objects"]
animData = data["animData"]
blendedAnimData["objects"].extend(objects)
blendedAnimData["animData"].extend(animData)
return blendedAnimData
def applyAnimData(self, animData):
if len(animData) == 0 : return
animData = self.blendAnimData(animData)
animMod.applyAnimData(animData, pasteInPlace=False, showProgress=True, status="aTools Animation Crash Recovery - Step 3/3 - Applying animation data...")
def applyAttrData(self, attrData):
firstStep = 0
totalSteps = len(attrData)
estimatedTime = None
status = "aTools Animation Crash Recovery - Step 2/3 - Applying attributes data..."
startChrono = None
for thisStep, loopData in enumerate(attrData):
if cmds.progressBar(G.progBar, query=True, isCancelled=True ): return
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
objAttr = loopData["object"]
value = loopData["value"]["value"]
if not cmds.objExists(objAttr): continue
if not cmds.getAttr(objAttr, settable=True): continue
if cmds.getAttr(objAttr, lock=True): continue
if cmds.getAttr(objAttr, type=True) == "string": continue
cmds.cutKey(objAttr)
if type(value) is list: #translate, rotate, scale
value = value[0]
cmds.setAttr(objAttr, value[0],value[1],value[2], clamp=True)
else: #translatex, translatey, etc
cmds.setAttr(objAttr, value, clamp=True)
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
def getAllAnimCurves(self):
return cmds.ls(type=["animCurveTA","animCurveTL","animCurveTT","animCurveTU"])
def getAllNonKeyedAttrs(self):
return self.getNonKeyedAttrs(cmds.ls(transforms=True, visible=True))
#return self.getNonKeyedAttrs([loopObj for loopObj in cmds.ls() if "transform" in cmds.nodeType(loopObj, inherited=True)])
def saveSelectedCurve(self, *args):
if self.pause: return
curveMsg = args[0]
curves = [OpenMaya.MFnDependencyNode(curveMsg[n]).name() for n in range(curveMsg.length())]
function = lambda *args:self.sendDataToSaveDeferred(curves, [])
G.deferredManager.sendToQueue(function, 50, "ACR")
def saveSelectedAttr(self, msg, mplug, otherMplug, clientData):
if self.pause: return
if OpenMaya.MNodeMessage.kAttributeSet == (OpenMaya.MNodeMessage.kAttributeSet & msg):
#nodeName, attrName = mplug.name().split('.')
nonKeyedAttr = mplug.name()
#if cmds.keyframe(nonKeyedAttr, query=True): return
function = lambda *args:self.sendDataToSaveDeferred([], [nonKeyedAttr])
G.deferredManager.sendToQueue(function, 50, "ACR")
def getNonKeyedAttrs(self, animObjects):
objAttrs = animMod.getAllChannels(animObjects, changed=True, withAnimation=False)
nonKeyedObjAttrs = []
for n, loopObj in enumerate(animObjects):
loopObjAttrs = objAttrs[n]
if not loopObjAttrs: continue
for loopAttr in loopObjAttrs:
if loopAttr in self.ignoreAttrs: continue
objAttr = "%s.%s"%(loopObj, loopAttr)
if not cmds.objExists(objAttr): continue
frameCount = cmds.keyframe(objAttr, query=True, keyframeCount=True)
if frameCount <= 0:
nonKeyedObjAttrs.append(objAttr)
return nonKeyedObjAttrs
def saveAllAnimationData(self, update=False, *args):#nao precisa???
#print "saveAllAnimationData"
if update:
self.curvesInFile = self.getAllAnimCurves()
self.nonKeyedAttrsInFile = self.getAllNonKeyedAttrs()
self.sendDataToSaveDeferred(self.curvesInFile, self.nonKeyedAttrsInFile)
def sendDataToSaveDeferred(self, curves, nonKeyedAttrs):
if not len(curves) > 0 and not len(nonKeyedAttrs) > 0:
return
for loopCurve in curves:
curveStr = loopCurve.replace(":", "_aTools_")
if not cmds.objExists(loopCurve):
if curveStr in self.deferredQueue: self.deferredQueue.remove(curveStr)
continue
if curveStr in self.deferredQueue: continue
self.deferredQueue.append(curveStr)
function = lambda function=self.saveCurve, mayaFileName=self.mayaFileName, attrStr=curveStr, *args: self.sendToDeferredManager(function, mayaFileName, attrStr)
G.deferredManager.sendToQueue(function, 50, "ACR")
for loopNonKeyedAttr in nonKeyedAttrs:
nonKeyedAttrsStr = loopNonKeyedAttr.replace(":", "_aTools_")
if not cmds.objExists(loopNonKeyedAttr):
if nonKeyedAttrsStr in self.deferredQueue: self.deferredQueue.remove(nonKeyedAttrsStr)
continue
if cmds.keyframe(loopNonKeyedAttr, query=True): continue
if nonKeyedAttrsStr in self.deferredQueue: continue
self.deferredQueue.append(nonKeyedAttrsStr)
function = lambda function=self.saveNonKeyedAttrs, mayaFileName=self.mayaFileName, attrStr=nonKeyedAttrsStr, *args: self.sendToDeferredManager(function, mayaFileName, attrStr)
G.deferredManager.sendToQueue(function, 50, "ACR")
G.deferredManager.sendToQueue(lambda *args:self.stopBlinking(self.mayaFileName), 50, "ACR")
def stopBlinking(self, mayaFileName):
if G.deferredManager.inQueue("ACR") <= 1:
self.setLed("on")
self.saveInfoData(mayaFileName, completed=True)
self.checkDeletedNodesCreated()
def checkDeletedNodesCreated(self):
if len(G.ACR_messages["mdg"]) == 0: return
toRemove = []
for loopNode in self.nodesCreated:
if not cmds.objExists(loopNode): toRemove.append(loopNode)
for loopNode in toRemove: self.nodesCreated.remove(loopNode)
if len(self.nodesCreated) == 0: self.recommendSaving(False)
def sendToDeferredManager(self, function, mayaFileName, attrStr):
function(mayaFileName, attrStr)
def saveCurve(self, mayaFileName, curveStr):
self.setLed("blinking")
sceneId = aToolsMod.getSceneId()
curve = curveStr.replace("_aTools_", ":")
animData = animMod.getAnimData([curve])
if curveStr in self.deferredQueue: self.deferredQueue.remove(curveStr)
if animData is None: return
if sceneId not in self.animCurvesInfo: self.animCurvesInfo[sceneId] = {}
if curveStr in self.animCurvesInfo[sceneId]:
if self.animCurvesInfo[sceneId][curveStr] == animData: return
self.animCurvesInfo[sceneId][curveStr] = animData
#save curve to disk
aToolsMod.saveFileWithUser("%s%s%s%s%s"%(self.baseFolderName, os.sep, sceneId, os.sep, self.baseLatestFolderName), curveStr, animData, ext=self.curveExt)
self.saveInfoData(mayaFileName)
def saveInfoData(self, mayaFileName, completed=False):
sceneId = aToolsMod.getSceneId()
currFrame = cmds.currentTime(query=True)
currSel = cmds.ls(selection=True)
infoData = {"mayaFileName":mayaFileName, "currFrame":currFrame, "currSel":currSel, "completed":completed}
aToolsMod.saveFileWithUser("%s%s%s%s%s"%(self.baseFolderName, os.sep, sceneId, os.sep, self.baseLatestFolderName), self.infoDataFileName, infoData, ext="info")
def loadInfoData(self):
sceneId = aToolsMod.getSceneId()
infoData = aToolsMod.loadFileWithUser("%s%s%s%s%s"%(self.baseFolderName, os.sep, sceneId, os.sep, self.baseLatestFolderName), self.infoDataFileName, ext="info")
if not infoData: return
currFrame = infoData["currFrame"]
currSel = infoData["currSel"]
if currFrame: cmds.currentTime(currFrame)
if len(currSel) > 0: cmds.select(currSel, replace=True)
def saveNonKeyedAttrs(self, mayaFileName, nonKeyedAttrsStr):
self.setLed("blinking")
sceneId = aToolsMod.getSceneId()
nonKeyedAttr = nonKeyedAttrsStr.replace("_aTools_", ":")
attrData = self.getNonKeyedAttrData(nonKeyedAttr)
if nonKeyedAttrsStr in self.deferredQueue: self.deferredQueue.remove(nonKeyedAttrsStr)
if attrData is None: return
if sceneId not in self.nonKeyedAttrInfo: self.nonKeyedAttrInfo[sceneId] = {}
if nonKeyedAttrsStr in self.nonKeyedAttrInfo[sceneId]:
if self.nonKeyedAttrInfo[sceneId][nonKeyedAttrsStr] == attrData: return
self.nonKeyedAttrInfo[sceneId][nonKeyedAttrsStr] = attrData
#save curve to disk
aToolsMod.saveFileWithUser("%s%s%s%s%s"%(self.baseFolderName, os.sep, sceneId, os.sep, self.baseLatestFolderName), nonKeyedAttrsStr, attrData, ext=self.attrExt)
self.saveInfoData(mayaFileName)
def checkAndClearOldFiles(self):
allIdFolders = aToolsMod.readFoldersWithUser(self.baseFolderName)
timeNow = time.time()
for loopIdFolder in allIdFolders:
idFolder = "%s%s%s"%(self.baseFolderName, os.sep, loopIdFolder)
modDate = None
for loopInfoFile in [self.baseLatestFolderName, self.baseBackupFolderName]:
infoDataFile = "%s%s%s%s%s%s%s.info"%(G.USER_FOLDER, os.sep, idFolder, os.sep, loopInfoFile, os.sep, self.infoDataFileName)
if os.path.isfile(infoDataFile):
modDate = os.path.getmtime(infoDataFile)
break
if not modDate: return
if timeNow - modDate >= self.daysToKeepOldFiles:
aToolsMod.deleteFolderWithUser(idFolder)
def clearLatestFolder(self):
self.deferredQueue = []
G.deferredManager.removeFromQueue("ACR")
sceneId = aToolsMod.getSceneId()
idFolder = "%s%s%s"%(self.baseFolderName, os.sep, sceneId)
latestFolder = "%s%s%s"%(idFolder, os.sep, self.baseLatestFolderName)
aToolsMod.deleteFolderWithUser(latestFolder)
def getNonKeyedAttrData(self, nonKeyedAttr):
value = None
if cmds.objExists(nonKeyedAttr): value = cmds.getAttr(nonKeyedAttr)
return {"value":value}
def recommendSaving(self, trueFalse):
self.saveRecommended = trueFalse
if not trueFalse: self.addMdgMessages()
self.setLed("on")
def isCrashSaving(self):
t = datetime.date.today()
todaySt = ".%s%s%s."%(str(t.year).zfill(4),str(t.month).zfill(2),str(t.day).zfill(2))
return (todaySt in utilMod.getMayaFileName())
def beforeSave(self, *args):
pass
def afterSave(self, *args):
if self.isCrashSaving():
self.saveCrashLog(cmds.file(query=True, sceneName=True), self.mayaFilePath, self.mayaFileName)
return
self.mayaFileName = utilMod.getMayaFileName()
self.mayaFilePath = utilMod.getMayaFileName("path")
self.recommendSaving(False)
self.addMdgMessages()
self.clearLatestFolder()
def afterNew(self, *args):
#print "afterOpen"
self.mayaFileName = utilMod.getMayaFileName()
self.mayaFilePath = utilMod.getMayaFileName("path")
self.recommendSaving(False)
def beforeOpen(self, *args):
self.pause = True
def afterOpen(self, *args):
self.pause = False
#print "afterOpen"
self.mayaFileName = utilMod.getMayaFileName()
self.mayaFilePath = utilMod.getMayaFileName("path")
self.recommendSaving(False)
function = lambda *args: self.checkForAnimationSaved(clearDeferredQueue=True)
G.deferredManager.sendToQueue(function, 80, "ACR")
#self.checkForAnimationSaved(clearDeferredQueue=True)
def checkForCrashLog(self):
crashLog = self.loadCrashLog()
if crashLog and "crashFilePath" in crashLog: self.warnCrashLog(crashLog)
def saveCrashLog(self, crashFilePath, beforeCrashPath, beforeCrashName):
crashData = {"crashFilePath":crashFilePath, "beforeCrashPath":beforeCrashPath, "beforeCrashName":beforeCrashName}
aToolsMod.saveFileWithUser("%s"%(self.baseFolderName), "crashLog", crashData, ext="info")
def loadCrashLog(self):
return aToolsMod.loadFileWithUser("%s"%(self.baseFolderName), "crashLog", ext="info")
def warnCrashLog(self, crashLog):
crashFilePath = crashLog["crashFilePath"]
beforeCrashPath = crashLog["beforeCrashPath"]
beforeCrashName = crashLog["beforeCrashName"]
if not os.path.isfile(crashFilePath) or not os.path.isfile(beforeCrashPath): return
crashFileModTime = time.ctime(os.path.getmtime(crashFilePath))
beforeCrashModTime = time.ctime(os.path.getmtime(beforeCrashPath))
message = "Looks like last Maya session crashed and saved a crash file.\n\nOriginal file:\n%s\n%s\n\nCrash saved file:\n%s\n%s\n\nDo you want to open the crash saved file?"%(beforeCrashName, beforeCrashModTime, crashFilePath, crashFileModTime)
confirm = cmds.confirmDialog( title='aTools Animation Crash Recovery', message=message, button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No' )
if confirm == 'Yes':
if cmds.file(query=True, sceneName=True):
message = "Save current file first? If you click NO, changes will be lost."
confirm = cmds.confirmDialog( title='aTools Animation Crash Recovery', message=message, button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No' )
if confirm == 'Yes': cmds.file(save=True)
cmds.file(new=True, force=True)
cmds.file(crashFilePath, open=True, prompt=True)
aToolsMod.deleteFileWithUser("%s"%(self.baseFolderName), "crashLog", ext="info")
"""
def sceneUpdate(self, *args):
self.clearOldFiles()
self.mayaFileName = utilMod.getMayaFileName()
#print "sceneUpdate", args, self.mayaFileName
def beforeSaveCheck(self, retCode, *args):
self.clearOldFiles()
OpenMaya.MScriptUtil.setBool(retCode, True)
print "beforeSaveCheck", args, self.mayaFileName
"""
def afterNodeCreated(self, *args):
if not self.checkNodeCreated: return
nodeCreated = OpenMaya.MFnDependencyNode(args[0]).name()
nodeType = cmds.nodeType(nodeCreated)
if nodeType in ["animCurveTA","animCurveTL","animCurveTT","animCurveTU"]:
return
print(("nodeCreated", nodeCreated, nodeType))
if nodeCreated not in self.nodesCreated: self.nodesCreated.append(nodeCreated)
self.recommendSaving(True)
#self.removeMdgMessages()
def afterNodeParent(self, *args):
if not self.checkNodeCreated: return
dag = args[0]
firstObj = dag.partialPathName()
#print "firstObj",firstObj
if not firstObj: return
dag = args[1]
secondObj = dag.partialPathName()
#print "secondObj",secondObj
if not firstObj: return
#if firstObj not in self.nodesCreated: self.nodesCreated.append(firstObj)
print(("parented", firstObj, secondObj))
self.recommendSaving(True)
self.removeMdgMessages()
def addAnimSceneMessages(self):
self.removeMessages()
#ANIM MESSAGES
G.ACR_messages["anim"].append(OpenMayaAnim.MAnimMessage.addAnimCurveEditedCallback(self.saveSelectedCurve))
#SCENE MESSAGES
G.ACR_messages["scene"].append(OpenMaya.MSceneMessage.addCallback( OpenMaya.MSceneMessage.kBeforeSave, self.beforeSave))
G.ACR_messages["scene"].append(OpenMaya.MSceneMessage.addCallback( OpenMaya.MSceneMessage.kAfterSave, self.afterSave))
G.ACR_messages["scene"].append(OpenMaya.MSceneMessage.addCallback( OpenMaya.MSceneMessage.kBeforeOpen, self.beforeOpen))
G.ACR_messages["scene"].append(OpenMaya.MSceneMessage.addCallback( OpenMaya.MSceneMessage.kAfterOpen, self.afterOpen))
G.ACR_messages["scene"].append(OpenMaya.MSceneMessage.addCallback( OpenMaya.MSceneMessage.kAfterNew, self.afterNew))
#G.ACR_messages["scene"].append(OpenMaya.MSceneMessage.addCallback( OpenMaya.MSceneMessage.kSceneUpdate, self.sceneUpdate))
#G.ACR_messages["scene"].append(OpenMaya.MSceneMessage.addCheckCallback( OpenMaya.MSceneMessage.kBeforeSaveCheck, self.beforeSaveCheck))
def addMdgMessages(self):
self.removeMdgMessages()
#MDG MESSAGES
G.ACR_messages["mdg"].append(OpenMaya.MDGMessage.addNodeAddedCallback(self.afterNodeCreated))
G.ACR_messages["mdg"].append(OpenMaya.MDagMessage.addParentAddedCallback(self.afterNodeParent, "_noData_"))
def addNodeMessages(self):
self.removeNodeMessages()
#NODE MESSAGES
currSel = cmds.ls(selection=True)
MSelectionList = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList(MSelectionList)
node = OpenMaya.MObject()
for n, loopSel in enumerate(currSel):
MSelectionList.getDependNode(n, node)
G.ACR_messages["node"].append(OpenMaya.MNodeMessage.addAttributeChangedCallback(node, self.saveSelectedAttr, None))
def removeMessages(self):
try:
for loopId in G.ACR_messages["anim"]:
OpenMayaAnim.MAnimMessage.removeCallback(loopId)
except: pass
self.removeNodeMessages()
try:
for loopId in G.ACR_messages["scene"]:
OpenMaya.MSceneMessage.removeCallback(loopId)
except: pass
self.removeMdgMessages()
G.ACR_messages["anim"] = []
G.ACR_messages["scene"] = []
def removeMdgMessages(self):
try:
for loopId in G.ACR_messages["mdg"]:
OpenMaya.MDGMessage.removeCallback(loopId)
except: pass
G.ACR_messages["mdg"] = []
def removeNodeMessages(self):
try:
for loopId in G.ACR_messages["node"]:
OpenMaya.MNodeMessage.removeCallback(loopId)
except: pass
G.ACR_messages["node"] = []
"""
import maya.OpenMaya as om
import maya.OpenMayaAnim as oma
def undoTest(*args):
print 'Checking Undo callback'
def undoRedoCallback(arg):
global callbackIDs
Null = om.MObject()
objs = cmds.ls(sl=1)
if arg == 'add':
undoID = oma.MAnimMessage.addAnimCurveEditedCallback(undoTest)
#undoID = oma.MAnimMessage.addAnimKeyframeEditedCallback(undoTest)
#undoID = oma.MAnimMessage.addNodeAnimKeyframeEditedCallback(undoTest)
#undoID = oma.MAnimMessage.addAnimKeyframeEditCheckCallback(undoTest)
#undoID = oma.MAnimMessage.addAnimKeyframeEditedCallback(undoTest)
callbackIDs = [undoID]
elif arg == 'remove':
try:
for i in callbackIDs:
oma.MAnimMessage.removeCallback(i)
except:
print 'There is no ID to delete'
undoRedoCallback("add")
undoRedoCallback("remove")
MNodeMessage.addAttributeChangedCallback
"""

View File

@@ -0,0 +1,84 @@
'''
========================================================================================================================
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 aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import utilMod
import importlib
def toggleframePlaybackRange(onOff):
utilMod.killScriptJobs("G.framePlaybackRangeScriptJobs")
if onOff:
G.framePlaybackRangeScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('ToolChanged', framePlaybackRangeFn)) )
G.framePlaybackRangeScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', framePlaybackRangeFn)) )
framePlaybackRangeFn()
def getMinMax(rangeStart=None, rangeEnd=None):
displayNormalized = cmds.animCurveEditor( 'graphEditor1GraphEd', query=True, displayNormalized=True)
if displayNormalized: return [-1.1, 1.1]
if not rangeStart:
rangeStart = cmds.playbackOptions(query=True, minTime=True)
rangeEnd = cmds.playbackOptions(query=True, maxTime=True)
curvesShown = cmds.animCurveEditor( 'graphEditor1GraphEd', query=True, curvesShown=True)
keysTimes = []
keysValues = []
keysShown = []
if curvesShown:
for aCurve in curvesShown:
kTimes = cmds.keyframe(aCurve, query=True, timeChange=True)
if kTimes:
keysTimes.extend(kTimes)
keysValues.extend(cmds.keyframe(aCurve, query=True, valueChange=True))
for n, key in enumerate(keysTimes):
if rangeStart <= key <= rangeEnd:
keysShown.append(keysValues[n])
if not keysShown:
keyMax = 0
keyMin = 0
else:
keyMax = max(keysShown)
keyMin = min(keysShown)
total = keyMax - keyMin
if total == 0: total = 10
border = total * .1
return [keyMax+border, keyMin-border]
else:
return [0, 100]
def framePlaybackRangeFn(rangeStart=None, rangeEnd=None):
from aTools.commonMods import animMod; importlib.reload(animMod)
animMod.filterNonAnimatedCurves()
if not rangeStart:
rangeStart = cmds.playbackOptions(query=True, minTime=True) -1
rangeEnd = cmds.playbackOptions(query=True, maxTime=True) +1
val = getMinMax(rangeStart, rangeEnd)
minVal = val[0]
maxVal = val[1]
cmds.animView('graphEditor1GraphEd', startTime=rangeStart, endTime=rangeEnd, minValue=minVal, maxValue=maxVal)

View File

@@ -0,0 +1,56 @@
'''
========================================================================================================================
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
def togglejumpToSelectedKey(onOff):
utilMod.killScriptJobs("G.jumpToSelectedKeyScriptJobs")
if onOff:
G.jumpToSelectedKeyScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', animMod.jumpToSelectedKey)) )
animMod.jumpToSelectedKey()
def getMinMax():
rangeStart = cmds.playbackOptions(query=True, minTime=True)
rangeEnd = cmds.playbackOptions(query=True, maxTime=True)
curvesShown = cmds.animCurveEditor( 'graphEditor1GraphEd', query=True, curvesShown=True)
keysTimes = []
keysValues = []
keysShown = []
if curvesShown:
for aCurve in curvesShown:
keysTimes.extend(cmds.keyframe(aCurve, query=True, timeChange=True))
keysValues.extend(cmds.keyframe(aCurve, query=True, valueChange=True))
for n, key in enumerate(keysTimes):
if rangeStart <= key <= rangeEnd:
keysShown.append(keysValues[n])
keyMax = max(keysShown)
keyMin = min(keysShown)
total = keyMax - keyMin
if total == 0: total = 1
border = total * .1
return [keyMax+border, keyMin-border]
else:
return [0, 100]

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from . import *

View File

@@ -0,0 +1,230 @@
'''
========================================================================================================================
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
import os
import shutil
import time
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import utilMod
G.A_NODE = "aTools_StoreNode"
G.USER_FOLDER = G.USER_FOLDER or mel.eval('getenv MAYA_APP_DIR') + os.sep + "aToolsSettings"
G.UM_timerMessage = ""
utilMod.makeDir(G.USER_FOLDER)
def getSceneId(forceCreate=False):
id = loadInfoWithScene("scene", "id") if not forceCreate else False
if not id:
id = time.time()
saveInfoWithScene("scene", "id", id)
return str(id)
def saveInfoWithScene(storeNode, attr, value):
with G.aToolsBar.createAToolsNode:
cmds.undoInfo(stateWithoutFlush=False)
currSel = None
if not cmds.objExists(G.A_NODE) or not cmds.objExists(storeNode): currSel = cmds.ls(selection=True)
if not cmds.objExists(G.A_NODE): cmds.createNode('mute', name=G.A_NODE)
if not cmds.objExists(storeNode): cmds.createNode('mute', name=storeNode)
if currSel: cmds.select(currSel)
if not cmds.isConnected("%s.output"%G.A_NODE, "%s.mute"%storeNode): cmds.connectAttr("%s.output"%G.A_NODE, "%s.mute"%storeNode)
if not cmds.objExists("%s.%s"%(storeNode, attr)): cmds.addAttr(storeNode, longName=attr, dataType="string", keyable=False)
cmds.setAttr("%s.%s"%(storeNode, attr), value, type="string")
cmds.undoInfo(stateWithoutFlush=True)
def loadInfoWithScene(storeNode, attr):
obj = "%s.%s"%(storeNode, attr)
if cmds.objExists(obj):
return cmds.getAttr(obj)
else:
return None
def saveFileWithUser(folder, file, value, ext=None):
filePath = getSaveFilePath("%s%s%s"%(folder, os.sep, file), ext)
folderPath = utilMod.getFolderFromFile(filePath)
if os.path.isfile(filePath): os.remove(filePath)
if not os.path.isdir(folderPath): os.makedirs(folderPath)
newFileContents = "%s"%value
utilMod.writeFile(filePath, newFileContents)
def deleteFileWithUser(folder, file, ext="aTools"):
filePath = getSaveFilePath("%s%s%s"%(folder, os.sep, file), ext)
if os.path.isfile(filePath): os.remove(filePath)
def deleteFolderWithUser(folder):
folderPath = "%s%s%s"%(G.USER_FOLDER, os.sep, folder)
if os.path.isdir(folderPath): shutil.rmtree(folderPath)
def renameFolderWithUser(oldFolder, newFolder):
oldUserFolder = "%s%s%s"%(G.USER_FOLDER, os.sep, oldFolder)
newUserFolder = "%s%s%s"%(G.USER_FOLDER, os.sep, newFolder)
if os.path.isdir(oldUserFolder): os.rename(oldUserFolder, newUserFolder)
def loadFileWithUser(folder, file, ext="aTools"):
filePath = getSaveFilePath("%s%s%s"%(folder, os.sep, file), ext)
readFileContents = utilMod.readFile(filePath)
if readFileContents != None:
return eval(readFileContents[0])
return None
def readFilesWithUser(folder, ext=None):
filePath = getSaveFilePath("%s%s%s"%(folder, os.sep, "dummy"))
folderPath = utilMod.getFolderFromFile(filePath)
if not os.path.isdir(folderPath): return []
filesInFolder = [loopFile for loopFile in os.listdir(folderPath) if ext is None or ext is True or loopFile.endswith(".%s"%ext)]
if ext is None:
for n, loopFile in enumerate(filesInFolder):
filesInFolder[n] = ".".join(loopFile.split(".")[:-1])
return filesInFolder
def readFoldersWithUser(folder):
folderPath = "%s%s%s"%(G.USER_FOLDER, os.sep, folder)
if not os.path.isdir(folderPath): return []
foldersInFolder = [loopFolder for loopFolder in os.listdir(folderPath) if os.path.isdir(folderPath) if loopFolder != ".directory"]
return foldersInFolder
def saveInfoWithUser(file, attr, value, delete=False):
filePath = getSaveFilePath(file)
newFileContents = []
writeNew = True
if isinstance(value, str): value = "\"%s\""%value
readFileContents = utilMod.readFile(filePath)
if readFileContents != None:
for loopLine in readFileContents:
if loopLine.find(attr) == 0:
if not delete:
newFileContents.append("%s = %s\n"%(attr, value))
writeNew = None
else:
if len(loopLine) > 1:
newFileContents.append(loopLine)
if writeNew:
if not delete: newFileContents.append("%s = %s\n"%(attr, value))
utilMod.writeFile(filePath, newFileContents)
def loadInfoWithUser(file, attr):
filePath = getSaveFilePath(file)
readFileContents = utilMod.readFile(filePath)
if readFileContents != None:
for loopLine in readFileContents:
if loopLine.find(attr) == 0:
value = loopLine[(loopLine.find("=")+2):]
return eval(value)
return None
def getUserPref(pref, default):
pref = loadInfoWithUser("userPrefs", pref)
if pref == None: pref = default
return pref
def setUserPref(pref, onOff):
saveInfoWithUser("userPrefs", pref, onOff)
def setPref(pref, preferences, init=False, default=False):
for loopPref in preferences:
name = loopPref["name"]
if pref == name:
if init:
onOff = getPref(pref, preferences)
elif default:
onOff = getDefPref(pref, preferences)
cmds.menuItem("%sMenu"%name, edit=True, checkBox=onOff)
saveInfoWithUser("userPrefs", name, "", True)
else:
onOff = cmds.menuItem("%sMenu"%name, query=True, checkBox=True)
saveInfoWithUser("userPrefs", pref, onOff)
def getPref(pref, preferences):
r = loadInfoWithUser("userPrefs", pref)
if r == None:
default = getDefPref(pref, preferences)
r = default
return r
def getDefPref(pref, preferences):
for loopPref in preferences:
name = loopPref["name"]
if pref == name:
default = loopPref["default"]
return default
def getaToolsPath(level=1, inScriptsFolder=True):
if inScriptsFolder:
mayaAppDir = mel.eval('getenv MAYA_APP_DIR')
scriptsDir = "%s%sscripts%s"%(mayaAppDir, os.sep, os.sep)
aToolsFolder = "%s%saTools%s"%(scriptsDir, os.sep, os.sep)
if level==1: return aToolsFolder
if level==2: return scriptsDir
return utilMod.getFolderFromFile(__file__, level)
def getSaveFilePath(saveFile, ext="aTools"):
saveFilePath = G.USER_FOLDER + os.sep + saveFile
if ext: saveFilePath += ".%s"%ext
return saveFilePath

View File

@@ -0,0 +1,941 @@
'''
========================================================================================================================
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
========================================================================================================================
'''
# maya modules
from maya import cmds
from maya import mel
import math
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import utilMod
from aTools.commonMods import aToolsMod
from aTools.animTools import framePlaybackRange
G.lastCurrentFrame = None
G.lastRange = None
G.currNameSpace = None
def getTarget(target, animCurves=None, getFrom=None, rangeAll=None):
# object from curves, object selected, anim curves, attributes, keytimes, keys selected
if target == "keysSel" or target == "keysIndexSel":
if animCurves:
keysSel = []
if getFrom == "graphEditor":
for node in animCurves:
if target == "keysSel": keysSel.append(cmds.keyframe(node, selected=True, query=True, timeChange=True))
if target == "keysIndexSel": keysSel.append(cmds.keyframe(node, selected=True, query=True, indexValue=True))
else:
if rangeAll is None:
timeline_range = getTimelineRange()
allKeys = [cmds.keyframe(node, query=True, timeChange=True) for node in animCurves if cmds.objExists(node)]
allIndexKeys = [cmds.keyframe(node, query=True, indexValue=True) for node in animCurves if cmds.objExists(node)]
keysSel = []
for n, loopKeyArrays in enumerate(allKeys):
keysSel.append([])
if loopKeyArrays:
for nn, loopKey in enumerate(loopKeyArrays):
if rangeAll or timeline_range[0] <= loopKey < timeline_range[1]:
if target == "keysSel": keysSel[n].append(loopKey)
if target == "keysIndexSel": keysSel[n].append(allIndexKeys[n][nn])
return keysSel
elif target == "keyTimes":
if animCurves:
keyTimes = []
for node in animCurves:
keyTimes.append(cmds.keyframe(node, query=True, timeChange=True))
return keyTimes
elif target == "keyIndexTimes":
if animCurves:
keyIndexTimes = []
for node in animCurves:
keyIndexTimes.append(cmds.keyframe(node, query=True, indexValue=True))
return keyIndexTimes
elif target == "keyValues":
if animCurves:
keyValues = []
for node in animCurves:
keyValues.append(cmds.keyframe(node, query=True, valueChange=True))
return keyValues
elif target == "currValues":
if animCurves:
keyValues = []
for node in animCurves:
keyValues.append(cmds.keyframe(node, query=True, eval=True, valueChange=True)[0])
return keyValues
elif target == "keyTangentsAngle":
if animCurves:
keyTangents = []
for n, node in enumerate(animCurves):
indexes = cmds.keyframe(node, query=True, indexValue=True)
keyTangents.append([])
for loopIndex in indexes:
keyTangents[n].append(cmds.keyTangent(node, query=True, index=(loopIndex,loopIndex),inAngle=True, outAngle=True))
return keyTangents
elif target == "keyTangentsY":
if animCurves:
keyTangents = []
for node in animCurves:
keyTangents.append(cmds.keyTangent(node, query=True, iy=True, oy=True))
return keyTangents
elif target == "keyTangentsX":
if animCurves:
keyTangents = []
for node in animCurves:
keyTangents.append(cmds.keyTangent(node, query=True, ix=True, ox=True))
return keyTangents
elif target == "keyTangentsType":
if animCurves:
keyTangents = []
for n, node in enumerate(animCurves):
indexes = cmds.keyframe(node, query=True, indexValue=True)
keyTangents.append([])
for loopIndex in indexes:
keyTangents[n].append(cmds.keyTangent(node, query=True, index=(loopIndex,loopIndex),inTangentType=True, outTangentType=True))
return keyTangents
else: # objFromCurves, attr
if animCurves:
objs = []
attrs = []
for node in animCurves:
if not cmds.objExists(node): continue
for n in range(100): # find transform node (obj) and attribute name
obj = None
attr = None
type = "animBlendNodeEnum"
while type == "animBlendNodeEnum": #skip anim layer nodes
if node is None: break
if cmds.objectType(node) == "animBlendNodeAdditiveRotation":
xyz = node[-1:]
node = cmds.listConnections("%s.output%s"%(node.split(".")[0], xyz), source=False, destination=True, plugs=True, skipConversionNodes=True)
if node is None:
continue
else:
node = node[0]
else:
node = cmds.listConnections("%s.output"%node.split(".")[0], source=False, destination=True, plugs=True, skipConversionNodes=True)
if node is None:
continue
else:
node = node[0]
type = cmds.nodeType(node)
if node is None: break
obj = node.split(".")[0]
attr = node.split(".")[-1]
if type.find("animBlendNodeAdditive") == -1 and type != "animCurveTU": break
objs.append(obj)
attrs.append(attr)
return [objs, attrs]
def getMirrorObjs(selObjs, side="both"):
MIRROR_PATTERN = [["l", "r"], ["lf", "rt"], ["left", "right"]]
SEPARATORS = ["_", "-"]
mirrorObjs = []
mirrorPatern = []
for loopPattern in MIRROR_PATTERN: #add uppercase and title to search
mirrorPatern.append([loopPattern[0], loopPattern[1]])
mirrorPatern.append([loopPattern[0].upper(), loopPattern[1].upper()])
mirrorPatern.append([loopPattern[0].title(), loopPattern[1].title()])
for loopObj in selObjs:
if not loopObj: continue
nameSpaceIndex = loopObj.find(":") + 1
nameSpace = loopObj[:nameSpaceIndex]
objName = loopObj[nameSpaceIndex:]
mirrorObj = objName
sideDetected = None
for loopSeparator in SEPARATORS:
mirrorObj = "%s%s%s"%(loopSeparator, mirrorObj, loopSeparator)
for loopPattern in mirrorPatern:
leftPattern = "%s%s%s"%(loopSeparator, loopPattern[0], loopSeparator)
rightPattern = "%s%s%s"%(loopSeparator, loopPattern[1], loopSeparator)
if side == "both" or side == "left":
if not sideDetected or sideDetected == "left":
doReplace = (mirrorObj.find(leftPattern) != -1)
if doReplace:
sideDetected = "left"
mirrorObj = mirrorObj.replace(leftPattern, rightPattern)
if side == "both" or side == "right":
if not sideDetected or sideDetected == "right":
doReplace = (mirrorObj.find(rightPattern) != -1)
if doReplace:
sideDetected = "right"
mirrorObj = mirrorObj.replace(rightPattern, leftPattern)
mirrorObj = mirrorObj[1:-1]
if mirrorObj == objName:
mirrorObj = None
else:
mirrorObj = "%s%s"%(nameSpace, mirrorObj)
mirrorObjs.append(mirrorObj)
return mirrorObjs
"""
def align(sourceObjs, targetObj, translate=True, rotate=True, suspend=True, onlyCurrFrame=True):
startTime = cmds.timer( startTimer=True)
if not sourceObjs or not targetObj: return
if suspend: cmds.refresh(suspend=True)
currFrame = cmds.currentTime(query=True)
currSel = cmds.ls(selection=True)
tempNull = None
if onlyCurrFrame:
keysSel = [currFrame]
else:
getCurves = getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves:
keysSel = getTarget("keysSel", animCurves, getFrom)
keysSel = utilMod.mergeLists(keysSel)
if keysSel == []:
keysSel = [currFrame]
else:
keysSel = [currFrame]
for loopKey in keysSel:
if currFrame != loopKey: cmds.currentTime(loopKey)
if translate:
translation = cmds.xform(targetObj, query=True, ws=True, rotatePivot=True)
if rotate:
rotation = cmds.xform(targetObj, query=True, ws=True, rotation=True)
orderMap = ['xyz', 'yzx', 'zxy', 'xzy', 'yxz', 'zyx']
targetOrder = cmds.getAttr( targetObj+'.ro' )
for loopSourceObj in sourceObjs:
objOrder = cmds.getAttr( loopSourceObj+'.ro' )
if rotate:
if targetOrder != objOrder:
if not tempNull:
tempNull = cmds.group(empty=True, world=True )
if tempNull != None:
cmds.xform(tempNull, ws=True, absolute=False, rotateOrder=orderMap[targetOrder], rotation=rotation)
cmds.xform(tempNull, ws=True, absolute=False, rotateOrder=orderMap[objOrder], p = True)
rotation = cmds.xform(tempNull, query=True, ws=True, rotation=True)
cmds.xform(loopSourceObj, ws=True, rotation=rotation)
cmds.xform(loopSourceObj, ws=True, rotation=rotation)#bug workaround
if translate:
localPivot = cmds.xform(loopSourceObj, query=True, os=True, rotatePivot=True)
cmds.xform(loopSourceObj, ws=True, translation=(localPivot[0]*-1,localPivot[1]*-1,localPivot[2]*-1))
globalPivot = cmds.xform(loopSourceObj, query=True, ws=True, rotatePivot=True)
cmds.move(globalPivot[0]*-1,globalPivot[1]*-1,globalPivot[2]*-1, loopSourceObj, relative=True, worldSpace=True)
cmds.move(translation[0],translation[1],translation[2], loopSourceObj, relative=True, worldSpace=True)
#cmds.xform(loopSourceObj, ws=True, translation=translation)
if tempNull != None and cmds.objExists(tempNull):
cmds.delete(tempNull)
if len(currSel) > 0: cmds.select(currSel, replace=True)
if suspend:
cmds.refresh(suspend=False)
#refresh()
fullTime = cmds.timer( endTimer=True)
print "timer: ", fullTime
"""
def createNull(locatorName="tmp"):
with G.aToolsBar.createAToolsNode: newNull = cmds.spaceLocator(name=locatorName)[0]
cmds.xform(cp=True)
cmds.setAttr(".localScaleX", 0)
cmds.setAttr(".localScaleY", 0)
cmds.setAttr(".localScaleZ", 0)
return newNull
def group(nodes=None, name="aTools_group", empty=True, world=False):
with G.aToolsBar.createAToolsNode:
if nodes: newGroup = cmds.group(nodes, empty=False, name=name, world=world)
else: newGroup = cmds.group(empty=empty, name=name, world=world)
return newGroup
def eulerFilterCurve(animCurves, filter="euler"):
if animCurves:
for loopCurve in animCurves:
#euler filter
if not isNodeRotate(loopCurve): continue
xyzCurves = ["%sX"%loopCurve[:-1], "%sY"%loopCurve[:-1], "%sZ"%loopCurve[:-1]]
apply = True
for loopXyzCurve in xyzCurves:
if not cmds.objExists(loopXyzCurve):
apply = False
break
if apply: cmds.filterCurve(xyzCurves, filter=filter)
def getObjsSel():
return cmds.ls(sl=True)
def getAngle(keyTimeA, keyTimeB, keyValA, keyValB):
relTime = keyTimeB - keyTimeA
relVal = keyValB - keyValA
angle = math.degrees(math.atan(relVal/relTime))
#outOpp = relTimeInA*math.tan(math.radians(outAngleA))
return angle
def getAnimCurves(forceGetFromGraphEditor=False):
# get selected anim curves from graph editor
animCurves = cmds.keyframe(query=True, name=True, selected=True)
#graphEditorFocus = cmds.getPanel(withFocus=True) == "graphEditor1"
visiblePanels = cmds.getPanel(visiblePanels=True)
graphEditor = None
for loopPanel in visiblePanels:
if loopPanel == "graphEditor1":
graphEditor = True
break
getFrom = "graphEditor"
if not animCurves or not graphEditor and not forceGetFromGraphEditor: #get from timeline
getFrom = "timeline"
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
animCurves = cmds.timeControl(G.playBackSliderPython, query=True, animCurveNames=True)
return [animCurves, getFrom]
def getTimelineRange(float=True):
#if G.lastCurrentFrame == cmds.currentTime(query=True): return G.lastRange
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
timeline_range = cmds.timeControl(G.playBackSliderPython, query=True, rangeArray=True)
if float: timeline_range[1] -= .0001
#G.lastRange = timeline_range
#G.lastCurrentFrame = cmds.currentTime(query=True)
return timeline_range
def getTimelineTime():
timelineTime = cmds.currentTime(query=True); timelineTime = (timelineTime, timelineTime)
return timelineTime
def refresh():
cmds.undoInfo(stateWithoutFlush=False)
#cmds.refresh(force=True)
#print "refresh"
cmds.refresh(suspend=False)
cmds.currentTime(cmds.currentTime(query=True), edit=True)
cmds.undoInfo(stateWithoutFlush=True)
def isNodeRotate(node, xyz=None):
isRotate = False
attr = "%s.output"%node.split(".")[0]
type = cmds.getAttr(attr, type=True)
#if type == "double3":
if type == "doubleAngle":
if xyz:
if attr.find("rotate%s"%xyz.upper()) != -1 or (attr.find("Merged_Layer_input") != -1 and attr.find(xyz.upper()) != -1):
isRotate = True
else:
isRotate = True
return isRotate
def isNodeTranslate(node, xyz=None):
isTranslate = False
attr = "%s.output"%node.split(".")[0]
type = cmds.getAttr(attr, type=True)
if type == "doubleLinear":
if xyz:
if attr.find("translate%s"%xyz.upper()) != -1 or (attr.find("Merged_Layer_input") != -1 and attr.find(xyz.upper()) != -1):
isTranslate = True
else:
isTranslate = True
return isTranslate
def isAnimCurveTranslate(aCurve):
isTranslate = False
if aCurve.find("translate") != -1:
isTranslate = True
return isTranslate
def isAnimCurveRotate(aCurve):
isRotate = False
if aCurve.find("rotate") != -1:
isRotate = True
return isRotate
def isAnimCurveScale(aCurve):
isScale = False
if aCurve.find("scale") != -1:
isScale = True
return isScale
def channelBoxSel():
channelsSel = []
mObj = cmds.channelBox('mainChannelBox', query=True, mainObjectList =True)
sObj = cmds.channelBox('mainChannelBox', query=True, shapeObjectList =True)
hObj = cmds.channelBox('mainChannelBox', query=True, historyObjectList =True)
oObj = cmds.channelBox('mainChannelBox', query=True, outputObjectList =True)
mAttr = cmds.channelBox('mainChannelBox', query=True, selectedMainAttributes =True)
sAttr = cmds.channelBox('mainChannelBox', query=True, selectedShapeAttributes =True)
hAttr = cmds.channelBox('mainChannelBox', query=True, selectedHistoryAttributes =True)
oAttr = cmds.channelBox('mainChannelBox', query=True, selectedOutputAttributes =True)
if mObj and mAttr: channelsSel.extend(["%s.%s"%(loopObj, loopAttr) for loopObj in mObj for loopAttr in mAttr if cmds.objExists("%s.%s"%(loopObj, loopAttr))])
if sObj and sAttr: channelsSel.extend(["%s.%s"%(loopObj, loopAttr) for loopObj in sObj for loopAttr in sAttr if cmds.objExists("%s.%s"%(loopObj, loopAttr))])
if hObj and hAttr: channelsSel.extend(["%s.%s"%(loopObj, loopAttr) for loopObj in hObj for loopAttr in hAttr if cmds.objExists("%s.%s"%(loopObj, loopAttr))])
if oObj and oAttr: channelsSel.extend(["%s.%s"%(loopObj, loopAttr) for loopObj in oObj for loopAttr in oAttr if cmds.objExists("%s.%s"%(loopObj, loopAttr))])
return channelsSel
def getAllChannels(objs=None, changed=False, withAnimation=True):
#startTime = cmds.timer( startTimer=True)
allChannels = []
if not objs: objs = getObjsSel()
for loopObj in objs:
if not cmds.objExists(loopObj): continue
isReference = False
if changed: isReference = cmds.referenceQuery(loopObj, isNodeReferenced=True)
#if not withAnimation:
#cmds.listConnections(loopObj, source=True, destination=False, connections=True)
allChannels.append(cmds.listAttr(loopObj, settable=True, keyable=True, locked=False, write=True, read=True, changedSinceFileOpen=isReference))
#allChannels.append([loopAttr for loopAttr in cmds.listAttr(loopObj, settable=True, keyable=True, locked=False, write=True, read=True, changedSinceFileOpen=isReference) if cmds.getAttr("%s.%s"%(loopObj, loopAttr), settable=True)])
shapes = cmds.listRelatives(loopObj, shapes=True, fullPath=True)
if shapes:
for loopShape in shapes:
newChannel = cmds.listAttr(loopShape, userDefined=True, settable=True, keyable=True, locked=False, write=True, read=True)
if newChannel and allChannels[-1]:
allChannels[-1].extend(newChannel)
#fullTime = cmds.timer( endTimer=True)
return allChannels
"""
def getAllChannels(objs=None):
startChrono = cmds.timerX()
total = 0
allChannels = []
if not objs: objs = getObjsSel()
for loopObj in objs:
attrList = cmds.listAttr(loopObj, keyable=True)
allChannels.append([])
if attrList:
total += len(attrList)
for loopAttr in attrList:
if cmds.objExists("%s.%s"%(loopObj, loopAttr)):
if cmds.getAttr("%s.%s"%(loopObj, loopAttr), settable=True):
allChannels[-1].extend(loopAttr)
shapes = cmds.listRelatives(loopObj, shapes=True)
if shapes and allChannels[-1]:
for loopShape in shapes:
attrList = cmds.listAttr(loopShape, userDefined=True, keyable=True)
if attrList:
for loopAttr in attrList:
if cmds.objExists("%s.%s"%(loopObj, loopAttr)):
if cmds.getAttr("%s.%s"%(loopObj, loopAttr), settable=True):
allChannels[-1].extend(loopAttr)
total += len(loopAttr)
endChrono = cmds.timerX(startTime=startChrono)
print "taotal", total, endChrono
return allChannels
"""
def jumpToSelectedKey():
frames = cmds.keyframe(query=True, selected=True)
if frames:
if frames[0] > 0:
size = 0
sum = 0
for loopFrame in frames:
sum += loopFrame
size += 1
average = sum / size
cmds.currentTime(average)
def expandKeySelection(frames = 1):
getCurves = getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves:
keysSel = getTarget("keysSel", animCurves, getFrom)
keyTimes = getTarget("keyTimes", animCurves)
# add tail and head keys
for n, loopCurve in enumerate(animCurves):
for key in keysSel[n]:
index = keyTimes[n].index(key)
startIndex = index-frames
endIndex = index+frames
if startIndex < 0: startIndex = 0
cmds.selectKey(loopCurve, addTo=True, index=(startIndex, endIndex))
def getShotCamera():
STORE_NODE = "tUtilities"
CAMERA_ATTR = "cameraSelected"
shotCamera = aToolsMod.loadInfoWithScene(STORE_NODE, CAMERA_ATTR)
if not shotCamera:
cameras = utilMod.getAllCameras()
if cameras:
aToolsMod.saveInfoWithScene(STORE_NODE, CAMERA_ATTR, cameras[0])
return cameras[0]
return shotCamera
def filterNonAnimatedCurves():
curvesShown = cmds.animCurveEditor( 'graphEditor1GraphEd', query=True, curvesShown=True)
if curvesShown:
objsAttrs = getTarget("", curvesShown)
cmds.selectionConnection( 'graphEditor1FromOutliner', e=True, clear=True)
cmds.waitCursor(state=True)
for n, loopCurve in enumerate(curvesShown):
keyValues = cmds.keyframe(loopCurve, query=True, valueChange=True)
if max(keyValues) != min(keyValues):
cmds.selectionConnection('graphEditor1FromOutliner', edit=True, select="%s.%s"%(objsAttrs[0][n], objsAttrs[1][n]))
#framePlaybackRange.framePlaybackRangeFn()
cmds.waitCursor(state=False)
def getAnimData(animCurves=None, showProgress=None):
if animCurves is None:
getCurves = getAnimCurves(True)
animCurves = getCurves[0]
getFrom = getCurves[1]
else:
getFrom = None
if not animCurves: return
if getFrom is None: keysSel = getTarget("keysSel", animCurves, getFrom, rangeAll=True)
else: keysSel = getTarget("keysSel", animCurves, getFrom)
if utilMod.isEmpty(keysSel): return
if showProgress: utilMod.startProgressBar("aTools - Saving animation data...")
objsAttrs = getTarget("", animCurves=animCurves)
objects = objsAttrs[0]
attributes = objsAttrs[1]
animData = {"objects":objects, "animData":[]}
if showProgress:
firstStep = 0
totalSteps = len(animCurves)
estimatedTime = None
status = "aTools - Saving animation data..."
startChrono = None
for thisStep, loopCurve in enumerate(animCurves):
if showProgress: startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
if objects[thisStep] is None: continue
if len(keysSel[thisStep]) == 0: continue
weighted = cmds.keyTangent(loopCurve, query=True, weightedTangents=True)
if weighted is not None: weighted = weighted[0]
objAttr = "%s.%s"%(objects[thisStep], attributes[thisStep])
infinity = cmds.setInfinity(objAttr, query=True, preInfinite=True, postInfinite=True)
animData["animData"].append({"objAttr":objAttr, "curveData":[weighted, infinity], "keyframeData":[], "tangentData":[]})
time = (keysSel[thisStep][0], keysSel[thisStep][-1])
timeChange = cmds.keyframe(loopCurve, query=True, time=time, timeChange=True)
valueChange = cmds.keyframe(loopCurve, query=True, time=time, valueChange=True)
breakdowns = cmds.keyframe(loopCurve, query=True, time=time, breakdown=True)
inTangentType = cmds.keyTangent(loopCurve, query=True, time=time, inTangentType=True)
outTangentType = cmds.keyTangent(loopCurve, query=True, time=time, outTangentType=True)
ix = cmds.keyTangent(loopCurve, query=True, time=time, ix=True)
iy = cmds.keyTangent(loopCurve, query=True, time=time, iy=True)
ox = cmds.keyTangent(loopCurve, query=True, time=time, ox=True)
oy = cmds.keyTangent(loopCurve, query=True, time=time, oy=True)
lock = cmds.keyTangent(loopCurve, query=True, time=time, lock=True)
weightLock = cmds.keyTangent(loopCurve, query=True, time=time, weightLock=True)
for n, loopKey in enumerate(keysSel[thisStep]):
breakdown = (timeChange[n] in breakdowns) if breakdowns else []
keyframe = [timeChange[n], valueChange[n], breakdown]
tangent = [inTangentType[n], outTangentType[n], ix[n], iy[n], ox[n], oy[n], lock[n], weightLock[n]]
animData["animData"][-1]["keyframeData"].append(keyframe)
animData["animData"][-1]["tangentData"].append(tangent)
if showProgress: estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
if showProgress: utilMod.setProgressBar(endProgress=True)
return animData
def applyAnimData(animData, pasteInPlace=True, onlySelectedNodes=False, showProgress=None, status=None):
if animData:
status = "aTools - Applying animation data..." if not status else status
objects = animData["objects"]
if not onlySelectedNodes:
#print "objects1", objects
if len(objects) > 0: objects = [loopObj for loopObj in objects if loopObj is not None and cmds.objExists(loopObj)]
#print "objects2", objects
if len(objects) > 0: cmds.select(objects)
else:
objects = getObjsSel()
if not objects:
cmds.warning("No objects to apply.")
return
cmds.refresh(suspend=True)
if showProgress: utilMod.startProgressBar(status)
if pasteInPlace:
currKey = cmds.currentTime(query=True)
for aData in animData["animData"]:
allKeys = []
keys = aData["keyframeData"]
for n, key in enumerate(keys):
timeChange = aData["keyframeData"][n][0]
allKeys.append(timeChange)
firstKey = 0
if allKeys:
firstKey = min(allKeys)
lastKey = max(allKeys)
cutIn = currKey+firstKey
cuOut = lastKey+firstKey
else:
cutIn = -49999
cuOut = 50000
objsAttrs = [loopItem["objAttr"] for loopItem in animData["animData"]]
existObjsAttrs = [loopObjAttr for loopObjAttr in objsAttrs if cmds.objExists(loopObjAttr)]
createDummyKey(existObjsAttrs)
cmds.cutKey(existObjsAttrs, time=(cutIn, cuOut), clear=True)
if showProgress:
totalSteps = 0
firstStep = 0
thisStep = 0
estimatedTime = None
startChrono = None
for loopObjAttr in existObjsAttrs:
index = objsAttrs.index(loopObjAttr)
aData = animData["animData"][index]
keys = aData["keyframeData"]
totalSteps = totalSteps + len(keys)
for loopObjAttr in existObjsAttrs:
index = objsAttrs.index(loopObjAttr)
aData = animData["animData"][index]
weighted = aData["curveData"][0]
infinity = aData["curveData"][1]
keys = aData["keyframeData"]
for n, key in enumerate(keys):
if showProgress:
if cmds.progressBar(G.progBar, query=True, isCancelled=True ):
refresh()
utilMod.setProgressBar(endProgress=True)
return
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
#read values
timeChange = aData["keyframeData"][n][0]
valueChange = aData["keyframeData"][n][1]
breakdown = aData["keyframeData"][n][2]
inTangentType = aData["tangentData"][n][0]
outTangentType = aData["tangentData"][n][1]
ix = aData["tangentData"][n][2]
iy = aData["tangentData"][n][3]
ox = aData["tangentData"][n][4]
oy = aData["tangentData"][n][5]
lock = aData["tangentData"][n][6]
weightLock = aData["tangentData"][n][7]
if pasteInPlace: timeChange = timeChange-firstKey+currKey
time = (timeChange,timeChange)
# create key
cmds.setKeyframe(loopObjAttr, time=time, value=valueChange, noResolve=True)
if n == 0:
cmds.keyTangent(loopObjAttr, weightedTangents=weighted)
cmds.setInfinity(loopObjAttr, edit=True, preInfinite=infinity[0], postInfinite=infinity[1])
if breakdown: cmds.keyframe(loopObjAttr, edit=True, time=time, breakdown=True)
cmds.keyTangent(loopObjAttr, time=time, ix=ix, iy=iy, ox=ox, oy=oy, lock=lock)
if weighted: cmds.keyTangent(loopObjAttr, time=time, weightLock=weightLock)
cmds.keyTangent(loopObjAttr, time=time, inTangentType=inTangentType, outTangentType=outTangentType)
if showProgress: estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
thisStep += 1
deleteDummyKey(existObjsAttrs)
if showProgress:
refresh()
utilMod.setProgressBar(endProgress=True)
def selectCtrlGroup(g):
sel = cmds.ls(selection=True)
if not sel and G.currNameSpace == None:
cmds.warning("Please select any controller.")
return
if sel:
nameSpaces = utilMod.getNameSpace(sel)
G.currNameSpace = nameSpaces[0][0]
cmds.select(clear=True)
nameSpaceAndObjs = ["%s%s"%(G.currNameSpace, loopObj) for loopObj in g]
cmds.select(nameSpaceAndObjs)
def setAttribute(obj, attr, value):
sel = cmds.ls(selection=True)
if not sel and G.currNameSpace == None:
cmds.warning("Please select any controller.")
return
if sel:
nameSpaces = utilMod.getNameSpace(sel)
G.currNameSpace = nameSpaces[0][0]
cmds.setAttr("%s%s.%s"%(G.currNameSpace, obj, attr), value)
def filterNoneObjects(objects):
objs = []
if objects:
for loopObj in objects:
if loopObj:
if cmds.objExists(loopObj):
objs.append(loopObj)
return objs
def createDummyKey(objects=None, select=False):
objs = filterNoneObjects(objects)
if len(objs) == 0: objs = getObjsSel()
cmds.setKeyframe(objs, time=(-50000, -50000), insert=False)
if select: cmds.selectKey(objs, replace=True, time=(-50000, -50000))
def deleteDummyKey(objects=None):
objs = filterNoneObjects(objects)
if not objs: objs = getObjsSel()
if len(objs) > 0:
cmds.cutKey(objs, time=(-50000, -50000), clear=True)
def getDefaultValue(node):
type = cmds.nodeType(node)
if "animCurve" in type:
target = getTarget("", [node], "")
object = target[0][0]
attr = target[1][0]
else:
object, attr = node.split(".")
if not object: return 0
isScale = isAnimCurveScale(node)
if isScale:
value = 1
return value
value = cmds.attributeQuery(attr, node=object, listDefault=True)
if len(value) > 0: value = value[0]
else: value = 0
return value
def frameSection(nudge=24):
curvesShown = cmds.animCurveEditor( 'graphEditor1GraphEd', query=True, curvesShown=True)
if not curvesShown: return
firstSelKey = cmds.keyframe(selected=True, query=True, timeChange=True)
#lastKey = max(cmds.keyframe(selected=False, query=True, timeChange=True))
lastKey = cmds.playbackOptions(query=True, maxTime=True)
if firstSelKey: #if key is selected
firstSelKey = min(firstSelKey)
else:
#firstSelKey = min(cmds.keyframe(selected=False, query=True, timeChange=True))
firstSelKey = cmds.playbackOptions(query=True, minTime=True)
try:
if G.AM_lastFrameSection + nudge < lastKey and G.AM_lastCurvesShown == curvesShown:
firstSelKey = G.AM_lastFrameSection + nudge
except:
pass
G.AM_lastFrameSection = firstSelKey
G.AM_lastCurvesShown = curvesShown
framePlaybackRange.framePlaybackRangeFn(rangeStart=(firstSelKey-1), rangeEnd=(firstSelKey+nudge+2))
cmds.currentTime(firstSelKey, edit=True)
def getTokens(obj, att):
objAttr = "%s.%s"%(obj, att)
enumTokens = []
if cmds.objExists(objAttr):
enumFields = None
type = cmds.getAttr(objAttr, type=True)
if type == "enum":
if utilMod.isDynamic(obj, att):
enumFields = cmds.addAttr("%s.%s"%(obj, att), query=True, enumName=True)
if enumFields: enumTokens = enumFields.split(":")
return enumTokens

View File

@@ -0,0 +1,383 @@
'''
========================================================================================================================
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 animMod
from aTools.commonMods import utilMod
from itertools import cycle
def toggleRotateMode():
rot = cmds.manipRotateContext('Rotate', query=True, mode=True)
# 0 = Local, 1 = Global, 2 = Gimbal
if (rot == 0):
cmds.manipRotateContext('Rotate', edit=True, mode=1)
elif (rot == 1):
cmds.manipRotateContext('Rotate', edit=True, mode=2)
else:
cmds.manipRotateContext('Rotate', edit=True, mode=0)
def toggleMoveMode():
mov = cmds.manipMoveContext('Move', query=True, mode=True)
# 0 = Local, 1 = Global, 2 = Gimbal
if (mov == 0):
cmds.manipMoveContext('Move', edit=True, mode=1)
elif (mov == 1):
cmds.manipMoveContext('Move', edit=True, mode=2)
else:
cmds.manipMoveContext('Move', edit=True, mode=0)
def orientMoveManip():
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]
orient = cmds.xform(targetObj, query=True, ws=True, rotation=True)
orientRad = [math.radians(loopDeg) for loopDeg in orient]
cmds.manipMoveContext('Move', edit=True, mode=6, orientAxes=orientRad)
cmds.select(sourceObjs, replace=True)
cmds.setToolTo("Move")
def cameraOrientMoveManip():
selection = cmds.ls(selection=True)
if len(selection) == 0: return
shotCamera = animMod.getShotCamera()
if not shotCamera or not cmds.objExists(shotCamera):
cmds.warning("No shot camera detected.")
return
cmds.refresh(suspend=True)
sourceObjs = selection[0:-1]
targetObj = selection[-1]
locator = animMod.createNull("tempCameraOrient_locator")
cameraNode = utilMod.getCamFromSelection([shotCamera])[0]
G.aToolsBar.align.align([locator], targetObj, translate=True, rotate=False)
with G.aToolsBar.createAToolsNode: constraint = cmds.aimConstraint(cameraNode, locator, name="tempCameraOrient_constraint", aimVector=[0, 0, 1], worldUpType="objectrotation", worldUpObject=cameraNode, maintainOffset=False)[0]
cmds.select(selection)
cmds.select(locator, add=True)
orientMoveManip()
if cmds.objExists(locator): cmds.delete(locator)
if cmds.objExists(constraint): cmds.delete(constraint)
cmds.refresh(suspend=False)
def toggleObj(type):
panelName = cmds.getPanel(withFocus=True)
value = eval("cmds.modelEditor(panelName, query=True, %s=True)"%type[0])
for loopType in type:
eval("cmds.modelEditor(panelName, edit=True, %s=not value)"%loopType)
def togglePanelLayout():
layouts = ["graphEditor1", "persp"]
currLayout = getCurrentPanelLayout()
licycle = cycle(layouts)
nextItem = next(licycle)
for loopItem in layouts:
nextItem = next(licycle)
if nextItem == currLayout:
nextItem = next(licycle)
break
setPanelLayout(nextItem)
def setPanelLayout(layout):
if layout == "graphEditor1":
mel.eval("setNamedPanelLayout \"Single Perspective View\";"+\
"scriptedPanel -e -rp modelPanel4 graphEditor1;")
else:
mel.eval("setNamedPanelLayout \"Single Perspective View\";"+\
"lookThroughModelPanel persp modelPanel4;")
def getCurrentPanelLayout():
if "graphEditor1" in cmds.getPanel(visiblePanels=True):
return "graphEditor1"
else:
return "persp"
def setSmartKey(time=None, animCurves=None, select=True, insert=True, replace=True, addTo=False):
if not time: time = animMod.getTimelineTime()
getFrom = "timeline"
if not animCurves:
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves and getFrom != "timeline":
cmds.setKeyframe(animCurves, time=time, insert=insert)
if select: cmds.selectKey(animCurves, replace=replace, addTo=addTo, time=time)
else:
objects = animMod.getObjsSel()
if objects:
channelboxSelObjs = animMod.channelBoxSel()
if channelboxSelObjs:
#objsAttrs = ["%s.%s"%(loopObj, loopChannelboxSel) for loopObj in objects for loopChannelboxSel in channelboxSel]
#key selected attributes in the channelbox
for n, loopObjAttr in enumerate(channelboxSelObjs):
prevKey = cmds.findKeyframe(loopObjAttr, time=(time,time), which="previous")
tangentType = cmds.keyTangent(loopObjAttr, query=True, outTangentType=True, time=(prevKey,prevKey))
if not tangentType: #if there is no key
tangentType = cmds.keyTangent(query=True, g=True, outTangentType=True)
inTangentType = tangentType[0].replace("fixed", "auto").replace("step", "auto")
outTangentType = tangentType[0].replace("fixed", "auto")
cmds.setKeyframe(loopObjAttr, time=time, insert=False, shape=False, inTangentType=inTangentType, outTangentType=outTangentType)
continue
inTangentType = tangentType[0].replace("fixed", "auto").replace("step", "auto")
outTangentType = tangentType[0].replace("fixed", "auto")
cmds.setKeyframe(loopObjAttr, time=time, insert=insert, shape=False, inTangentType=inTangentType, outTangentType=outTangentType)
else:
#allChannels = animMod.getAllChannels(objects)
#objAttrs = ["%s.%s"%(objects[n], loopAttr) for n, loopObj in enumerate(allChannels) for loopAttr in loopObj]
prevKeys = [cmds.findKeyframe(obj, time=(time,time), which="previous") for obj in objects]
tangentTypes = [cmds.keyTangent(obj, query=True, outTangentType=True, time=(prevKeys[n],prevKeys[n])) for n, obj in enumerate(objects)]
#prevKeys = [cmds.findKeyframe(obj, time=(time,time), which="previous") for obj in objAttrs]
#tangentTypes = [cmds.keyTangent(obj, query=True, outTangentType=True, time=(prevKeys[n],prevKeys[n])) for n, obj in enumerate(objAttrs)]
#key all atributes
cmds.setKeyframe(objects, time=time, insert=insert, shape=False)
#cmds.setKeyframe(objAttrs, time=time, insert=insert, shape=False)
if insert: #will force create key if there is no key
for n, loopTangent in enumerate(tangentTypes):
if not loopTangent:
cmds.setKeyframe(objects[n], time=time, insert=False, shape=False)
#cmds.setKeyframe(objAttrs[n], time=time, insert=False, shape=False)
def unselectChannelBox():
currList = cmds.channelBox('mainChannelBox', query=True, fixedAttrList=True)
cmds.channelBox('mainChannelBox', edit=True, fixedAttrList=[""])
function = lambda *args:cmds.channelBox('mainChannelBox', edit=True, fixedAttrList=currList)
G.deferredManager.sendToQueue(function, 1, "unselectChannelBox")
def goToKey(which, type="key"):
cmds.undoInfo(stateWithoutFlush=False)
cmds.refresh(suspend=True)
frame = cmds.findKeyframe(timeSlider=True, which=which) if type == "key" else cmds.currentTime(query=True) + (1 if which == "next" else -1)
cmds.currentTime(frame)
G.aToolsBar.timeoutInterval.removeFromQueue("goToKey")
G.aToolsBar.timeoutInterval.setTimeout(animMod.refresh, sec=.05, id="goToKey")
cmds.undoInfo(stateWithoutFlush=True)
def selectOnlyKeyedObjects():
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
if animCurves:
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
objects = animMod.getTarget("", animCurves, getFrom)[0]
selObjs = []
for n, loopObj in enumerate(objects):
if len(keysSel[n]) > 0:
if not loopObj in selObjs:
selObjs.append(loopObj)
if len(selObjs) > 0: cmds.select(selObjs, replace=True)
def cropTimelineAnimation():
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
getFrom = getCurves[1]
range = animMod.getTimelineRange()
if animCurves:
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
for n, aCurve in enumerate(animCurves):
firstKey = keyTimes[n][0]
lastKey = keyTimes[n][-1]
if range[0] >= firstKey:
cmds.cutKey(aCurve, time=(firstKey, range[0]-1), clear=True)
if range[1] <= lastKey:
cmds.cutKey(aCurve, time=(range[1], lastKey), clear=True)
def smartSnapKeys():
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
if not animCurves or len(animCurves) == 0: return
getFrom = getCurves[1]
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
hasDecimalKeys = False
for loopKey in utilMod.mergeLists(keysSel):
if loopKey != round(loopKey) > 0:
hasDecimalKeys = True
break
if not hasDecimalKeys: return
keyTangentsType = animMod.getTarget("keyTangentsType", animCurves, getFrom)
firstStep = 0
totalSteps = len(animCurves)
estimatedTime = None
status = "aTools - Smart Snap Curves..."
startChrono = None
utilMod.startProgressBar(status)
for thisStep, loopCurve in enumerate(animCurves):
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
if None in [keyTimes[thisStep], keysSel[thisStep]]: continue
stepKeys = [loopKey for nn, loopKey in enumerate(keyTimes[thisStep]) if loopKey != round(loopKey) and loopKey in keysSel[thisStep] and keyTangentsType[thisStep][nn][1] == "step"]
linearKeys = [loopKey for nn, loopKey in enumerate(keyTimes[thisStep]) if loopKey != round(loopKey) and loopKey in keysSel[thisStep] and keyTangentsType[thisStep][nn][1] == "linear"]
decimalKeys = [loopKey for nn, loopKey in enumerate(keyTimes[thisStep]) if loopKey != round(loopKey) and loopKey in keysSel[thisStep] and loopKey not in stepKeys + linearKeys]
for loopKey in stepKeys: cmds.snapKey(loopCurve, time=(loopKey, loopKey))
for loopKey in linearKeys: cmds.snapKey(loopCurve, time=(loopKey, loopKey))
if len(decimalKeys) == 0: continue
if not getFrom:
if cmds.keyframe(query=True, selected=True) != None: getFrom = "graphEditor"
#inLinearKeys = [round(loopKey) for nn, loopKey in enumerate(keyTimes[thisStep]) if keyTangentsType[thisStep][nn][0] == "linear"]
#outLinearKeys = [round(loopKey) for nn, loopKey in enumerate(keyTimes[thisStep]) if keyTangentsType[thisStep][nn][1] == "linear"]
createKeys = list(set([round(loopKey) for loopKey in decimalKeys]))
selectKeys = []
#print "inlinearKeys", inLinearKeys, outLinearKeys
if getFrom == "graphEditor":
selectKeys = list(set([round(loopKey) for loopKey in keysSel[thisStep] if round(loopKey) in createKeys]))
for loopKey in createKeys: cmds.setKeyframe(loopCurve, time=(loopKey, loopKey), insert=True)
for loopKey in selectKeys: cmds.selectKey(loopCurve, addTo=True, time=(loopKey, loopKey))
for loopKey in decimalKeys: cmds.cutKey(loopCurve, time=(loopKey, loopKey))
#for loopKey in outLinearKeys: cmds.keyTangent(loopCurve, edit=True, time=(loopKey, loopKey), outTangentType="linear")
#for loopKey in inLinearKeys: cmds.keyTangent(loopCurve, edit=True, time=(loopKey, loopKey), inTangentType="linear")
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
utilMod.setProgressBar(endProgress=True)
def scrubbingUndo(onOff):
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
pc = "from maya import cmds;"
rc = "from maya import cmds;"
if not onOff:
pc += "cmds.undoInfo(stateWithoutFlush=False); "
rc += "cmds.undoInfo(stateWithoutFlush=True); "
pc += "cmds.timeControl('%s',edit=True,beginScrub=True)"%G.playBackSliderPython
rc += "cmds.timeControl('%s',edit=True,endScrub=True)"%G.playBackSliderPython
cmds.timeControl( G.playBackSliderPython, edit=True, pressCommand=pc, releaseCommand=rc)
def topWaveform(onOff):
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
onOff = 'top' if onOff else 'both'
cmds.timeControl(G.playBackSliderPython, edit=True, waveform=onOff)
def eulerFilterSelection():
getCurves = animMod.getAnimCurves()
animCurves = getCurves[0]
animMod.eulerFilterCurve(animCurves)
def setThreePanelLayout():
shotCamera = animMod.getShotCamera()
if not shotCamera: shotCamera = "persp"
mel.eval("toolboxChangeQuickLayoutButton \"Persp/Graph/Hypergraph\" 2;"+\
#"ThreeTopSplitViewArrangement;"+\
"lookThroughModelPanel %s hyperGraphPanel2;"%shotCamera+\
"lookThroughModelPanel persp modelPanel4;")
#"scriptedPanel -e -rp modelPanel2 graphEditor1;")
viewports = [view for view in cmds.getPanel(type='modelPanel') if view in cmds.getPanel(visiblePanels=True)]
defaultCameras = ['front', 'persp', 'side', 'top']
for view in viewports:
camera = utilMod.getCamFromSelection([cmds.modelEditor(view, query=True, camera=True)])
cameraTransform = camera[0]
cameraShape = camera[1]
if cameraTransform in defaultCameras:
utilMod.animViewportViewMode(view)
if cameraTransform == "persp":
cmds.camera(cameraTransform, edit=True, orthographic=False)
cmds.setAttr("%s.nearClipPlane"%cameraShape, 1000)
cmds.setAttr("%s.farClipPlane"%cameraShape, 10000000)
cmds.setAttr("%s.focalLength"%cameraShape, 3500)
else:
utilMod.cameraViewMode(view)
cmds.setAttr("%s.displayFilmGate"%cameraShape, 1)
cmds.setAttr("%s.overscan"%cameraShape, 1)

View File

@@ -0,0 +1,71 @@
'''
========================================================================================================================
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
import os
FILE_PATH = __file__
class BaseSubUI(object):
def __init__(self, parent, buttonSizeDict):
self.btnSizeDict = buttonSizeDict
self.parentLayout = parent
#get values
self.ws = self.btnSizeDict["small"][0]
self.hs = self.btnSizeDict["small"][1]
self.wb = self.btnSizeDict["big"][0]
self.hb = self.btnSizeDict["big"][1]
def getImagePath(imageName, ext="png", imageFolder="img"):
imageFile = "%s.%s"%(imageName, ext)
relativePath = os.path.abspath(os.path.join(FILE_PATH, os.pardir, os.pardir))
imgPath = os.path.abspath(os.path.join(relativePath, imageFolder, imageFile))
return imgPath
def getModulePath(filePath, moduleName):
relativePath = os.sep.join(filePath.split(os.sep)[:-1])
return relativePath + os.sep + moduleName
def getModKeyPressed():
mods = cmds.getModifiers()
if mods == 1:
return "shift"
if mods == 4:
return "ctrl"
if mods == 8:
return "alt"
if mods == 5:
return "ctrlShift"
if mods == 9:
return "altShift"
if mods == 12:
return "altCtrl"
if mods == 13:
return "altCtrlShift"
def clearMenuItems(menu):
menuItens = cmds.popupMenu(menu, query=True, itemArray=True)
if menuItens:
for loopMenu in menuItens:
if cmds.menuItem(loopMenu, query=True, exists=True): cmds.deleteUI(loopMenu)

View File

@@ -0,0 +1,548 @@
'''
========================================================================================================================
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 os
import copy
import webbrowser
import urllib.request, urllib.error, urllib.parse
from maya import OpenMaya
from datetime import datetime, timedelta
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
G.UM_timerMessage = ""
def getAllAnimCurves(selection=False):
if selection:
sel = cmds.ls(selection=True)
if len(sel) == 0: return []
return cmds.keyframe(sel, query=True, name=True)
return cmds.ls(type=["animCurveTA","animCurveTL","animCurveTT","animCurveTU"])
def onlyShowObj(types, panelName=None):
allTypes = ["nurbsCurves", "nurbsSurfaces", "polymeshes", "subdivSurfaces", "planes", "lights", "cameras", "controlVertices", "grid", "hulls", "joints", "ikHandles", "deformers", "dynamics", "fluids", "hairSystems", "follicles", "nCloths", "nParticles", "nRigids", "dynamicConstraints", "locators", "manipulators", "dimensions", "handles", "pivots", "textures", "strokes"]
if not panelName: panelName = cmds.getPanel(withFocus=True)
#views = cmds.getPanel(type='modelPanel')
#if panelName in views:
if not cmds.modelEditor(panelName, exists=True): return
cmds.modelEditor(panelName, edit=True, allObjects=True, displayAppearance="smoothShaded", displayTextures=True)
#
for loopType in allTypes:
if not loopType in types:
eval("cmds.modelEditor(panelName, edit=True, %s=False)"%loopType)
else:
eval("cmds.modelEditor(panelName, edit=True, %s=True)"%loopType)
def cameraViewMode(panelName=None):
if not panelName: panelName = cmds.getPanel(withFocus=True)
onlyShowObj(["polymeshes"], panelName)
if (len(cmds.ls(type="light")) > 0): lights = "all"
else : lights = "default"
cmds.modelEditor(panelName, edit=True, displayLights=lights, selectionHiliteDisplay=False)
def animViewportViewMode(panelName=None):
if not panelName: panelName = cmds.getPanel(withFocus=True)
onlyShowObj(["nurbsCurves", "polymeshes", "manipulators"], panelName)
cmds.modelEditor(panelName, edit=True, displayLights="default", selectionHiliteDisplay=True)
def getAllCameras():
defaultCameras = ['frontShape', 'perspShape', 'sideShape', 'topShape']
cameras = [cam for cam in cmds.ls(cameras=True) if cam not in defaultCameras]
return cameras
def download(progBar, downloadUrl, saveFile):
response = None
try:
response = urllib.request.urlopen(downloadUrl, timeout=60)
except:
pass
if response is None: return
fileSize = int(response.info().getheaders("Content-Length")[0])
fileSizeDl = 0
blockSize = 128
output = open(saveFile,'wb')
cmds.progressBar( progBar,
edit=True,
beginProgress=True,
progress=0,
maxValue=100 )
while True:
buffer = response.read(blockSize)
if not buffer:
output.close()
cmds.progressBar(progBar, edit=True, progress=100)
break
fileSizeDl += len(buffer)
output.write(buffer)
p = float(fileSizeDl) / fileSize *100
cmds.progressBar(progBar, edit=True, progress=p)
return output
def dupList(l):
return copy.deepcopy(l)
def timer(mode="l", function=""):
if mode == "s":
try:
startTime = cmds.timer( startTimer=True)
G.UM_timerMessage = "startTime: %s\n"%startTime
G.UM_timerLap = 1
except:
pass
elif mode == "l":
try:
lapTime = cmds.timer( lapTime=True)
G.UM_timerMessage += "lapTime %s: %s\n"%(G.UM_timerLap, lapTime)
G.UM_timerLap += 1
except:
pass
elif mode == "e":
try:
fullTime = cmds.timer( endTimer=True)
G.UM_timerMessage += "Timer: %s took %s sec.\n"%(function, fullTime)
except:
pass
print((G.UM_timerMessage))
#cmds.timer( startTimer=True)
#print (cmds.timer( endTimer=True))
def getRenderResolution():
defaultResolution = "defaultResolution"
width = cmds.getAttr(defaultResolution+".width")
height = cmds.getAttr(defaultResolution+".height")
return [width, height]
def mergeLists(lists):
mergedList = []
if lists:
for loopList in lists:
if not loopList: continue
for loopItem in loopList:
if not loopItem in mergedList:
mergedList.append(loopItem)
return mergedList
def listIntersection(list, sublist):
return list(filter(set(list).__contains__, sublist))
def getNameSpace(objects):
nameSpaces = []
objectNames = []
for loopObj in objects:
nameSpaceIndex = loopObj.find(":") + 1
nameSpace = loopObj[:nameSpaceIndex]
objName = loopObj[nameSpaceIndex:]
nameSpaces.append(nameSpace)
objectNames.append(objName)
return [nameSpaces, objectNames]
def listAllNamespaces():
removeList = ["UI", "shared"]
nameSpaces = list(set(cmds.namespaceInfo(listOnlyNamespaces=True))- set(removeList))
if nameSpaces: nameSpaces.sort()
return nameSpaces
def makeDir(directory):
if not os.path.exists(directory):
try:
os.makedirs(directory)
except:
print(("Was not able to create folder: %s"%directory))
def listReplace(list, search, replace):
newList = []
for loopList in list:
for n, loopSearch in enumerate(search):
loopList = loopList.replace(loopSearch, replace[n])
#if replaced != loopList: break
newList.append(loopList)
return newList
def killScriptJobs(jobVar):
exec("%s = %s or []"%(jobVar, jobVar))
jobs = eval(jobVar)
#kill previous jobs
if jobs:
for job in jobs:
try:
if cmds.scriptJob (exists = job):
cmds.scriptJob (kill = job)
except:
Warning ("Job " + str(job) + " could not be killed!")
jobs = []
exec("%s = %s"%(jobVar, jobs))
def getCurrentCamera():
panel = cmds.getPanel(withFocus=True)
views = cmds.getPanel(type='modelPanel')
if panel in views:
camera = cmds.modelEditor(panel, query=True, camera=True)
return camera
def getFolderFromFile(filePath, level=0):
folderArray = filePath.split(os.sep)[:-1-level]
newFolder = ""
for loopFolder in folderArray:
newFolder += loopFolder + os.sep
return newFolder
def formatPath(path):
path = path.replace("/", os.sep)
path = path.replace("\\", os.sep)
return path
def writeFile(filePath, contents):
contentString = ""
if contents != None:
for loopLine in contents:
contentString += "%s"%loopLine
# write
try:
output = open(filePath, 'w') # Open file for writing
output.write(contentString)
output.close()
except:
print(("aTools - Error writing file: %s"%filePath))
def readFile(filePath):
try:
with open(filePath, 'r'):
input = open(filePath, 'r') # Open file for reading
return input.readlines() # Read entire file into a list of line strings
except IOError:
return None
def toTitle(string):
newString = ""
for n, loopChar in enumerate(string):
if n == 0:
newString += "%s"%loopChar.upper()
elif loopChar.isupper() and not string[n-1].isupper() and not string[n-1] == " ":
newString += " %s"%loopChar
else:
newString += "%s"%loopChar
return newString.replace("_", " ")
def capitalize(string):
spacers = [" ", "_"]
newString = ""
cap = True
for n, loopChar in enumerate(string):
if cap: newString += loopChar.upper()
else: newString += loopChar
cap = False
if loopChar in spacers:
cap = True
return newString
def getUrl(url):
webbrowser.open(url)
def loadDefaultPrefs(preferences, *args):
for loopPref in preferences:
name = loopPref["name"]
setPref(name, preferences, False, True)
def isEmpty(list):
try:
return all(map(isEmpty, list))
except TypeError:
return False
def startProgressBar(status="", isInterruptable=True):
G.progBar = G.progBar or mel.eval('$aTools_gMainProgressBar = $gMainProgressBar')
cmds.progressBar( G.progBar,
edit=True,
beginProgress=True,
status=status,
isInterruptable=isInterruptable,
progress=0,
maxValue=100 )
"""
cmds.progressWindow(title='Doing Nothing',
status=status,
isInterruptable=isInterruptable,
progress=0,
maxValue=100 )
"""
def setProgressBar(status=None, progress=None, endProgress=None):
G.progBar = G.progBar or mel.eval('$aTools_gMainProgressBar = $gMainProgressBar')
if status: cmds.progressBar(G.progBar, edit=True, status=status)
if progress: cmds.progressBar(G.progBar, edit=True, progress=progress)
if endProgress: cmds.progressBar(G.progBar, edit=True, endProgress=True)
def getMayaFileName(path=False):
if path == "path": return cmds.file(query=True, sceneName=True)
fileName = cmds.file(query=True, sceneName=True, shortName=True)
if fileName: shotName = ".".join(fileName.split(".")[:-1])
else: shotName = "Unsaved_shot"
return shotName
def getCamFromSelection(sel):
if len(sel) > 0:
if "camera" in cmds.nodeType(sel[0], inherited=True):
transformNode = cmds.listRelatives(sel[0], parent=True)[0]
shapeNode = sel[0]
elif cmds.nodeType(sel[0]) == "transform":
transformNode = sel[0]
shapeNode = cmds.listRelatives(sel[0], shapes=True)[0]
return [transformNode, shapeNode]
def isAffected(nodeAffected, nodeDriver):
driverFamily = cmds.ls(nodeDriver, dagObjects=True)
if nodeAffected in driverFamily: return True
nodeAffectedConnections = cmds.listHistory(nodeAffected)
if nodeDriver in nodeAffectedConnections: return True
steps1to3=set()
steps1to3.update(steps1and3)
step4=[]
for each in (cmds.ls(list(steps1to3),shapes=True)):
try:
step4.extend(cmds.listConnections(each+'.instObjGroups', t='shadingEngine', et=1))
except TypeError:
pass
steps1to3.update(step4)
steps1to4=set()
steps1to4.update(steps1to3)
steps1to4.update(step4)
step5=set(steps1to4)
step5.update(cmds.listHistory(list(steps1to4)))
print(step5)
def getMObject(objectName):
'''given an object name string, this will return the MDagPath api handle to that object'''
sel = OpenMaya.MSelectionList()
sel.add( str( objectName ) )
obj = OpenMaya.MObject()
sel.getDependNode(0,obj)
return obj
def getMDagPath(nodeName):
"""
Convenience function that returns a MDagPath for a given Maya DAG node.
"""
selList = OpenMaya.MSelectionList()
selList.add(nodeName)
mDagPath = OpenMaya.MDagPath()
selList.getDagPath(0, mDagPath)
return mDagPath
def isDynamic(object, attribute):
MSelectionList = OpenMaya.MSelectionList()
MSelectionList.add(object)
node = OpenMaya.MObject()
MSelectionList.getDependNode(0, node)
fnThisNode = OpenMaya.MFnDependencyNode(node)
try:
attr = fnThisNode.attribute(attribute)
plug = OpenMaya.MPlug(node, attr)
return plug.isDynamic()
except:
pass
def formatTime(sec):
sec = timedelta(seconds=int(sec))
d = datetime(1,1,1) + sec
l = ["day", "hour", "minute", "second"]
for loopL in l:
t = eval("d.%s"%loopL)
if loopL == "day": t -= 1
if t > 0:
if t > 1: loopL+= "s"
return [t, loopL]
return None
def chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status):
if not startChrono and thisStep == firstStep +1: startChrono = cmds.timerX()
if estimatedTime:
estimatedTimeSt = "%s %s"%(estimatedTime[0],estimatedTime[1])
status += " about %s remaining"%estimatedTimeSt
p = float(thisStep) / totalSteps * 100
setProgressBar(status=status, progress=p)
return startChrono
def chronoEnd(startChrono, firstStep, thisStep, totalSteps):
if thisStep >= firstStep +2:
endChrono = cmds.timerX(startTime=startChrono)
estimatedTime = formatTime((((endChrono+1)/(thisStep+1))*totalSteps)-endChrono)
return estimatedTime
def checkScriptJobEvents(onOff=True):
killScriptJobs("G.checkScriptJobEventsJobs")
if onOff:
events = cmds.scriptJob(listEvents=True)
ignore = ["idle", "idleHigh"]
for loopEvent in events:
if loopEvent not in ignore:
G.checkScriptJobEventsJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =(loopEvent, "print('Script Job Event: %s')"%loopEvent )))
def hasInternet(url):
try:
proxy = urllib.request.ProxyHandler({})
opener = urllib.request.build_opener(proxy)
urllib.request.install_opener(opener)
response = urllib.request.urlopen(url, timeout=60)
return True
except: pass
return False
def deselectTimelineRange():
currSel = cmds.ls(selection=True)
if len(currSel) == 0:
cmds.select(G.A_NODE)
cmds.select(None)
else:
cmds.select(currSel)
def transferAttributes(fromNode, toNode):
fromAttrs = {}
for loopAttr in cmds.listAttr(fromNode):
try: fromAttrs[loopAttr] = cmds.getAttr("%s.%s"%(fromNode, loopAttr))
except: pass
for loopAttr in list(fromAttrs.keys()):
value = fromAttrs[loopAttr]
try: cmds.setAttr("%s.%s"%(toNode, loopAttr), value)
except: pass
def getAllViewports():
return [view for view in cmds.getPanel(type='modelPanel') if view in cmds.getPanel(visiblePanels=True) and view != "scriptEditorPanel1"]
def rangeToList(range):
list = []
frame = range[0]
while True:
list.append(frame)
frame += 1
if frame > range[1]: break
return list
def getApiMatrix (matrix):
mat = OpenMaya.MMatrix()
OpenMaya.MScriptUtil.createMatrixFromList(matrix, mat)
return mat

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from . import *

View File

@@ -0,0 +1,317 @@
'''
========================================================================================================================
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 aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from maya import OpenMaya, OpenMayaAnim, OpenMayaUI
class DeferredManager(object):
def __init__(self):
if G.deferredManager: self.queue = G.deferredManager.queue
else: self.queue = {}
#self.queue = {}#temp
G.deferredManager = self
self.running = False
self.nextId = None
#test
"""
self.sendToQueue((lambda *args:self.printe('functionHigh1')), 1)
self.sendToQueue((lambda *args:self.printe('functionLow1')), 100)
self.sendToQueue((lambda *args:self.printe('functionHigh2')), 1)
self.sendToQueue((lambda *args:self.printe('functionMedium1')), 50, "id1")
self.sendToQueue((lambda *args:self.printe('functionMedium2')), 50, "id1")
self.sendToQueue((lambda *args:self.printe('functionMedium3')), 50, "id1")
self.sendToQueue((lambda *args:self.printe('functionLow2')), 100)
self.sendToQueue((lambda *args:self.printe('functionLow3')), 100)
self.sendToQueue((lambda *args:self.printe('functionLow4')), 100)
self.sendToQueue((lambda *args:self.printe('functionLow5')), 100)
self.sendToQueue((lambda *args:self.printe('functionMedium4')), 50, "id2")
self.sendToQueue((lambda *args:self.printe('functionHigh3')), 1)
self.sendToQueue((lambda *args:self.printe('functionLow6')), 100)
self.sendToQueue((lambda *args:self.printe('functionLow7')), 100)
self.sendToQueue((lambda *args:self.printe('functionLow8')), 100)
self.sendToQueue((lambda *args:self.printe('functionLow9')), 100)
self.sendToQueue((lambda *args:self.printe('functionMedium5')), 50, "id2")
self.sendToQueue((lambda *args:self.printe('functionMedium6')), 50, "id2")
self.sendToQueue((lambda *args:self.printe('functionMedium10')), 50)
self.sendToQueue((lambda *args:self.printe('functionMedium11')), 50)
self.sendToQueue((lambda *args:self.printe('functionLow10')), 100)
self.sendToQueue((lambda *args:self.printe('functionLow11')), 100)
self.sendToQueue((lambda *args:self.printe('functionLow12')), 100)
self.sendToQueue((lambda *args:self.printe('functionMedium7')), 50, "id1")
self.sendToQueue((lambda *args:self.printe('functionMedium8')), 50, "id1")
self.sendToQueue((lambda *args:self.printe('functionMedium9')), 50, "id1")
"""
return
self.runQueue()
def printe(self, what):
#pass
print(what)
def sendToQueue(self, function, priority=1, id="default"):
if priority not in self.queue: self.queue[priority] = {}
if id not in self.queue[priority]: self.queue[priority][id] = []
self.queue[priority][id].append(function)
if not self.running:
self.running = True
cmds.evalDeferred(self.runQueue)
def runQueue(self):
if len(self.queue) == 0: return
self.running = True
priority = sorted(self.queue)[0]
if len(self.queue[priority]) > 0:
keys = list(self.queue[priority].keys())
id = self.nextId or keys[0]
if id not in self.queue[priority]: id = keys[0]
function = self.queue[priority][id].pop(0)
try: function()
except: print(("aTools Deferred Manager Error#%s/%s: %s"%(priority, id, function)))
self.nextId = keys[0]
if id in keys:
index = keys.index(id)
if index < len(keys)-1: self.nextId = keys[index+1]
else: self.nextId = keys[0]
if id in self.queue[priority] and len(self.queue[priority][id]) == 0: self.queue[priority].pop(id, None)
if len(self.queue[priority]) == 0: self.queue.pop(priority, None)
if len(self.queue) > 0:
cmds.evalDeferred(self.runQueue)
return
self.running = False
def removeFromQueue(self, id):
for loopChunk in self.queue:
chunk = self.queue[loopChunk]
if id in chunk: chunk.pop(id, None)
def inQueue(self, id):
results = 0
for loopChunk in self.queue:
chunk = self.queue[loopChunk]
if id in chunk: results += len(chunk[id])
return results
DeferredManager()
class TimeoutInterval(object):
def __init__(self):
if not G.aToolsBar: return
G.aToolsBar.timeoutInterval = self
G.deferredManager.removeFromQueue("timeoutInterval")
self.queue = []
def setTimeout(self, function, sec, offset=0, xTimes=1, id=None, interval=None):
timeNow = cmds.timerX()
timeToExec = timeNow + sec + offset
self.queue.append([function, timeToExec, sec, xTimes, id, interval])
self.runQueue()
def runQueue(self):
if len(self.queue) > 0:
timeNow = cmds.timerX()
for loopQueue in self.queue:
timeToExec = loopQueue[1]
if timeToExec <= timeNow:
function = loopQueue[0]
sec = loopQueue[2]
xTimes = loopQueue[3]
id = loopQueue[4]
interval = loopQueue[5]
timeToExec = timeNow + sec
xTimes -= 1
function()
if loopQueue in self.queue: self.queue.remove(loopQueue)
if xTimes > 0 or interval: self.queue.append([function, timeToExec, sec, xTimes, id, interval])
if len(self.queue) > 0:
priority = 1
for loopQueue in self.queue:
interval = loopQueue[5]
id = loopQueue[4]
if interval:
priority = 50
break
G.deferredManager.sendToQueue(self.runQueue, priority, "timeoutInterval")
def setInterval(self, function, sec, offset=0, id="general"):
self.setTimeout(function, sec, offset, id=id, interval=True)
def stopInterval(self, idToStop):
for loopQueue in self.queue:
id = loopQueue[4]
if id == idToStop: self.queue.remove(loopQueue)
def removeFromQueue(self, id):
toRemove = []
for loopQueue in self.queue:
loopId = loopQueue[4]
if id == loopId: toRemove.append(loopQueue)
for loopRemove in toRemove: self.queue.remove(loopRemove)
TimeoutInterval()
class CreateAToolsNode(object):
def __init__(self):
if not G.aToolsBar: return
G.aToolsBar.createAToolsNode = self
def __enter__(self):
#print "enter"
G.animationCrashRecovery.checkNodeCreated = False
def __exit__(self, type, value, traceback):
#print "exit"
G.animationCrashRecovery.checkNodeCreated = True
CreateAToolsNode()
class CallbackManager(object):
def __init__(self):
if G.callbackManager: self.queue = G.callbackManager.queue
else: self.queue = {}
G.callbackManager = self
self.clearQueue()
def __del__(self):
#print "CallbackManager deleted"
self.clearQueue()
def sendToQueue(self, job, type, id):
#print "sendToQueue", job, type, id
newQueue = {"job":job, "type":type}
if id not in self.queue: self.queue[id] = []
self.queue[id].append(newQueue)
def removeFromQueue(self, id):
if id not in self.queue: return
toRemove = []
for loopQueue in self.queue[id]:
loopJob = loopQueue["job"]
loopType = loopQueue["type"]
if loopType == "scriptJob": self.removeScriptJob(loopJob, loopType, id)
else: self.removeApiCallback(loopJob, loopType, id)
toRemove.append(loopQueue)
for loopRemove in toRemove: self.queue[id].remove(loopRemove)
if len(self.queue[id]) == 0: self.queue.pop(id, None)
def removeScriptJob(self, job, type, id):
try:
if cmds.scriptJob(exists=job): cmds.scriptJob(kill=job, force=True)
except: print(("aTools CallbackManager could not remove job %s/%s/%s"%(id, type, job)))
def removeApiCallback(self, job, type, id):
#print "removeApiCallback", job, type, id
function = eval("%s.removeCallback"%type)
try: function(job)
except: cmds.warning("aTools CallbackManager could not remove job %s/%s/%s"%(id, type, job))
def clearQueue(self):
for loopId in list(self.queue.keys()): self.removeFromQueue(loopId)
def inQueue(self, id):
results = 0
for loopId in list(self.queue.keys()):
if loopId == id: results += len(self.queue[id])
return results
CallbackManager()

View File

@@ -0,0 +1,24 @@
'''
========================================================================================================================
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
========================================================================================================================
'''
class AToolsGlobals(object):
def __getattr__(self, attr):
return None
aToolsGlobals = AToolsGlobals()

View File

@@ -0,0 +1,900 @@
'''
========================================================================================================================
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 sys
import urllib.request, urllib.error, urllib.parse
import shutil
import zipfile
import os
import webbrowser
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
from aTools.commonMods import commandsMod
from aTools.commonMods import aToolsMod
from aTools import setup
from aTools.generalTools import hotkeys; importlib.reload(hotkeys)
from aTools.generalTools import tumbleOnObjects; importlib.reload(tumbleOnObjects)
from aTools.animTools import animationCrashRecovery; importlib.reload(animationCrashRecovery)
from aTools.animTools import framePlaybackRange; importlib.reload(framePlaybackRange)
from aTools.animTools import jumpToSelectedKey; importlib.reload(jumpToSelectedKey)
animationCrashRecovery = animationCrashRecovery.AnimationCrashRecovery()
tumbleOnObjects = tumbleOnObjects.TumbleOnObjects()
versionInfoPath = "%sversion_info.txt"%aToolsMod.getaToolsPath(inScriptsFolder=False)
versionInfoContents = utilMod.readFile(versionInfoPath)
VERSION = versionInfoContents[0].split(" ")[-1].replace("\n", "")
WHATISNEW = "".join(versionInfoContents[1:])
KEYSLIST = ["Up", "Down", "Left", "Right", "", "Page_Up", "Page_Down", "Home", "End", "Insert", "", "Return", "Space", "", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"]
SITE_URL = "http://camiloalan.wix.com/atoolswebsite"
ATOOLS_FOLDER = "http://www.trickorscript.com/aTools/"
UPDATE_URL = "%slatest_version.txt"%ATOOLS_FOLDER
DOWNLOAD_URL = "%saTools.zip"%ATOOLS_FOLDER
lastUsedVersion = aToolsMod.loadInfoWithUser("userPrefs", "lastUsedVersion")
HELP_URL = "http://camiloalan.wix.com/atoolswebsite#!help/cjg9"
DONATE_URL = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RQLT89A239K6"
PREFS = [{ "name":"tumbleOnObjects",
"command":"tumbleOnObjects.switch(onOff)",
"default":True
},{ "name":"autoFramePlaybackRange",
"command":"framePlaybackRange.toggleframePlaybackRange(onOff)",
"default":False
},{ "name":"autoJumpToSelectedKey",
"command":"jumpToSelectedKey.togglejumpToSelectedKey(onOff)",
"default":False
},{ "name":"autoSmartSnapKeys",
"command":"self.autoSmartSnapKeys.switch(onOff)",
"default":False
},{ "name":"animationCrashRecovery",
"command":"animationCrashRecovery.switch(onOff)",
"default":True
},{ "name":"selectionCounter",
"command":"self.selectionCounter.switch(onOff)",
"default":True
},{ "name":"autoSave",
"command":"cmds.autoSave(enable=onOff)",
"default":cmds.autoSave(query=True, enable=True)
},{ "name":"topWaveform",
"command":"commandsMod.topWaveform(onOff)",
"default":True
},{ "name":"playbackAllViews",
"command":"onOff = 'all' if onOff else 'active'; cmds.playbackOptions(view=onOff)",
"default":True
},{ "name":"displayAffected",
"command":"cmds.displayAffected(onOff)",
"default":False
},{ "name":"undoQueue",
"command":"if onOff: cmds.undoInfo( state=True, infinity=False, length=300)",
"default":True
},{ "name":"scrubbingUndo",
"command":"commandsMod.scrubbingUndo(onOff)",
"default":True
},{ "name":"zoomTowardsCenter",
"command":"cmds.dollyCtx('dollyContext', edit=True, dollyTowardsCenter=onOff)",
"default":cmds.dollyCtx('dollyContext', query=True, dollyTowardsCenter=True)
},{ "name":"cycleCheck",
"command":"cmds.cycleCheck(evaluation=onOff)",
"default":cmds.cycleCheck(query=True, evaluation=True)
}]
class GeneralTools_Gui(uiMod.BaseSubUI):
def createLayout(self):
mainLayout = cmds.rowLayout(numberOfColumns=6, parent=self.parentLayout)
#manipulator orientation
#cmds.iconTextButton("manipOrientButton", style='textOnly', label='-', h=self.hb, annotation="Selected objects", command=updateManipOrient)
#launchManipOrient()
self.autoSmartSnapKeys = AutoSmartSnapKeys()
self.selectionCounter = SelectionCounter()
#selection
cmds.iconTextButton("selectionCounterButton", style='textOnly', font="smallPlainLabelFont", label='0', h=self.hb, annotation="Selected objects")
cmds.popupMenu("selectionCounterButtonMenu", button=1, postMenuCommand=self.selectionCounter.populateMenu)
#animation crash recovery
cmds.image("animationCrashRecoveryLed", w=14, h=14, annotation="Test")
#menu
cmds.iconTextButton(style='iconOnly', w=self.wb, h=self.hb, image= uiMod.getImagePath("aTools"), highlightImage= uiMod.getImagePath("aTools copy"), annotation="aTools Menu")
self.popUpaToolsMenu()
self.update = Update()
self.update.about = self.about
self.update.checkUpdates(self, mainLayout)
# set default config and startup scripts
self.setDefaultConfig()
# end createLayout
def popUpaToolsMenu(self):
cmds.popupMenu(postMenuCommand=lambda *args:self.populateaToolsMenu(args[0], 1), button=1)
cmds.popupMenu(postMenuCommand=lambda *args:self.populateaToolsMenu(args[0], 3), button=3)
def populateaToolsMenu(self, menu, button, *args):
#print menu
#print button
#menu = menu[0]
uiMod.clearMenuItems(menu)
subMenu = cmds.menuItem("animBotMenu", subMenu=True, label='animBot - the new aTools' , tearOff=True, parent=menu)
cmds.menuItem("shelfButtonMenu", label="Install animBot", command=installAnimBot, parent=subMenu)
cmds.menuItem( label="Watch Launch Video", command=watchLaunchVideo, parent=subMenu)
cmds.menuItem( label="Join the Community", command=joinTheCommunity, parent=subMenu)
cmds.menuItem(divider=True, parent=menu)
shortPrefs = PREFS[:4]
for loopPref in shortPrefs:
name = loopPref["name"]
cmds.menuItem('%sMenu'%name, label=utilMod.toTitle(name), command=lambda x, name=name, *args: self.setPref(name), checkBox=self.getPref(name), parent=menu)
#ANIMATION CRASH RECOVERY
animationCrashRecoveryPref = PREFS[4]
cmds.menuItem("animationCrashRecoveryMenu", label='Animation Crash Recovery' , command=lambda *args: self.setPref(animationCrashRecoveryPref["name"]), checkBox=self.getPref(animationCrashRecoveryPref["name"]), parent=menu)
cmds.menuItem(optionBox=True, command=animationCrashRecovery.optionBoxWindow, parent=menu)
cmds.menuItem(divider=True, parent=menu)
subMenu = cmds.menuItem("prefsMenu", subMenu=True, label='Preferences' , tearOff=True, parent=menu)
self.commandsAndHotkeys = CommandsAndHotkeys()
cmds.menuItem(label="Commands and Hotkeys", command=self.commandsAndHotkeys.openGui, parent=subMenu)
cmds.menuItem(divider=True, parent=subMenu)
shortPrefs = PREFS[5:]
for loopPref in shortPrefs:
name = loopPref["name"]
cmds.menuItem('%sMenu'%name, label=utilMod.toTitle(name), command=lambda x, name=name, *args: self.setPref(name), checkBox=self.getPref(name), parent=subMenu)
cmds.menuItem(divider=True, parent=subMenu)
cmds.menuItem("loadDefaultsMenu", label="Load Defaults", command=self.loadDefaultPrefs, parent=subMenu)
cmds.menuItem("shelfButtonMenu", label="Create Toggle on Shelf", command=shelfButton, parent=menu)
cmds.menuItem( label="Refresh", command=refreshATools, parent=menu)
cmds.menuItem( label="Uninstall", command=self.uninstall, parent=menu)
cmds.menuItem( divider=True )
cmds.menuItem( label="Help", command=self.help, parent=menu)
cmds.menuItem( label="About", command=self.about, parent=menu)
def setPref(self, pref, init=False, default=False):
for loopPref in PREFS:
name = loopPref["name"]
if pref == name:
command = loopPref["command"]
if init:
onOff = self.getPref(pref)
elif default:
onOff = self.getDefPref(pref)
cmds.menuItem("%sMenu"%name, edit=True, checkBox=onOff)
aToolsMod.saveInfoWithUser("userPrefs", name, "", True)
else:
onOff = cmds.menuItem("%sMenu"%name, query=True, checkBox=True)
aToolsMod.saveInfoWithUser("userPrefs", pref, onOff)
exec(command)
def getPref(self, pref):
r = aToolsMod.loadInfoWithUser("userPrefs", pref)
if r == None:
default = self.getDefPref(pref)
r = default
return r
def getDefPref(self, pref):
for loopPref in PREFS:
name = loopPref["name"]
if pref == name:
default = loopPref["default"]
return default
def loadDefaultPrefs(self, *args):
for loopPref in PREFS:
name = loopPref["name"]
self.setPref(name, False, True)
def setDefaultConfig(self):
#STATIC PREFS
# tumble config
#cmds.tumbleCtx( 'tumbleContext', edit=True, alternateContext=True, tumbleScale=1.0, localTumble=0, autoOrthoConstrain=False, orthoLock=False)
cmds.tumbleCtx( 'tumbleContext', edit=True, alternateContext=True, tumbleScale=1.0, localTumble=0)
cmds.dollyCtx( 'dollyContext', edit=True, alternateContext=True, scale=1.0, localDolly=True, centerOfInterestDolly=False)
#timeline ticks display
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
cmds.timeControl(G.playBackSliderPython, edit=True, showKeys="mainChannelBox", showKeysCombined=True, animLayerFilterOptions="active")
#tickDrawSpecial Color
# seems to fail on maya 2024
# cmds.displayRGBColor('timeSliderTickDrawSpecial',1,1,.4)
#CUSTOMIZABLE PREFS
for loopPref in PREFS:
name = loopPref["name"]
self.setPref(name, True)
def uninstall(self, *args):
message = "Are you sure you want to uninstall aTools?"
confirm = cmds.confirmDialog( title='Confirm', message=message, button=['Yes','No'], defaultButton='No', cancelButton='No', dismissString='No' )
if confirm == 'Yes':
from aTools.animTools.animBar import animBarUI; importlib.reload(animBarUI)
#aToolsPath = aToolsMod.getaToolsPath(2)
aToolsFolder = aToolsMod.getaToolsPath()
#if aToolsPath in sys.path: sys.path.remove(aToolsPath)
G.deferredManager.sendToQueue(G.aToolsBar.delWindows, 1, "uninstall_delWindows")
G.deferredManager.sendToQueue(lambda *args:setup.install('', True), 1, "uninstall_install")
#delete files
if os.path.isdir(aToolsFolder): shutil.rmtree(aToolsFolder)
cmds.warning("Uninstall complete! If you want to install aTools in the future, go to %s."%SITE_URL)
def help(self, *args):
webbrowser.open_new_tab(HELP_URL)
def about(self, warnUpdate=None, *args):
winName = "aboutWindow"
title = "About" if not warnUpdate else "aTools has been updated!"
if cmds.window(winName, query=True, exists=True): cmds.deleteUI(winName)
window = cmds.window( winName, title=title)
form = cmds.formLayout(numberOfDivisions=100)
pos = 10
minWidth = 300.0
# Creating Elements
object = cmds.image(image= uiMod.getImagePath("aTools_big"))
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
object = cmds.text( label="aTools - Version %s"%VERSION, font="boldLabelFont")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 80)] )
#=========================================
pos += 30
object = cmds.text( label="More info:")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 80)] )
#=========================================
object = cmds.text( label="<a href=\"%s\">aTools website</a>"%SITE_URL, hyperlink=True)
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 220)] )
#=========================================
pos += 15
object = cmds.text( label="Author: Alan Camilo")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 80)] )
#=========================================
object = cmds.text( label="<a href=\"http://www.alancamilo.com/\">www.alancamilo.com</a>", hyperlink=True)
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 220)] )
#========================================= pos += 15
pos += 15
object = cmds.text( label="Adaped: Michael Klimenko")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 80)] )
#=========================================
object = cmds.text( label="<a href=\"https://github.com/MKlimenko/\">My GitHub</a>", hyperlink=True)
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 220)] )
#=========================================
minWidth = 550.0
w = 210
object = cmds.text( label="Do you like aTools?", w=w)
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos-50), ( object, 'right', 10)] )
#=========================================
object = cmds.iconTextButton(label="Buy Me a Beer!", style="iconAndTextVertical", bgc=(.3,.3,.3), h=45, w=w, command=lambda *args: webbrowser.open_new_tab(DONATE_URL), image= uiMod.getImagePath("beer"), highlightImage= uiMod.getImagePath("beer copy"))
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos-30), ( object, 'right', 10)] )
object = cmds.text( label="I really appreciate\nthe support!", w=w)
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos+20), ( object, 'right', 10)] )
if warnUpdate:
pos += 40
object = cmds.text( label="aTools has been updated to version %s. What is new?"%VERSION, align="left")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos -= 20
# open bit link - next big thing
#webbrowser.open('http://bit.ly/2inAinL', new=0, autoraise=True)
#=========================================
pos += 40
object = cmds.text( label=WHATISNEW, align="left")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
#=========================================
for x in range(WHATISNEW.count("\n")):
pos += 13
pos += 25
cmds.setParent( '..' )
cmds.showWindow( window )
whatsNewWidth = cmds.text(object, query=True, width=True) + 15
wid = whatsNewWidth if whatsNewWidth > minWidth else minWidth
cmds.window( winName, edit=True, widthHeight=(wid, pos))
class Update(object):
def __init__(self):
G.GT_wasUpdated = G.GT_wasUpdated or None
def tryUpdate(self):
return True
def checkUpdates(self, gui, layout, *args):
if self.tryUpdate():
if not G.GT_wasUpdated:
hasUpdate = self.hasUpdate()
if hasUpdate != False:
cmds.iconTextButton(label="Updating...", style='textOnly', h=gui.hb, parent=layout)
cmds.progressBar("aToolsProgressBar", maxValue=100, width=50, parent=layout)
if hasUpdate == "offline_update":
offlinePath = aToolsMod.loadInfoWithUser("userPrefs", "offlinePath")
offlineFolder = offlinePath[0]
offlineFilePath = "%s%saTools.zip"%(offlineFolder, os.sep)
downloadUrl = "file:///%s%saTools.zip"%(offlineFolder, os.sep)
fileModTime = os.path.getmtime(offlineFilePath)
offline = [offlineFilePath, fileModTime]
else:
downloadUrl = DOWNLOAD_URL
offline = None
function = lambda *args:self.updateaTools(downloadUrl, offline)
G.deferredManager.sendToQueue(function, 1, "checkUpdates")
return
self.warnUpdate()
self.warnAnimBot()
def updateaTools(self, downloadUrl, offline=None, *args):
aToolsPath = aToolsMod.getaToolsPath(2)
aToolsFolder = aToolsMod.getaToolsPath()
oldaToolsFolder = "%saTools.old"%aToolsPath
tmpZipFile = "%stmp.zip"%aToolsPath
#delete temp
if os.path.isfile(tmpZipFile): os.remove(tmpZipFile)
if os.path.isdir(oldaToolsFolder): shutil.rmtree(oldaToolsFolder)
output = utilMod.download("aToolsProgressBar", downloadUrl, tmpZipFile)
if not output:
cmds.warning("Atools - Update failed.")
return
#rename aTools to old
if os.path.isdir(aToolsFolder): os.rename(aToolsFolder, oldaToolsFolder)
#uncompress file
zfobj = zipfile.ZipFile(tmpZipFile)
for name in zfobj.namelist():
uncompressed = zfobj.read(name)
# save uncompressed data to disk
filename = utilMod.formatPath("%s%s"%(aToolsPath, name))
d = os.path.dirname(filename)
if not os.path.exists(d): os.makedirs(d)
if filename.endswith(os.sep): continue
output = open(filename,'wb')
output.write(uncompressed)
output.close()
#delete temp
zfobj.close()
if os.path.isfile(tmpZipFile): os.remove(tmpZipFile)
if os.path.isdir(oldaToolsFolder): shutil.rmtree(oldaToolsFolder)
setup.install(offline=offline)
#refresh
G.GT_wasUpdated = True
refreshATools()
def hasUpdate(self):
return False
def warnUpdate(self):
if G.GT_wasUpdated:
G.GT_wasUpdated = None
if lastUsedVersion != VERSION:
aToolsMod.saveInfoWithUser("userPrefs", "lastUsedVersion", VERSION)
G.deferredManager.sendToQueue(lambda *args:self.about(warnUpdate=True), 50, "warnUpdate")
def warnAnimBot(self):
try:
import animBot
except ImportError:
pref = aToolsMod.loadInfoWithUser("userPrefs", "dontShowAnimBotWarningAgain")
if not pref:
G.deferredManager.sendToQueue(self.atoolsIsRetiring, 50, "warnAnimBot")
def dontShowAgain(self, onOff):
aToolsMod.saveInfoWithUser("userPrefs", "dontShowAnimBotWarningAgain", onOff)
def atoolsIsRetiring(self):
winName = "atoolsIsRetiringWindow"
title = "aTools is Retiring..."
if cmds.window(winName, query=True, exists=True):
cmds.deleteUI(winName)
window = cmds.window( winName, title=title)
form = cmds.formLayout(numberOfDivisions=100)
pos = 10
minWidth = 300.0
# Creating Elements
object = cmds.text( label="aTools is giving place to animBot, a more robust,\nsmart and intuitive toolset. ", align="left")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 15
object = cmds.image(image=uiMod.getImagePath("atools_animbot"))
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 100
object = cmds.text( label="Three Steps for Full Awesomeness:", fn="boldLabelFont")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 20
object = cmds.button(label="1) Install animBot and have fun!", bgc=(.3,.3,.3), h=45, w=280, command=installAnimBot)
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 45
object = cmds.button(label="2) Watch the launch video.", bgc=(.3,.3,.3), h=45, w=280, command=lambda *args:webbrowser.open_new_tab("https://youtu.be/DezLHqXrDao"))
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 45
object = cmds.button(label="3) Join the community.", bgc=(.3,.3,.3), h=45, w=280, command=lambda *args:webbrowser.open_new_tab("https://www.facebook.com/groups/1589262684419439"))
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 65
object = cmds.text(align="left", label="The upgrade will be optional and although aTools\nwon't get feature updates, it will be available forever.\nPlease check the community for information about\nanimBot development progress.")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 80
object = cmds.text( label="Enjoy!")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 20
object = cmds.text( label="-Alan")
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 20
object = cmds.checkBox(label="Don't show this again", value=False, changeCommand=self.dontShowAgain)
cmds.formLayout( form, edit=True, attachForm=[( object, 'top', pos), ( object, 'left', 10)] )
pos += 20
pos += 10
cmds.setParent( '..' )
cmds.showWindow( window )
cmds.window( winName, edit=True, widthHeight=(minWidth, pos))
class SelectionCounter(object):
def __init__(self):
self.defaultWidth = 25
def update(self):
selectionCount = len(cmds.ls(selection=True))
cmds.iconTextButton("selectionCounterButton", edit=True, label="%s"%selectionCount)
cmds.iconTextButton("selectionCounterButton", edit=True, w=self.defaultWidth)
def populateMenu(self, parent, *args):
menuItens = cmds.popupMenu(parent, query=True, itemArray=True)
if menuItens:
for loopMenu in menuItens:
if cmds.menuItem(loopMenu, query=True, exists=True): cmds.deleteUI(loopMenu)
selection = cmds.ls(selection=True)
selection.sort()
for loopSel in selection:
cmds.menuItem('%sMenu'%loopSel, label=loopSel, parent=parent, command=lambda x, loopSel=loopSel, *args: self.selectFromMenu(loopSel))
def selectFromMenu(self, selection):
cmds.select(selection)
def switch(self, onOff):
utilMod.killScriptJobs("G.selectionCounterScriptJobs")
cmds.iconTextButton("selectionCounterButton", edit=True, visible=False)
if onOff:
cmds.iconTextButton("selectionCounterButton", edit=True, visible=True)
G.selectionCounterScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.update )))
self.update()
class AutoSmartSnapKeys(object):
def __init__(self):
utilMod.killScriptJobs("G.autoSmartSnapKeysJobs")
def switch(self, onOff):
utilMod.killScriptJobs("G.autoSmartSnapKeysJobs")
if onOff:
G.autoSmartSnapKeysJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('timeChanged', self.smartSnapKeys )))
def smartSnapKeys(self):
rangeVisible = cmds.timeControl( G.playBackSliderPython, query=True, rangeVisible=True )
if not rangeVisible: return
cmds.undoInfo(stateWithoutFlush=False)
commandsMod.smartSnapKeys()
cmds.undoInfo(stateWithoutFlush=True)
class CommandsAndHotkeys(object):
def __init__(self):
self.allColors = ["yellow", "green", "blue", "purple", "red", "orange", "gray"]
self.colorValues = {"yellow":(1,0.97,0.4),
"green" :(0.44,1,0.53),
"blue" :(0.28,0.6,1),
"purple":(0.640,0.215,0.995),
"red" :(1,0.4,0.4),
"orange":(1,0.6,0.4),
"gray" :(0.5,0.5,0.5)}
self.reassignCommandsAtStartup()
def openGui(self, *args):
winName = "commandsWindow"
height = 26
commands = []
names = []
hotkeysDict = [[]]
allHotkeys = hotkeys.getHotkeys()
totalItems = sum(len(x) for x in allHotkeys)
itemsCount = 0
aB = 0
totalColums = 2
for n, loopHotkey in enumerate(allHotkeys):
if itemsCount > (totalItems/totalColums) * (aB+1):
aB += 1
hotkeysDict.append([])
itemsCount += len(loopHotkey)
for loopItem in loopHotkey:
hotkeysDict[aB].append(loopItem)
hotkeysDict[aB][-1]["colorValue"] = self.colorValues[self.allColors[n]]
if cmds.window(winName, query=True, exists=True): cmds.deleteUI(winName)
window = cmds.window( winName, title = "Commands and Hotkeys")
mainLayout = cmds.columnLayout(adjustableColumn=True)
columnsLayout = cmds.rowColumnLayout(numberOfColumns=totalColums)
for loopColumn in range(totalColums):
parent = cmds.rowColumnLayout(numberOfColumns=7, columnSpacing=([2,5], [3,3], [4,3], [5,1], [6,5], [7,5]), parent=columnsLayout)
cmds.text(label='Command', h=height)
cmds.text(label='Ctl', h=height)
cmds.text(label='Alt', h=height)
cmds.text(label='Key', h=height)
cmds.text(label='', h=height)
cmds.text(label='Set Hotkey', h=height)
cmds.text(label='Assigned to', align="left", h=height)
for loopIndex, loopCommand in enumerate(hotkeysDict[loopColumn]):
command = loopCommand["command"]
name = loopCommand["name"]
key = loopCommand["hotkey"]
alt = loopCommand["alt"]
ctl = loopCommand["ctl"]
toolTip = loopCommand["toolTip"]
color = loopCommand["colorValue"]
hotkeyData = aToolsMod.loadInfoWithUser("hotkeys", name)
if hotkeyData != None:
key = hotkeyData[0]
alt = hotkeyData[1]
ctl = hotkeyData[2]
cmds.button("command%s"%name, label=utilMod.toTitle(name), command=command, annotation=toolTip, h=height, bgc=color, parent=parent)
cmds.checkBox('ctl%s'%name, label='', value=ctl, changeCommand=lambda x, name=name, *args:self.updateHotkeyCheck(name), h=height, parent=parent)
cmds.checkBox('alt%s'%name, label='', value=alt, changeCommand=lambda x, name=name, *args:self.updateHotkeyCheck(name), h=height, parent=parent)
cmds.scrollField('key%s'%name, w=80, text=key, keyPressCommand=lambda x, name=name, *args:self.updateHotkeyCheck(name), h=height, parent=parent)
cmds.button(label=" ", h=height, parent=parent)
self.popSpecialHotkeys(name)
cmds.button(label='>', command=lambda x, name=name, command=command, *args: self.setHotkey(self.getHotkeyDict([name], [command])), h=height, parent=parent)
cmds.text("query%s"%name, align="left", label=self.hotkeyCheck(key, ctl, alt), font="plainLabelFont", h=height, parent=parent)
commands.append(command)
names.append(name)
#cmds.button(label="Set Hotkey", command=lambda *args: getHotkeyDict([name], [command], [key], [alt], [ctl], [cmd]))
self.updateHotkeyCheck(name)
#cmds.rowLayout(numberOfColumns=2, columnAttach=([1, 'left', 0],[2, 'right', 0]), adjustableColumn=2)
cmds.button(label="Load Defaults", command=lambda *args: self.loadHotkeys(True), parent=mainLayout)
cmds.button(label="Set All Hotkeys", command=lambda *args: self.setHotkey(self.getHotkeyDict(names, commands)), parent=mainLayout)
cmds.showWindow( window )
def loadHotkeys(self, defaults=False):
allHotkeys = hotkeys.getHotkeys()
hotkeysDict = []
for n, loopHotkey in enumerate(allHotkeys):
for loopItem in loopHotkey:
hotkeysDict.append(loopItem)
for loopIndex, loopCommand in enumerate(hotkeysDict):
command = loopCommand["command"]
name = loopCommand["name"]
key = loopCommand["hotkey"]
alt = loopCommand["alt"]
ctl = loopCommand["ctl"]
toolTip = loopCommand["toolTip"]
if not defaults:
hotkeyData = aToolsMod.loadInfoWithUser("hotkeys", name)
if hotkeyData != None:
key = hotkeyData[0]
alt = hotkeyData[1]
ctl = hotkeyData[2]
cmds.checkBox('ctl%s'%name, edit=True, value=ctl)
cmds.checkBox('alt%s'%name, edit=True, value=alt)
cmds.scrollField('key%s'%name, edit=True, text=key)
self.updateHotkeyCheck(name)
def popSpecialHotkeys(self, name):
cmds.popupMenu("popSpecialHotkeysMenu", button=1)
for loopKey in KEYSLIST:
if loopKey == "":
cmds.menuItem( divider=True )
else:
cmds.menuItem ("menu%s"%loopKey, label=str(loopKey), command=lambda x, name=name, loopKey=loopKey, *args: self.typeSpecialKey(name, loopKey))
cmds.setParent( '..', menu=True )
def typeSpecialKey(self, name, text):
cmds.scrollField("key%s"%name, edit=True, text=text)
self.updateHotkeyCheck(name)
def getHotkeyDict(self, names, commands):
hotkeysDict = []
for n, loopName in enumerate(names):
command = commands[n]
name = loopName
key = cmds.scrollField("key%s"%loopName, query=True, text=True)
alt = cmds.checkBox("alt%s"%loopName, query=True, value=True)
ctl = cmds.checkBox("ctl%s"%loopName, query=True, value=True)
if len(key) > 1: key = key[0]
hotkeysDict.append({"name":"%s"%name,
"command":"%s"%command,
"hotkey":"%s"%key,
"alt":alt,
"ctl":ctl
})
return hotkeysDict
def setHotkey(self, hotkeyDict):
message = "Are you sure?\n\n"
#format message
for loopIndex, loopCommand in enumerate(hotkeyDict):
command = loopCommand["command"]
name = loopCommand["name"]
key = loopCommand["hotkey"]
alt = loopCommand["alt"]
ctl = loopCommand["ctl"]
q = cmds.text("query%s"%name, query=True, label=True)
commandKeys = ""
if ctl: commandKeys += "Ctl + "
if alt: commandKeys += "Alt + "
message += "%s (%s%s)"%(name, commandKeys, key)
if q != "": message += " is assigned to: %s"%q
message += "\n"
confirm = cmds.confirmDialog( title='Confirm', message=message, button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No' )
if confirm == 'Yes':
for loopIndex, loopCommand in enumerate(hotkeyDict):
command = loopCommand["command"]
name = loopCommand["name"]
key = loopCommand["hotkey"]
alt = loopCommand["alt"]
ctl = loopCommand["ctl"]
cmds.nameCommand(name, command='python("%s");'%command, annotation=name)
cmds.hotkey(k=key, alt=alt, ctl=ctl, name=name)
aToolsMod.saveInfoWithUser("hotkeys", name, [key, alt, ctl])
self.updateHotkeyCheck(name)
cmds.savePrefs( hotkeys=True )
def hotkeyCheck(self, key, ctl, alt):
if key != "":
q = cmds.hotkey(key, query=True, alt=alt, ctl=ctl, name=True)
if q != None and "NameCom" in q: q = q[7:]
return q
else:
return ""
def updateHotkeyCheck(self, name):
function = lambda name=name, *args: self.delayedUpdateHotkeyCheck(name)
G.deferredManager.sendToQueue(function, 1, "updateHotkeyCheck")
def delayedUpdateHotkeyCheck(self, name):
command = cmds.button("command%s"%name, query=True, label=True)
key = cmds.scrollField("key%s"%name, query=True, text=True)
ctl = cmds.checkBox("ctl%s"%name, query=True, value=True)
alt = cmds.checkBox("alt%s"%name, query=True, value=True)
if len(key) > 1 and key not in KEYSLIST:
key = key[0]
cmds.scrollField("key%s"%name, edit=True, text=key)
label = self.hotkeyCheck(key, ctl, alt)
if label == None: label = ""
cmds.text("query%s"%name, edit=True, label=label, font="plainLabelFont")
if utilMod.toTitle(label) != command: cmds.text("query%s"%name, edit=True, font="boldLabelFont")
def reassignCommandsAtStartup(self):
allHotkeys = hotkeys.getHotkeys()
hotkeysDict = []
for n, loopHotkey in enumerate(allHotkeys):
for loopItem in loopHotkey:
hotkeysDict.append(loopItem)
for loopCommand in hotkeysDict:
command = loopCommand["command"]
name = loopCommand["name"]
key = loopCommand["hotkey"]
alt = loopCommand["alt"]
ctl = loopCommand["ctl"]
#toolTip = loopCommand["toolTip"]
label = self.hotkeyCheck(key, ctl, alt)
if label == name: cmds.nameCommand(name, command='python("%s");'%command, annotation=name)
#=========================================================
def shelfButton(*args):
topShelf = mel.eval('$nul = $gShelfTopLevel')
currentShelf = cmds.tabLayout(topShelf, q=1, st=1)
command = "from aTools.animTools.animBar import animBarUI; animBarUI.show('toggle')"
cmds.shelfButton(parent=currentShelf, annotation='aTools ON/OFF', imageOverlayLabel="aTools", i='commandButton.xpm', command=command)
def refreshATools(*args):
G.deferredManager.sendToQueue(refreshAToolsDef, 1, "refreshATools")
def refreshAToolsDef():
from aTools.animTools.animBar import animBarUI; importlib.reload(animBarUI)
animBarUI.show('refresh')
# animBot
def installAnimBot(*args):
installFileFolder = os.path.normpath(os.path.dirname(os.path.dirname(__file__)))
installFilePath = os.path.join(installFileFolder, "animBot Drag'n Drop Install.mel").replace("\\", "/") # fix for windows
mel.eval("source \"%s\";"%installFilePath)
def watchLaunchVideo(*args):
webbrowser.open_new_tab("https://youtu.be/DezLHqXrDao")
def joinTheCommunity(*args):
webbrowser.open_new_tab("https://www.facebook.com/groups/1589262684419439")

View File

@@ -0,0 +1,354 @@
'''
========================================================================================================================
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
========================================================================================================================
'''
def getHotkeys():
yellow = [{
"name":"RepeatLastTweenMachineCommand",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.tweenMachine.repeatLastCommand()",
"hotkey":"t",
"alt":0,
"ctl":0,
"toolTip":"Repeat the last Tween Machine command"
},{
"name":"SetSmartKey",
"command":"from aTools.commonMods import commandsMod; commandsMod.setSmartKey()",
"hotkey":"s",
"alt":0,
"ctl":0,
"toolTip":"Set a key without changing the tangents"
},{
"name":"SetSmartKeyOnScrub",
"command":"from aTools.commonMods import commandsMod; commandsMod.setSmartKey(insert=False)",
"hotkey":"s",
"alt":1,
"ctl":0,
"toolTip":"Copy a key dragged with middle mouse"
},{
"name":"smartSnapKeys",
"command":"from aTools.commonMods import commandsMod; commandsMod.smartSnapKeys()",
"hotkey":"S",
"alt":0,
"ctl":1,
"toolTip":"Snap decimal frame keys to the closest integer frame and preserve the curves"
},{
"name":"SelectOnlyKeyedObjects",
"command":"from aTools.commonMods import commandsMod; commandsMod.selectOnlyKeyedObjects()",
"hotkey":"s",
"alt":1,
"ctl":1,
"toolTip":"Select the objects which the selected keys belong to"
}]
green = [{
"name":"EulerFilterSelection",
"command":"from aTools.commonMods import commandsMod; commandsMod.eulerFilterSelection()",
"hotkey":"E",
"alt":0,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"ResetValue",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.keyTransform.resetValue()",
"hotkey":"0",
"alt":0,
"ctl":0,
"toolTip":"The same as the reset value button"
},{
"name":"NudgeKeyLeft",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.nudge.nudgeKey(-1)",
"hotkey":",",
"alt":0,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"NudgeKeyRight",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.nudge.nudgeKey(1)",
"hotkey":".",
"alt":0,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"AddInbetween",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.keyTransform.inbetween(1)",
"hotkey":".",
"alt":1,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"RemoveInbetween",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.keyTransform.inbetween(-1)",
"hotkey":",",
"alt":1,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"InbetweenUI",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.keyTransform.inbetweenUI()",
"hotkey":"<",
"alt":1,
"ctl":1,
"toolTip":"A GUI to help timing keys"
},{
"name":"CropTimelineAnimation",
"command":"from aTools.commonMods import commandsMod; commandsMod.cropTimelineAnimation()",
"hotkey":"X",
"alt":1,
"ctl":1,
"toolTip":"Delete all keys from timeline but the range selected"
}]
blue = [{
"name":"FlowTangent",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.tangents.setTangent('flow')",
"hotkey":"z",
"alt":1,
"ctl":1,
"toolTip":"It is the same command as the one in the aTools bar"
},{
"name":"FlowTangentAround",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.tangents.flowAround(2)",
"hotkey":"Z",
"alt":1,
"ctl":1,
"toolTip":"Will apply Flow Tangent to the selected keys plus two neighbor keys"
},{
"name":"AutoTangent",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.tangents.setTangent('auto')",
"hotkey":"z",
"alt":0,
"ctl":0,
"toolTip":"It is the same command as the one in the aTools bar"
}]
purple = [{
"name":"alignSelection",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.align.alignSelection()",
"hotkey":"a",
"alt":1,
"ctl":0,
"toolTip":"Align selection\nSelect the slaves and a master object"
},{
"name":"toggleMicroTransform",
"command":"from aTools.generalTools.aToolsGlobals import aToolsGlobals as G; G.aToolsBar.microTransform.switch()",
"hotkey":"m",
"alt":0,
"ctl":0,
"toolTip":"Toggle Micro Transform mode"
}]
red = [{
"name":"Playblast",
"command":"from maya import mel; mel.eval('performPlayblast false')",
"hotkey":"p",
"alt":1,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"FrameSection",
"command":"from aTools.commonMods import animMod; animMod.frameSection()",
"hotkey":"f",
"alt":1,
"ctl":0,
"toolTip":"In the Graph Editor, frame/zoom according to the current timeline range"
},{
"name":"FramePlaybackRange",
"command":"from aTools.animTools import framePlaybackRange; framePlaybackRange.framePlaybackRangeFn()",
"hotkey":"f",
"alt":1,
"ctl":1,
"toolTip":"In the Graph Editor, frame/zoom according to the current timeline range"
},{
"name":"FilterNonAnimatedCurves",
"command":"from aTools.commonMods import animMod; animMod.filterNonAnimatedCurves()",
"hotkey":"f",
"alt":0,
"ctl":1,
"toolTip":"Hide curves in the Graph Editor that have only keys with the same value"
},{
"name":"JumpToSelectedKey",
"command":"from aTools.commonMods import animMod; animMod.jumpToSelectedKey()",
"hotkey":"z",
"alt":1,
"ctl":0,
"toolTip":"In the Graph Editor, will go to the selected key"
},{
"name":"CopyKeyframesFromTimeline",
"command":"from maya import mel; mel.eval('timeSliderCopyKey')",
"hotkey":"c",
"alt":1,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"CutKeyframesFromTimeline",
"command":"from maya import mel; mel.eval('timeSliderCutKey')",
"hotkey":"x",
"alt":1,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"PasteKeyframesFromTimeline",
"command":"from maya import mel; mel.eval('timeSliderPasteKey false')",
"hotkey":"v",
"alt":1,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"DeleteKeyframesFromTimeline",
"command":"from maya import mel; mel.eval('timeSliderClearKey')",
"hotkey":"d",
"alt":1,
"ctl":1,
"toolTip":"It is what is says"
},{
"name":"TogglePanelLayout",
"command":"from aTools.commonMods import commandsMod; commandsMod.togglePanelLayout()",
"hotkey":"`",
"alt":0,
"ctl":0,
"toolTip":"Toggle between graph editor and persp in the main viewport"
}]
orange = [{
"name":"ToggleRotateMode",
"command":"from aTools.commonMods import commandsMod; commandsMod.toggleRotateMode()",
"hotkey":"e",
"alt":1,
"ctl":0,
"toolTip":"Toggle the rotate tool mode (world, local, gimbal)"
},{
"name":"ToggleMoveMode",
"command":"from aTools.commonMods import commandsMod; commandsMod.toggleMoveMode()",
"hotkey":"w",
"alt":1,
"ctl":0,
"toolTip":"Toggle the move tool mode (world, local, object)"
},{
"name":"OrientMoveManip",
"command":"from aTools.commonMods import commandsMod; commandsMod.orientMoveManip()",
"hotkey":"W",
"alt":0,
"ctl":1,
"toolTip":"Orient the move tool axis to the local axis of the last selected object"
},{
"name":"CameraOrientMoveManip",
"command":"from aTools.commonMods import commandsMod; commandsMod.cameraOrientMoveManip()",
"hotkey":"W",
"alt":1,
"ctl":1,
"toolTip":"Toggle the move tool mode (world, local, object)"
},{
"name":"ToggleGeometry",
"command":"from aTools.commonMods import commandsMod; commandsMod.toggleObj(['polymeshes', 'nurbsSurfaces'])",
"hotkey":"G",
"alt":0,
"ctl":0,
"toolTip":"Show or hide polygons"
},{
"name":"ToggleNurbCurves",
"command":"from aTools.commonMods import commandsMod; commandsMod.toggleObj(['nurbsCurves'])",
"hotkey":"N",
"alt":0,
"ctl":0,
"toolTip":"Show or hide nurb curves"
},{
"name":"ToggleLocators",
"command":"from aTools.commonMods import commandsMod; commandsMod.toggleObj(['locators'])",
"hotkey":"L",
"alt":0,
"ctl":0,
"toolTip":"Show or hide locators"
},{
"name":"CameraViewMode",
"command":"from aTools.commonMods import utilMod; utilMod.cameraViewMode()",
"hotkey":"C",
"alt":0,
"ctl":1,
"toolTip":"Shows only polygons"
},{
"name":"AnimViewportViewMode",
"command":"from aTools.commonMods import utilMod; utilMod.animViewportViewMode()",
"hotkey":"V",
"alt":0,
"ctl":1,
"toolTip":"Shows only polygons and nurb curves"
}]
gray = [{
"name":"setThreePanelLayout",
"command":"from aTools.commonMods import commandsMod; commandsMod.setThreePanelLayout()",
"hotkey":"3",
"alt":0,
"ctl":1,
"toolTip":"Set layout with 3 panels - camera, perspective and graph editor. Sets a couple of other attributes to the perspective camera."
},{
"name":"UnselectChannelBox",
"command":"from aTools.commonMods import commandsMod; commandsMod.unselectChannelBox()",
"hotkey":"C",
"alt":1,
"ctl":1,
"toolTip":"Unselect channels in the channel box\nGood when you want to show all channels keys in the timeline"
},{
"name":"NextFrame",
"command":"from aTools.commonMods import commandsMod; commandsMod.goToKey('next', 'frame')",
"hotkey":".",
"alt":1,
"ctl":0,
"toolTip":"Go to next frame without saving the undo state and refreshes in background, \nwhich means you can jump several frames way faster without waiting rigs refresh on every frame"
},{
"name":"NextKeyframe",
"command":"from aTools.commonMods import commandsMod; commandsMod.goToKey('next')",
"hotkey":".",
"alt":0,
"ctl":0,
"toolTip":"Go to next keyframe without saving the undo state and refreshes in background, \nwhich means you can jump several frames way faster without waiting rigs refresh on every frame"
},{
"name":"PrevFrame",
"command":"from aTools.commonMods import commandsMod; commandsMod.goToKey('previous', 'frame')",
"hotkey":",",
"alt":1,
"ctl":0,
"toolTip":"Go to previous frame without saving the undo state and refreshes in background, \nwhich means you can jump several frames way faster without waiting rigs refresh on every frame"
},{
"name":"PrevKeyframe",
"command":"from aTools.commonMods import commandsMod; commandsMod.goToKey('previous')",
"hotkey":",",
"alt":0,
"ctl":0,
"toolTip":"Go to previous keyframe without saving the undo state and refreshes in background, \nwhich means you can jump several frames way faster without waiting rigs refresh on every frame"
},{
"name":"GraphEditor",
"command":"from maya import mel; mel.eval('tearOffPanel \\\"Graph Editor\\\" \\\"graphEditor\\\" true;')",
"hotkey":"`",
"alt":0,
"ctl":1,
"toolTip":"Open the Graph Editor"
},{
"name":"Outliner",
"command":"from maya import mel; mel.eval('tearOffPanel \\\"Outliner\\\" \\\"outlinerPanel\\\" false;')",
"hotkey":"o",
"alt":0,
"ctl":0,
"toolTip":"Open the Outliner"
}]
return [yellow, green, blue, purple, red, orange, gray]

View File

@@ -0,0 +1,47 @@
import os
import sys
import shutil
from maya import mel, cmds # type: ignore
def install():
# Get the current path of aTools
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
aTools_path = os.path.normpath(current_dir).replace('\\', '/')
# Add aTools path to Maya's Python path
if aTools_path not in sys.path:
sys.path.append(aTools_path)
# Create or update userSetup.py file
maya_app_dir = mel.eval('getenv MAYA_APP_DIR')
scripts_dir = os.path.join(maya_app_dir, "scripts")
user_setup_file = os.path.join(scripts_dir, "userSetup.py")
atools_code = f"""
# Start aTools
import sys
atools_path = r"{aTools_path}"
if atools_path not in sys.path:
sys.path.append(atools_path)
from maya import cmds
if not cmds.about(batch=True):
cmds.evalDeferred("from aTools.animTools.animBar import animBarUI; animBarUI.show('launch')", lowestPriority=True)
# End aTools
"""
# If userSetup.py exists, ensure we don't add duplicate aTools code
if os.path.exists(user_setup_file):
with open(user_setup_file, 'r') as f:
content = f.read()
if "# Start aTools" not in content:
with open(user_setup_file, 'a') as f:
f.write(atools_code)
else:
with open(user_setup_file, 'w') as f:
f.write(atools_code)
print("aTools has been successfully installed.")
if __name__ == "__main__":
install()

View File

@@ -0,0 +1,111 @@
'''
========================================================================================================================
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
========================================================================================================================
Tumble on objects was adapted from:
'''
from maya import cmds
from maya import mel
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
from aTools.commonMods import utilMod
import math
class TumbleOnObjects(object):
def __init__(self):
self.currentLocalTumble = cmds.tumbleCtx ("tumbleContext", query=True, localTumble=True)
self.unitMultiplier = {"mm": 0.1,
"cm": 1.0,
"m" : 100.0,
"in": 2.54,
"ft": 30.48,
"yd": 91.44}
def switch(self, onOff):
utilMod.killScriptJobs("G.tumbleOnObjectsScriptJobs")
if onOff:
cmds.tumbleCtx ("tumbleContext", edit=True, localTumble=0)
#scriptJob
G.tumbleOnObjectsScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('DragRelease', self.update )))
G.tumbleOnObjectsScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.update )))
G.tumbleOnObjectsScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('timeChanged', self.update )))
self.update()
else:
cmds.tumbleCtx ("tumbleContext", edit=True, localTumble=self.currentLocalTumble)
def update(self):
sel = cmds.ls(selection=True)
if len(sel) > 0:
sel = sel[-1]
allowedTypes = ["transform", "joint"]
if cmds.nodeType(sel) in allowedTypes :
currUnit = cmds.currentUnit(query=True, linear=True)
unitMultiplier = self.unitMultiplier[currUnit]
isMesh = cmds.listRelatives(sel, allDescendents=True, noIntermediate=True, type="mesh") != None
if isMesh:
bb = cmds.xform(sel, query=True, boundingBox=True, ws=True)
x = ((bb[0] + bb[3])/2.)
y = ((bb[1] + bb[4])/2.)
z = ((bb[2] + bb[5])/2.)
else:
xyz = cmds.xform(sel, query=True, ws=True, rotatePivot=True)
x = xyz[0]
y = xyz[1]
z = xyz[2]
x = x * unitMultiplier
y = y * unitMultiplier
z = z * unitMultiplier
cams = cmds.ls(dag=True, cameras=True )
"""
for loopCam in cams:
if math.isnan(cmds.getAttr("%s.centerOfInterest"%loopCam)):
print "center is NAN"
if math.isnan(x) or math.isnan(y) or math.isnan(z):
print "tumble returns"
print xyz
for cam in cams:
t = cmds.xform(cam, query=True, ws=True, rotatePivot=True)
print cam, t
return
"""
cmds.undoInfo(stateWithoutFlush=False)
for loopCam in cams:
try: cmds.setAttr("%s.tumblePivot"%loopCam, x, y, z)
except: pass
cmds.undoInfo(stateWithoutFlush=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1016 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1016 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Some files were not shown because too many files have changed in this diff Show More