Updated
45
Scripts/Animation/aTools/__init__.py
Normal 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}")
|
175
Scripts/Animation/aTools/animBot Drag'n Drop Install.mel
Normal 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\
|
||||
");
|
7
Scripts/Animation/aTools/animTools/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import animBar
|
||||
from . import animationCrashRecovery
|
||||
from . import framePlaybackRange
|
||||
from . import jumpToSelectedKey
|
4
Scripts/Animation/aTools/animTools/animBar/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import *
|
174
Scripts/Animation/aTools/animTools/animBar/animBarUI.py
Normal file
@@ -0,0 +1,174 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
Modified: Michael Klimenko
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt, located in the folder aTools
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
# maya modulesspecialTools
|
||||
import importlib
|
||||
from maya import cmds
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.generalTools import aToolsClasses; importlib.reload(aToolsClasses)
|
||||
from aTools.commonMods import animMod; importlib.reload(animMod)
|
||||
from aTools.generalTools import generalToolsUI; importlib.reload(generalToolsUI)
|
||||
from aTools.commonMods import utilMod; importlib.reload(utilMod)
|
||||
from aTools.commonMods import commandsMod; importlib.reload(commandsMod)
|
||||
from aTools.commonMods import aToolsMod; importlib.reload(aToolsMod)
|
||||
from aTools import setup; importlib.reload(setup)
|
||||
|
||||
# constants
|
||||
SUB_UI_MODS = ["tweenMachine", "keyTransform", "tangents", "specialTools", "tUtilities"]
|
||||
|
||||
# import subUI modules
|
||||
for loopMod in SUB_UI_MODS:
|
||||
exec("import aTools.animTools.animBar.subUIs.%s as %s; importlib.reload(%s)"%(loopMod, loopMod, loopMod))
|
||||
|
||||
def show(mode="show"):
|
||||
|
||||
G.aToolsBar = G.aToolsBar or AnimationBar_Gui()
|
||||
|
||||
if mode == False: mode = "show"
|
||||
if mode == True: mode = "toggle"
|
||||
|
||||
if mode == "launch":
|
||||
lastState = aToolsMod.loadInfoWithUser("userPrefs", "animationBarLastState")
|
||||
if lastState: show()
|
||||
return
|
||||
|
||||
|
||||
if mode == "show" or mode == "hide":
|
||||
if cmds.toolBar("aTools_Animation_Bar", query=True, exists=True):
|
||||
visible = (mode == "show")
|
||||
cmds.toolBar("aTools_Animation_Bar", edit=True, visible=visible)
|
||||
G.aToolsBar.saveLastState(visible)
|
||||
return
|
||||
elif mode == "show":
|
||||
G.aToolsBar.start()
|
||||
G.aToolsBar.saveLastState()
|
||||
return
|
||||
|
||||
|
||||
if mode == "toggle":
|
||||
if cmds.toolBar("aTools_Animation_Bar", query=True, exists=True):
|
||||
state = cmds.toolBar("aTools_Animation_Bar", query=True, visible=True)
|
||||
visible = (not state)
|
||||
G.aToolsBar.toggleToolbars(visible)
|
||||
cmds.toolBar("aTools_Animation_Bar", edit=True, visible=visible)
|
||||
G.aToolsBar.saveLastState(visible)
|
||||
return
|
||||
else:
|
||||
show()
|
||||
return
|
||||
|
||||
if mode == "refresh":
|
||||
G.aToolsBar = AnimationBar_Gui()
|
||||
G.aToolsBar.start()
|
||||
G.aToolsBar.saveLastState()
|
||||
|
||||
|
||||
|
||||
class AnimationBar_Gui(object):
|
||||
|
||||
def __init__(self):
|
||||
self.winName = "aAnimationBarWin"
|
||||
self.toolbarName = "aTools_Animation_Bar"
|
||||
self.allWin = [self.winName, self.toolbarName]
|
||||
self.buttonSize = {"small":[15, 20], "big":[25, 25]}
|
||||
self.barOffset = 0
|
||||
self.barHotkeys = {}
|
||||
G.aToolsUIs = {"toolbars":[
|
||||
|
||||
],
|
||||
"windows":[
|
||||
|
||||
]}
|
||||
|
||||
# [ SUBUIs ]
|
||||
self.uiList = None
|
||||
self.subUIs = None
|
||||
|
||||
def __getattr__(self, attr):
|
||||
return None
|
||||
|
||||
def start(self):
|
||||
|
||||
from aTools.generalTools import aToolsClasses; importlib.reload(aToolsClasses)
|
||||
self.startUpFunctions()
|
||||
self.delWindows()
|
||||
self.createWin()
|
||||
|
||||
def startUpFunctions(self):
|
||||
#wait cursor state
|
||||
n = 0
|
||||
while True:
|
||||
if not cmds.waitCursor(query=True, state=True) or n > 100: break
|
||||
cmds.waitCursor(state=False)
|
||||
n += 1
|
||||
|
||||
#refresh state
|
||||
cmds.refresh(suspend=False)
|
||||
#undo state
|
||||
if not cmds.undoInfo(query=True, stateWithoutFlush=True): cmds.undoInfo(stateWithoutFlush=True)
|
||||
#progress bar state
|
||||
utilMod.setProgressBar(status=None, progress=None, endProgress=True)
|
||||
|
||||
|
||||
def saveLastState(self, state=True):
|
||||
aToolsMod.saveInfoWithUser("userPrefs", "animationBarLastState", state)
|
||||
|
||||
def createWin(self):
|
||||
|
||||
# Creates window
|
||||
self.mainWin = cmds.window(self.winName, sizeable=True)
|
||||
|
||||
# Main frame
|
||||
cmds.frameLayout("mainFrameLayout", labelVisible=False, borderVisible=False, w=10, marginHeight=0, marginWidth=0, labelIndent=0, collapsable=False)
|
||||
cmds.rowLayout(numberOfColumns=2, adjustableColumn=1, columnAttach=([2, 'right', self.barOffset]), h=37)
|
||||
cmds.text(label="")
|
||||
self.subUIsLayout = cmds.rowLayout("mainLayout", numberOfColumns=len(SUB_UI_MODS)+2)
|
||||
|
||||
# subUIs
|
||||
self.uiList = [eval("%s.%s%s_Gui"%(loopUi, loopUi[0].upper(), loopUi[1:])) for loopUi in SUB_UI_MODS]
|
||||
# append general tools ui
|
||||
self.uiList.append(generalToolsUI.GeneralTools_Gui)
|
||||
# define subUis
|
||||
self.subUIs = [loopUi(self.subUIsLayout, self.buttonSize) for loopUi in self.uiList]
|
||||
|
||||
self.addSubUIs()
|
||||
|
||||
# shows toolbar
|
||||
cmds.toolBar(self.toolbarName, area='bottom', content=self.mainWin, allowedArea=['bottom'])
|
||||
|
||||
# end method createWin
|
||||
#---------------------------------------------------------------------
|
||||
def addSubUIs(self):
|
||||
# parent subUis to the main layout
|
||||
for loopIndex, loopSubUI in enumerate(self.subUIs):
|
||||
loopSubUI.createLayout()
|
||||
# space
|
||||
if loopIndex < len(self.subUIs) -1:
|
||||
cmds.rowLayout(numberOfColumns=2)
|
||||
cmds.text( label=' ', h=1 )
|
||||
|
||||
# end for
|
||||
|
||||
def toggleToolbars(self, visible):
|
||||
pass
|
||||
|
||||
def delWindows(self, onOff=True, forceOff=False):
|
||||
for loopWin in self.allWin:
|
||||
if cmds.window(loopWin, query=True, exists=True): cmds.deleteUI(loopWin)
|
||||
if cmds.toolBar(loopWin, query=True, exists=True):
|
||||
cmds.deleteUI(loopWin)
|
||||
|
@@ -0,0 +1 @@
|
||||
|
1490
Scripts/Animation/aTools/animTools/animBar/subUIs/keyTransform.py
Normal file
@@ -0,0 +1,99 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
Modified: Michael Klimenko
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
import importlib
|
||||
import os
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod; importlib.reload(uiMod)
|
||||
from aTools.commonMods import utilMod; importlib.reload(utilMod)
|
||||
from aTools.commonMods import animMod; importlib.reload(animMod)
|
||||
|
||||
MODULES = ["align","selectSets","mirror","spaceSwitch","tempCustomPivot","animationCopier","fakeConstrain", "microTransform", "transformAll"]
|
||||
|
||||
# import subUI modules
|
||||
for loopMod in MODULES:
|
||||
exec("from aTools.animTools.animBar.subUIs.specialTools_subUIs import %s; importlib.reload(%s)"%(loopMod, loopMod))
|
||||
|
||||
class SpecialTools_Gui(uiMod.BaseSubUI):
|
||||
|
||||
def createLayout(self):
|
||||
|
||||
cmds.rowLayout(numberOfColumns=20, parent=self.parentLayout)
|
||||
|
||||
#SELECTION SETS
|
||||
SelectSets = selectSets.SelectSets()
|
||||
cmds.iconTextButton("selectSetsBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_select_sets"), highlightImage= uiMod.getImagePath("specialTools_select_sets copy"), w=self.wb, h=self.hb, command=SelectSets.toggleToolbar, annotation="Quick select set groups\nRight click for options")
|
||||
SelectSets.popupMenu()
|
||||
|
||||
#ALIGN
|
||||
Align = align.Align()
|
||||
cmds.iconTextButton(style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_align"), highlightImage= uiMod.getImagePath("specialTools_align copy"), w=self.wb, h=self.hb, command=Align.alignSelection, annotation="Align selection\nSelect the slaves and a master object\nRight click for options")
|
||||
Align.popupMenu()
|
||||
|
||||
#MIRROR
|
||||
Mirror = mirror.Mirror()
|
||||
cmds.iconTextButton("mirrorBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_mirror"), highlightImage= uiMod.getImagePath("specialTools_mirror copy"), w=self.wb, h=self.hb, command=Mirror.start, annotation="Mirror values to opposite ctrls\nHighlight the timeline for applying on a range\nRight click for options\n\nCtrl+click: Select mirror objects\nShift+click: Add mirror objects to selection")
|
||||
Mirror.popupMenu()
|
||||
|
||||
#SPACE SWITCH
|
||||
SpaceSwitch = spaceSwitch.SpaceSwitch()
|
||||
cmds.iconTextButton(style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_space_switcher"), highlightImage= uiMod.getImagePath("specialTools_space_switcher copy"), w=self.wb, h=self.hb, annotation="Space switcher\nIf the constraint controller is not the same as the attribute controller, select it too")
|
||||
SpaceSwitch.popupMenu()
|
||||
|
||||
#TEMP CUSTOM PIVOT
|
||||
TempCustomPivot = tempCustomPivot.TempCustomPivot()
|
||||
cmds.iconTextButton("TempCustomPivotBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_create_temp_custom_pivot"), highlightImage= uiMod.getImagePath("specialTools_create_temp_custom_pivot copy"), w=self.wb, h=self.hb, command=TempCustomPivot.create, annotation="Temporary custom pivot\nRight click for options")
|
||||
TempCustomPivot.popupMenu()
|
||||
|
||||
#ANIMATION COPIER
|
||||
AnimationCopier = animationCopier.AnimationCopier()
|
||||
cmds.iconTextButton(style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_copy_animation"), highlightImage= uiMod.getImagePath("specialTools_copy_animation copy"), w=self.wb, h=self.hb, command=AnimationCopier.copyAnimation, annotation="Animation Copier\nRight click for options")
|
||||
AnimationCopier.popupMenu()
|
||||
|
||||
#FAKE CONSTRAIN
|
||||
FakeConstrain = fakeConstrain.FakeConstrain()
|
||||
cmds.iconTextButton("fakeConstrainBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_fake_constrain"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain copy"), w=self.wb, h=self.hb, command=FakeConstrain.copyPaste, annotation="Fake Constrain\nClick once to copy objects position relative to the last selected\nGo to another frame or select a range and click again to paste\nChanging the current selection will flush the copy cache\n\nRight click for options")
|
||||
FakeConstrain.popupMenu()
|
||||
|
||||
# motion trail is disabled, please use the built-in
|
||||
# #MOTION TRAIL
|
||||
# MotionTrail = motionTrail.MotionTrail()
|
||||
# MotionTrail.toolBarButton = cmds.iconTextButton("motionTrailBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_motion_trail"), highlightImage= uiMod.getImagePath("specialTools_motion_trail copy"), w=self.wb, h=self.hb, command=MotionTrail.switch, annotation="Motion trail\nRight click for options")
|
||||
# MotionTrail.popupMenu()
|
||||
# #cmds.iconTextButton("motionTrailBtnOLD", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_motion_trail"), highlightImage= uiMod.getImagePath("specialTools_motion_trail copy"), w=self.wb, h=self.hb, command=self.motionTrail, annotation="Motion trail")
|
||||
|
||||
|
||||
#MICRO TRANSFORM
|
||||
MicroTransform = microTransform.MicroTransform()
|
||||
cmds.iconTextButton("microTransformBtn", style='iconAndTextVertical', image= uiMod.getImagePath("specialTools_micro_transform"), highlightImage= uiMod.getImagePath("specialTools_micro_transform copy"), w=self.wb, h=self.hb, command=MicroTransform.switch, annotation="Enable micro transform\nRight click for options")
|
||||
MicroTransform.popupMenu()
|
||||
|
||||
|
||||
#TRANSFORM ALL
|
||||
TransformAll = transformAll.TransformAll()
|
||||
cmds.iconTextButton ("transformAllBtn", style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("specialTools_transform_all"), highlightImage= uiMod.getImagePath("specialTools_transform_all copy"), command=TransformAll.switch, annotation="Enable transform all keys\nWill affect selected range or all keys if no range is selected\nCtrl+click will toggle blend range mode")
|
||||
#TransformAll.popupMenu()
|
||||
|
||||
|
||||
|
||||
# end createLayout
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1 @@
|
||||
|
@@ -0,0 +1,177 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
|
||||
class Align(object):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
if G.aToolsBar.align: return
|
||||
G.aToolsBar.align = self
|
||||
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu()
|
||||
cmds.menuItem(label="All Keys", command=self.alignAllKeys)
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem(label="Align Position", command=lambda *args: self.alignSelection(True, False))
|
||||
cmds.menuItem(label="Align Rotation", command=lambda *args: self.alignSelection(False, True))
|
||||
|
||||
|
||||
def alignAllKeys(self, *args):
|
||||
self.alignSelection(translate=True, rotate=True, all=True)
|
||||
|
||||
def alignSelection(self, translate=True, rotate=True, all=False):
|
||||
|
||||
selection = cmds.ls(selection=True)
|
||||
|
||||
if len(selection) < 2:
|
||||
cmds.warning("You need to select at least 2 objects.")
|
||||
return
|
||||
|
||||
sourceObjs = selection[0:-1]
|
||||
targetObj = selection[-1]
|
||||
frames = None
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
showProgress = all
|
||||
|
||||
|
||||
if animCurves:
|
||||
if all: keysSel = animMod.getTarget("keyTimes", animCurves, getFrom)
|
||||
else: keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
|
||||
frames = utilMod.mergeLists(keysSel)
|
||||
|
||||
if frames == []:
|
||||
frames = [currFrame]
|
||||
else:
|
||||
frames = [currFrame]
|
||||
|
||||
self.align(sourceObjs, targetObj, frames, translate, rotate, showProgress, selectSorceObjs=True)
|
||||
|
||||
|
||||
def align(self, sourceObjs, targetObj, frames=None, translate=True, rotate=True, showProgress=False, selectSorceObjs=False):
|
||||
|
||||
if not sourceObjs or not targetObj: return
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
constraints = []
|
||||
setValues = []
|
||||
modes = []
|
||||
status = "aTools - Aligning nodes..."
|
||||
|
||||
if translate: modes.append({"mode":"translate", "constrain":"pointConstraint"})
|
||||
if rotate: modes.append({"mode":"rotate", "constrain":"orientConstraint"})
|
||||
|
||||
if showProgress: utilMod.startProgressBar(status)
|
||||
|
||||
if not frames:
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
|
||||
if animCurves:
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
frames = utilMod.mergeLists(keysSel)
|
||||
|
||||
if frames == []:
|
||||
frames = [currFrame]
|
||||
else:
|
||||
frames = [currFrame]
|
||||
|
||||
if showProgress:
|
||||
totalSteps = len(sourceObjs + frames)
|
||||
firstStep = 0
|
||||
thisStep = 0
|
||||
estimatedTime = None
|
||||
startChrono = None
|
||||
|
||||
|
||||
#get values
|
||||
for thisStep, loopSourceObj in enumerate(sourceObjs):
|
||||
|
||||
if showProgress: startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
|
||||
|
||||
setValues.append({"modes":[], "values":[], "skips":[]})
|
||||
|
||||
for loopMode in modes:
|
||||
|
||||
mode = loopMode["mode"]
|
||||
constrainType = loopMode["constrain"]
|
||||
|
||||
allAttrs = cmds.listAttr(loopSourceObj, settable=True, keyable=True)
|
||||
skip = [loopXyz for loopXyz in ["x", "y", "z"] if "%s%s"%(mode, loopXyz.upper()) not in allAttrs]
|
||||
contrainFn = eval("cmds.%s"%constrainType)
|
||||
|
||||
with G.aToolsBar.createAToolsNode: constraints.append(contrainFn(targetObj, loopSourceObj, skip=skip)[0])
|
||||
|
||||
setValues[-1]["modes"].append(mode)
|
||||
setValues[-1]["values"].append([cmds.getAttr("%s.%s"%(loopSourceObj, mode), time=loopKey)[0] for loopKey in frames])
|
||||
setValues[-1]["skips"].append(skip)
|
||||
|
||||
|
||||
if showProgress: estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
|
||||
|
||||
#del constraints
|
||||
for loopConstrain in constraints: cmds.delete(loopConstrain)
|
||||
|
||||
for n, loopKey in enumerate(frames):
|
||||
|
||||
if showProgress:
|
||||
thisStep = thisStep + n + 1
|
||||
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
|
||||
|
||||
for nn, loopSourceObj in enumerate(sourceObjs):
|
||||
loopSetValue = setValues[nn]
|
||||
values = loopSetValue["values"]
|
||||
skips = loopSetValue["skips"]
|
||||
|
||||
for nnn, loopMode in enumerate(modes):
|
||||
mode = loopMode["mode"]
|
||||
xyz = [loopXyz for loopXyz in ["x", "y", "z"] if loopXyz not in skips[nnn]]
|
||||
|
||||
|
||||
for nnnn, loopXyz in enumerate(xyz):
|
||||
attr = "%s%s"%(mode, loopXyz.upper())
|
||||
value = values[nnn][n][nnnn]
|
||||
|
||||
if len(frames) > 1:
|
||||
cmds.setKeyframe(loopSourceObj, attribute=attr, time=(loopKey,loopKey), value=value)
|
||||
|
||||
if currFrame == loopKey: cmds.setAttr("%s.%s"%(loopSourceObj, attr), value)
|
||||
|
||||
#euler filter
|
||||
if n == len(frames)-1 and rotate:
|
||||
animCurves = utilMod.mergeLists([cmds.keyframe(loopSourceObj, query=True, name=True) for loopSourceObj in sourceObjs])
|
||||
animMod.eulerFilterCurve(animCurves)
|
||||
|
||||
if showProgress: estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
|
||||
|
||||
if showProgress: utilMod.setProgressBar(endProgress=True)
|
||||
if selectSorceObjs: cmds.select(sourceObjs)
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
|
@@ -0,0 +1,116 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
|
||||
class AnimationCopier(object):
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu()
|
||||
cmds.menuItem( label="Copy All Animation", command=lambda *args: self.copyAnimation(range="all"))
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem("onlySelectedNodesMenu", label="Paste To Selected", checkBox=False)
|
||||
cmds.menuItem( label="Paste Animation in Place", command=lambda *args: self.pasteAnimation(pasteInPlace=True))
|
||||
cmds.menuItem( label="Paste Original Animation", command=lambda *args: self.pasteAnimation(pasteInPlace=False))
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem( label="Paste To Another Character", command=self.remapNamespaces)
|
||||
|
||||
|
||||
def copyAnimation(self, range="selected", *args):
|
||||
cmds.waitCursor(state=True)
|
||||
|
||||
if range == "all":
|
||||
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
animData = animMod.getAnimData(animCurves, showProgress=True)
|
||||
else:
|
||||
animData = animMod.getAnimData(showProgress=True)
|
||||
|
||||
aToolsMod.saveInfoWithUser("copyPasteAnim", "animData", animData)
|
||||
|
||||
if cmds.window("remapNamespacesWindow", query=True, exists=True): self.remapNamespaces()
|
||||
|
||||
cmds.waitCursor(state=False)
|
||||
|
||||
def pasteAnimation(self, animData=None, pasteInPlace=True, onlySelectedNodes=None, *args):
|
||||
cmds.waitCursor(state=True)
|
||||
|
||||
if not onlySelectedNodes: onlySelectedNodes = cmds.menuItem("onlySelectedNodesMenu", query=True, checkBox=True)
|
||||
if not animData: animData = aToolsMod.loadInfoWithUser("copyPasteAnim", "animData")
|
||||
animMod.applyAnimData(animData, pasteInPlace, onlySelectedNodes, showProgress=True)
|
||||
|
||||
cmds.waitCursor(state=False)
|
||||
|
||||
def remapNamespaces(self, *args):
|
||||
winName = "remapNamespacesWindow"
|
||||
if cmds.window(winName, query=True, exists=True): cmds.deleteUI(winName)
|
||||
window = cmds.window( winName, title = "Remap Namespaces")
|
||||
|
||||
cmds.columnLayout(adjustableColumn=True)
|
||||
cmds.rowColumnLayout( numberOfColumns=3)
|
||||
|
||||
animData = aToolsMod.loadInfoWithUser("copyPasteAnim", "animData")
|
||||
inputNameSpaces = list(set(utilMod.getNameSpace(animData["objects"])[0]))
|
||||
outputNameSpaces = utilMod.listAllNamespaces()
|
||||
|
||||
for loopNameSpace in inputNameSpaces:
|
||||
|
||||
nameSpace = loopNameSpace[:-1]
|
||||
|
||||
eval("cmds.text('input%s', align='right', w=150, h=26, label='%s: ')"%(nameSpace, nameSpace))
|
||||
eval("cmds.textField('output%s', w=150, h=26, text='%s')"%(nameSpace, nameSpace))
|
||||
eval("cmds.button('output%s', w=26, h=26, label='...')"%(nameSpace))
|
||||
if outputNameSpaces:
|
||||
cmds.popupMenu(button=1)
|
||||
for loopOutput in outputNameSpaces:
|
||||
cmds.menuItem ("menu%s"%loopOutput, label=str(loopOutput), command=lambda x, loopOutput=loopOutput, nameSpace=nameSpace, *args: self.setOutputValue(loopOutput, nameSpace))
|
||||
|
||||
cmds.setParent( '..' )
|
||||
|
||||
|
||||
cmds.button(label="Paste Animation in Place", command=lambda *args: self.remapAndPasteAnimation(animData, inputNameSpaces, pasteInPlace=True))
|
||||
cmds.button(label="Paste Original Animation", command=lambda *args: self.remapAndPasteAnimation(animData, inputNameSpaces, pasteInPlace=False))
|
||||
|
||||
cmds.showWindow( window )
|
||||
|
||||
def setOutputValue(self, output, nameSpace):
|
||||
cmds.textField('output%s'%nameSpace, edit=True, text=str(output))
|
||||
|
||||
def remapAndPasteAnimation(self, animData, nameSpaces, pasteInPlace):
|
||||
|
||||
|
||||
separator = ":"
|
||||
|
||||
for loopNameSpace in nameSpaces:
|
||||
|
||||
nameSpace = loopNameSpace[:-1]
|
||||
|
||||
input = nameSpace
|
||||
output = cmds.textField('output%s'%nameSpace, query=True, text=True)
|
||||
|
||||
animStr = str(animData)
|
||||
animData = eval(animStr.replace("%s%s"%(input, separator), "%s%s"%(output, separator)))
|
||||
|
||||
self.pasteAnimation(animData, pasteInPlace)
|
||||
|
||||
|
@@ -0,0 +1,236 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
|
||||
|
||||
class FakeConstrain(object):
|
||||
|
||||
def __init__(self):
|
||||
self.copyCache = []
|
||||
self.locators = []
|
||||
self.locatorGroup = ""
|
||||
self.locatorGroupName = "fakeConstrain_group"
|
||||
self.selection = None
|
||||
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu(postMenuCommand=self.populateMenu)
|
||||
|
||||
def populateMenu(self, menu, *args):
|
||||
|
||||
uiMod.clearMenuItems(menu)
|
||||
|
||||
if self.copyCache != []:
|
||||
cmds.menuItem(label='Copy', command=self.copy, parent=menu)
|
||||
cmds.menuItem(label='Paste to All Frames' , command=lambda *args: self.paste('allFrames'), parent=menu)
|
||||
cmds.menuItem(divider=True, parent=menu)
|
||||
|
||||
|
||||
cmds.menuItem(label='Copy Relative to World' , command=self.copyWorld, parent=menu)
|
||||
|
||||
def copyPaste(self):
|
||||
|
||||
if len(self.copyCache) > 0: self.paste()
|
||||
else: self.copy()
|
||||
|
||||
def copy(self, *args):
|
||||
#print "copy"
|
||||
self.selection = cmds.ls(selection=True)
|
||||
|
||||
if len(self.selection) < 1:
|
||||
cmds.warning("You need to select at least 2 objects.")
|
||||
return
|
||||
if len(self.selection) == 1:
|
||||
self.copyWorld()
|
||||
return
|
||||
|
||||
if len(self.selection) > 20:
|
||||
message = "Too many objects selected, continue?"
|
||||
confirm = cmds.confirmDialog( title='Confirm', message=message, button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No' )
|
||||
if confirm != 'Yes': return
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
self.flushCopyCache(force=True)
|
||||
self.scriptJob()
|
||||
|
||||
self.sourceObjs = self.selection[0:-1]
|
||||
self.targetObj = self.selection[-1]
|
||||
selObjects = utilMod.getNameSpace(self.selection)[1]
|
||||
self.locators = []
|
||||
|
||||
self.locatorGroup = animMod.group(name=self.locatorGroupName)
|
||||
G.aToolsBar.align.align([self.locatorGroup], self.targetObj)
|
||||
self.locators.append(self.locatorGroup)
|
||||
|
||||
|
||||
for loopObj in self.sourceObjs:
|
||||
|
||||
nameSpace = utilMod.getNameSpace([loopObj])
|
||||
loopSelName = "%s_%s"%(nameSpace[0][0], nameSpace[1][0])
|
||||
locatorName = "fakeConstrain_%s"%loopSelName
|
||||
|
||||
locator = animMod.createNull(locatorName)
|
||||
self.locators.append(locator)
|
||||
with G.aToolsBar.createAToolsNode: cmds.parent(locator, self.locatorGroup)
|
||||
G.aToolsBar.align.align([locator], loopObj)
|
||||
|
||||
matrix = cmds.xform(locator, query=True, matrix=True)
|
||||
|
||||
self.copyCache.append(matrix)
|
||||
|
||||
self.clearLocators()
|
||||
|
||||
cmds.select(self.selection)
|
||||
|
||||
cmds.iconTextButton("fakeConstrainBtn", edit=True, image= uiMod.getImagePath("specialTools_fake_constrain_active"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain_active copy"))
|
||||
|
||||
cmds.refresh(suspend=False)
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
def copyWorld(self, *args):
|
||||
#print "copyworld"
|
||||
self.selection = cmds.ls(selection=True)
|
||||
|
||||
if len(self.selection) < 1: return
|
||||
|
||||
if len(self.selection) > 20:
|
||||
message = "Too many objects selected, continue?"
|
||||
confirm = cmds.confirmDialog( title='Confirm', message=message, button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No' )
|
||||
if confirm != 'Yes': return
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
|
||||
self.flushCopyCache(force=True)
|
||||
self.scriptJob()
|
||||
|
||||
self.sourceObjs = self.selection
|
||||
self.targetObj = "world"
|
||||
|
||||
for loopObj in self.sourceObjs:
|
||||
matrix = cmds.xform(loopObj, query=True, ws=True, matrix=True)
|
||||
|
||||
self.copyCache.append(matrix)
|
||||
|
||||
|
||||
cmds.iconTextButton("fakeConstrainBtn", edit=True, image= uiMod.getImagePath("specialTools_fake_constrain_active"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain_active copy"))
|
||||
|
||||
cmds.refresh(suspend=False)
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
def paste(self, type="onlyKeys"):
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
selObjects = utilMod.getNameSpace(self.selection)[1]
|
||||
self.locators = []
|
||||
|
||||
if self.targetObj != "world":
|
||||
#CREATE
|
||||
self.locatorGroup = animMod.group(name=self.locatorGroupName)
|
||||
|
||||
for n, loopObj in enumerate(self.sourceObjs):
|
||||
|
||||
nameSpace = utilMod.getNameSpace([loopObj])
|
||||
loopSelName = "%s_%s"%(nameSpace[0][0], nameSpace[1][0])
|
||||
locatorName = "fakeConstrain_%s"%loopSelName
|
||||
|
||||
locator = animMod.createNull(locatorName)
|
||||
self.locators.append(locator)
|
||||
with G.aToolsBar.createAToolsNode: cmds.parent(locator, self.locatorGroup)
|
||||
|
||||
self.locators.append(self.locatorGroup)
|
||||
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
if animCurves:
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
keysSel = utilMod.mergeLists(keysSel)
|
||||
if keysSel == []:
|
||||
keysSel = [currFrame]
|
||||
else:
|
||||
keysSel = [currFrame]
|
||||
|
||||
frames = keysSel
|
||||
|
||||
if type == "allFrames":
|
||||
frameRange = animMod.getTimelineRange(float=False)
|
||||
frames = list(range(int(frameRange[0]),int(frameRange[1])))
|
||||
|
||||
if self.targetObj != "world":
|
||||
G.aToolsBar.align.align([self.locatorGroup], self.targetObj, frames=frames)
|
||||
|
||||
for n, loopObj in enumerate(self.sourceObjs):
|
||||
|
||||
matrix = self.copyCache[n]
|
||||
|
||||
if self.targetObj != "world":
|
||||
cmds.xform(self.locators[n], matrix=matrix)
|
||||
|
||||
G.aToolsBar.align.align([loopObj], self.locators[n], frames=frames, showProgress=True)
|
||||
|
||||
else:
|
||||
for loopFrame in frames:
|
||||
cmds.currentTime(loopFrame)
|
||||
cmds.xform(loopObj, ws=True, matrix=matrix)
|
||||
|
||||
cmds.currentTime(currFrame)
|
||||
|
||||
for loopFrame in frames:
|
||||
for loopAttr in ["translate", "rotate"]:
|
||||
breakdown = (loopFrame not in keysSel)
|
||||
cmds.keyframe(loopObj, edit=True, attribute=loopAttr, time=(loopFrame, loopFrame), breakdown=breakdown)
|
||||
|
||||
|
||||
if self.targetObj != "world":
|
||||
self.clearLocators()
|
||||
cmds.select(self.selection)
|
||||
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
|
||||
def clearLocators(self):
|
||||
|
||||
for loopLocator in self.locators:
|
||||
if cmds.objExists(loopLocator): cmds.delete(loopLocator)
|
||||
|
||||
if cmds.objExists(self.locatorGroup): cmds.delete(self.locatorGroup)
|
||||
|
||||
def flushCopyCache(self, force=False):
|
||||
|
||||
if not force and cmds.ls(selection=True) == self.selection:
|
||||
self.scriptJob()
|
||||
return
|
||||
|
||||
cmds.iconTextButton("fakeConstrainBtn", edit=True, image= uiMod.getImagePath("specialTools_fake_constrain"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain copy"))
|
||||
|
||||
self.clearLocators()
|
||||
self.copyCache = []
|
||||
|
||||
def scriptJob(self):
|
||||
#scriptjob
|
||||
cmds.scriptJob(runOnce = True, killWithScene = True, event =('SelectionChanged', self.flushCopyCache))
|
||||
|
@@ -0,0 +1,321 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
Modified: Michael Klimenko
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
import maya.OpenMaya as om
|
||||
|
||||
#============================================================================================================
|
||||
class MicroTransform(object):
|
||||
|
||||
utilMod.killScriptJobs("G.microTransformScriptJobs")
|
||||
|
||||
def __init__(self):
|
||||
|
||||
G.deferredManager.removeFromQueue("MT_blinking")
|
||||
|
||||
if G.aToolsBar.microTransform: return
|
||||
G.aToolsBar.microTransform = self
|
||||
|
||||
self.attributes = ['translate', 'translateX','translateY','translateZ','rotate', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scaleX','scaleY','scaleZ']
|
||||
|
||||
self.multiplierValues = [ {"name":"ultraSlow", "value":.05
|
||||
},{"name":"superSlow", "value":.2
|
||||
},{"name":"slow", "value":.5
|
||||
},{"name":"medium", "value":1
|
||||
}]
|
||||
self.defaultMultiplier = "slow"
|
||||
self.microTransformStartTimer = {}
|
||||
self.microTransformValues = {}
|
||||
self.onOff = False
|
||||
self.rotationOrientMode = cmds.manipRotateContext('Rotate', query=True, mode=True)
|
||||
|
||||
self.setMultiplier(self.getMultiplier())
|
||||
self.removeMicroTransform()
|
||||
self.blinkingButton(self.onOff)
|
||||
|
||||
|
||||
def blinkingButton(self, onOff):
|
||||
|
||||
if onOff: G.aToolsBar.timeoutInterval.setInterval(self.toggleButtonActive, .3, id="MT_blinking")
|
||||
else: G.aToolsBar.timeoutInterval.stopInterval("MT_blinking")
|
||||
|
||||
|
||||
def toggleButtonActive(self):
|
||||
onOff = "active" in cmds.iconTextButton("microTransformBtn", query=True, image=True)
|
||||
|
||||
self.setButtonImg(not onOff)
|
||||
|
||||
def setButtonImg(self, onOff):
|
||||
if onOff:
|
||||
cmds.iconTextButton("microTransformBtn", edit=True, image=uiMod.getImagePath("specialTools_micro_transform_active"), highlightImage= uiMod.getImagePath("specialTools_micro_transform_active"))
|
||||
else:
|
||||
cmds.iconTextButton("microTransformBtn", edit=True, image=uiMod.getImagePath("specialTools_micro_transform"), highlightImage= uiMod.getImagePath("specialTools_micro_transform copy"))
|
||||
|
||||
|
||||
def switch(self):
|
||||
|
||||
self.onOff = (not self.onOff)
|
||||
self.setButtonImg(self.onOff)
|
||||
self.blinkingButton(self.onOff)
|
||||
self.setMode(self.onOff)
|
||||
|
||||
|
||||
def setMode(self, onOff):
|
||||
|
||||
utilMod.killScriptJobs("G.microTransformScriptJobs")
|
||||
|
||||
if onOff:
|
||||
|
||||
self.rotationOrientMode = cmds.manipRotateContext('Rotate', query=True, mode=True)
|
||||
cmds.manipRotateContext('Rotate', edit=True, mode=2)#gimbal
|
||||
#update values on turning on
|
||||
self.addMicroTransform()
|
||||
|
||||
G.microTransformScriptJobs = []
|
||||
# get the current selected object values
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.addMicroTransform )))
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('timeChanged', self.updateValues )))
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('Undo', self.updateValues )))
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('Redo', self.updateValues )))
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('DragRelease', self.release )))
|
||||
|
||||
|
||||
|
||||
#print "microTransform is ON."
|
||||
|
||||
else:
|
||||
cmds.manipRotateContext('Rotate', edit=True, mode=self.rotationOrientMode)
|
||||
self.removeMicroTransform()
|
||||
#print "microTransform is OFF."
|
||||
|
||||
|
||||
def changedMicroTransform(self, msg, mplug, otherMplug, clientData):
|
||||
|
||||
#cmds.undoInfo(stateWithoutFlush=False)
|
||||
|
||||
|
||||
if om.MNodeMessage.kAttributeSet == (om.MNodeMessage.kAttributeSet & msg) and not om.MGlobal.isUndoing() and not om.MGlobal.isRedoing():
|
||||
nodeName, attrName = mplug.name().split('.')
|
||||
|
||||
#print "changed!"
|
||||
|
||||
if attrName not in self.attributes: return
|
||||
|
||||
nodeAttr = mplug.name()
|
||||
val = cmds.getAttr(nodeAttr)
|
||||
mtValue = self.microTransformValues["%s_%s"%(nodeName, attrName)]
|
||||
|
||||
if str(val) != str(mtValue):
|
||||
#timer
|
||||
if "%s"%nodeName not in self.microTransformStartTimer:
|
||||
self.microTransformStartTimer["%s"%nodeName] = cmds.timerX()
|
||||
microTransformTimer = cmds.timerX(startTime=self.microTransformStartTimer["%s"%nodeName])
|
||||
self.microTransformStartTimer["%s"%nodeName] = cmds.timerX()
|
||||
|
||||
microTransformTimer *= 50
|
||||
if microTransformTimer == 0: microTransformTimer = 1000
|
||||
mult = self.multiplier/microTransformTimer
|
||||
|
||||
|
||||
if mult >= self.multiplier: mult = self.multiplier
|
||||
|
||||
|
||||
self.undoChunkFn("open")
|
||||
#print "changedMicroTransform"
|
||||
|
||||
if type(val) is list:
|
||||
|
||||
temp = ()
|
||||
for n, loopVal in enumerate(val[0]):
|
||||
dif = loopVal-mtValue[0][n]
|
||||
temp = temp + (mtValue[0][n]+(dif*mult),)
|
||||
newVal = [temp]
|
||||
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName)] = newVal
|
||||
#xyz
|
||||
self.microTransformValues["%s_%sX"%(nodeName, attrName)] = newVal[0][0]
|
||||
self.microTransformValues["%s_%sY"%(nodeName, attrName)] = newVal[0][1]
|
||||
self.microTransformValues["%s_%sZ"%(nodeName, attrName)] = newVal[0][2]
|
||||
|
||||
eval("cmds.setAttr(nodeAttr, %s,%s,%s)"%(newVal[0][0],newVal[0][1],newVal[0][2]))
|
||||
#xyz
|
||||
cmds.setAttr("%sX"%nodeAttr, newVal[0][0])
|
||||
cmds.setAttr("%sY"%nodeAttr, newVal[0][1])
|
||||
cmds.setAttr("%sZ"%nodeAttr, newVal[0][2])
|
||||
|
||||
|
||||
else:
|
||||
dif = val-mtValue
|
||||
newVal = mtValue+(dif*mult)
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName)] = newVal
|
||||
|
||||
#xyz inverse
|
||||
val = cmds.getAttr("%s.%s"%(nodeName, attrName[:-1]))
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName[:-1])] = val
|
||||
|
||||
cmds.setAttr(nodeAttr, newVal)
|
||||
|
||||
|
||||
else:
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName)] = cmds.getAttr(nodeAttr)
|
||||
if type(val) is list:
|
||||
valX = cmds.getAttr("%s.%sX"%(nodeName, attrName))
|
||||
valY = cmds.getAttr("%s.%sY"%(nodeName, attrName))
|
||||
valZ = cmds.getAttr("%s.%sZ"%(nodeName, attrName))
|
||||
#xyz
|
||||
self.microTransformValues["%s_%sX"%(nodeName, attrName)] = valX
|
||||
self.microTransformValues["%s_%sY"%(nodeName, attrName)] = valY
|
||||
self.microTransformValues["%s_%sZ"%(nodeName, attrName)] = valZ
|
||||
|
||||
else:
|
||||
#xyz inverse
|
||||
val = cmds.getAttr("%s.%s"%(nodeName, attrName[:-1]))
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName[:-1])] = val
|
||||
|
||||
|
||||
#cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
def release(self):
|
||||
|
||||
self.undoChunkFn("close")
|
||||
self.updateValues()
|
||||
self.microTransformStartTimer = {}
|
||||
|
||||
|
||||
def undoChunkFn(self, openClose):
|
||||
if openClose == "open":
|
||||
if self.undoChunk == "closed":
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
self.undoChunk = "open"
|
||||
#print "openChunk"
|
||||
else:
|
||||
if self.undoChunk == "open":
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
self.undoChunk = "closed"
|
||||
#print "closeChunk"
|
||||
|
||||
def addMicroTransform(self):
|
||||
|
||||
self.updateValues()
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
|
||||
|
||||
sel = cmds.ls(selection=True)
|
||||
|
||||
if G.MT_lastSel:
|
||||
graphEditorFocus = cmds.getPanel(withFocus=True) == "graphEditor1"
|
||||
if sel == G.MT_lastSel and graphEditorFocus:
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
return
|
||||
|
||||
G.MT_lastSel = sel
|
||||
|
||||
if len(sel) <= 0:
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
return
|
||||
|
||||
self.removeMicroTransform()
|
||||
G.microTransformIds = []
|
||||
self.undoChunk = "closed"
|
||||
MSelectionList = om.MSelectionList()
|
||||
om.MGlobal.getActiveSelectionList(MSelectionList)
|
||||
node = om.MObject()
|
||||
|
||||
for n, loopSel in enumerate(sel):
|
||||
|
||||
MSelectionList.getDependNode(n, node)
|
||||
clientData = None
|
||||
G.microTransformIds.append(om.MNodeMessage.addAttributeChangedCallback(node, self.changedMicroTransform, clientData))
|
||||
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
|
||||
def removeMicroTransform(self):
|
||||
|
||||
try:
|
||||
for loopId in G.microTransformIds:
|
||||
om.MNodeMessage.removeCallback(loopId)
|
||||
except: pass
|
||||
|
||||
G.microTransformIds = None
|
||||
|
||||
|
||||
|
||||
|
||||
def updateValues(self):
|
||||
#print "updateValues"
|
||||
|
||||
self.microTransformValues = {}
|
||||
sel = cmds.ls(selection=True)
|
||||
|
||||
for loopSel in sel:
|
||||
for loopAttr in self.attributes:
|
||||
val = cmds.getAttr("%s.%s"%(loopSel, loopAttr))
|
||||
self.microTransformValues["%s_%s"%(loopSel, loopAttr)] = val
|
||||
|
||||
|
||||
def setMultiplier(self, option):
|
||||
name = None
|
||||
for loopOption in self.multiplierValues:
|
||||
if loopOption["name"] == option:
|
||||
value = loopOption["value"]
|
||||
name = loopOption["name"]
|
||||
|
||||
if not name: #in case file is corrupt
|
||||
self.setMultiplier(self.defaultMultiplier)
|
||||
return
|
||||
|
||||
self.multiplier = value
|
||||
aToolsMod.saveInfoWithUser("userPrefs", "microTransform", name)
|
||||
|
||||
def getMultiplier(self):
|
||||
name = aToolsMod.loadInfoWithUser("userPrefs", "microTransform")
|
||||
if name == None: name = self.defaultMultiplier
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def popupMenu(self, *args):
|
||||
menu = cmds.popupMenu()
|
||||
cmds.popupMenu(menu, edit=True, postMenuCommand=self.populateMenu, postMenuCommandOnce=True)
|
||||
|
||||
|
||||
def populateMenu(self, menu, *args):
|
||||
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
for loopOption in self.multiplierValues:
|
||||
radioSelected = (self.multiplier == loopOption["value"])
|
||||
option = loopOption["name"]
|
||||
cmds.menuItem (label=utilMod.toTitle(loopOption["name"]), radioButton=radioSelected, command=lambda x, option=option, *args: self.setMultiplier(option), parent=menu)
|
||||
|
||||
|
||||
|
@@ -0,0 +1,319 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
class Mirror(object):
|
||||
|
||||
|
||||
utilMod.killScriptJobs("G.mirrorScriptJobs")
|
||||
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.INVERT_RULES_PREFS = [{ "name":"invertRulesMirrorObjsTranslateX",
|
||||
"default":True
|
||||
},{ "name":"invertRulesMirrorObjsTranslateY",
|
||||
"default":False
|
||||
},{ "name":"invertRulesMirrorObjsTranslateZ",
|
||||
"default":False
|
||||
},{ "name":"invertRulesMirrorObjsRotateX",
|
||||
"default":False
|
||||
},{ "name":"invertRulesMirrorObjsRotateY",
|
||||
"default":False
|
||||
},{ "name":"invertRulesMirrorObjsRotateZ",
|
||||
"default":False
|
||||
},{ "name":"invertRulesCenterObjsTranslateX",
|
||||
"default":True
|
||||
},{ "name":"invertRulesCenterObjsTranslateY",
|
||||
"default":False
|
||||
},{ "name":"invertRulesCenterObjsTranslateZ",
|
||||
"default":False
|
||||
},{ "name":"invertRulesCenterObjsRotateX",
|
||||
"default":False
|
||||
},{ "name":"invertRulesCenterObjsRotateY",
|
||||
"default":True
|
||||
},{ "name":"invertRulesCenterObjsRotateZ",
|
||||
"default":True
|
||||
}]
|
||||
|
||||
def start(self):
|
||||
mod = uiMod.getModKeyPressed()
|
||||
|
||||
if mod == "shift":
|
||||
self.selectMirrorObjs(True)
|
||||
elif mod == "ctrl":
|
||||
self.selectMirrorObjs(False)
|
||||
else:
|
||||
sel = cmds.ls(selection=True)
|
||||
if sel: self.applyMirror()
|
||||
else: self.toggleAutoSelectMirrorObjects()
|
||||
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu()
|
||||
cmds.menuItem("autoSelectMirrorObjectsMenu", label='Auto Select Mirror Objects' , checkBox=False, command=self.toggleAutoSelectMirrorObjects)
|
||||
cmds.menuItem("invertRulesMenu", subMenu=True, label='Invert Rules' , tearOff=True)
|
||||
for n, loopPref in enumerate(self.INVERT_RULES_PREFS):
|
||||
name = loopPref["name"]
|
||||
if n == 6: cmds.menuItem( divider=True )
|
||||
|
||||
cmds.menuItem('%sMenu'%name, label=utilMod.toTitle(name[11:]), command=lambda x, name=name, *args: aToolsMod.setPref(name, self.INVERT_RULES_PREFS), checkBox=aToolsMod.getPref(name, self.INVERT_RULES_PREFS))
|
||||
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem("loadDefaultsInvertRulesMenu", label="Load Defaults", command=lambda *args:utilMod.loadDefaultPrefs(self.INVERT_RULES_PREFS))
|
||||
cmds.setParent( '..', menu=True )
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem(label="Unselect Right", command=lambda *args: self.unselectMirrorObjs("right"))
|
||||
cmds.menuItem(label="Unselect Left", command=lambda *args: self.unselectMirrorObjs("left"))
|
||||
cmds.menuItem(label="Unselect Center", command=lambda *args: self.unselectMirrorObjs("center"))
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem(label="Paste And Invert Cycle", command=lambda *args: self.applyMirror(pasteAndCycle=True))
|
||||
|
||||
|
||||
def toggleAutoSelectMirrorObjects(self, *args):
|
||||
|
||||
onOff = not cmds.menuItem("autoSelectMirrorObjectsMenu", query=True , checkBox=True)
|
||||
if args: onOff = not onOff #if checkbox pressed
|
||||
|
||||
if onOff: cmds.iconTextButton("mirrorBtn", edit=True, image=uiMod.getImagePath("specialTools_mirror_active"), highlightImage= uiMod.getImagePath("specialTools_mirror_active"))
|
||||
else: cmds.iconTextButton("mirrorBtn", edit=True, image=uiMod.getImagePath("specialTools_mirror"), highlightImage= uiMod.getImagePath("specialTools_mirror copy"))
|
||||
|
||||
self.setAutoSelectMirrorObjects(onOff)
|
||||
if not args:cmds.menuItem("autoSelectMirrorObjectsMenu", edit=True , checkBox=onOff)
|
||||
|
||||
|
||||
def setAutoSelectMirrorObjects(self, onOff):
|
||||
|
||||
utilMod.killScriptJobs("G.mirrorScriptJobs")
|
||||
|
||||
if onOff:
|
||||
self.autoSelectMirrorObjects()
|
||||
G.mirrorScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.autoSelectMirrorObjects )))
|
||||
|
||||
|
||||
|
||||
|
||||
def autoSelectMirrorObjects(self):
|
||||
sel = cmds.ls(selection=True)
|
||||
if sel: self.selectMirrorObjs(add=True, lastObj=sel[-1])
|
||||
|
||||
def getInvertRules(self):
|
||||
|
||||
invertRules = []
|
||||
|
||||
for loopPref in self.INVERT_RULES_PREFS:
|
||||
name = loopPref["name"]
|
||||
pref = aToolsMod.getPref(name, self.INVERT_RULES_PREFS)
|
||||
mode = name[11:]
|
||||
|
||||
if pref: invertRules.append(mode)
|
||||
|
||||
|
||||
return invertRules
|
||||
|
||||
def mirrorInvert(self, aCurve, isCenterCurve, invertRules):
|
||||
|
||||
transRot =["Translate", "Rotate"]
|
||||
modes = ["x", "y", "z"]
|
||||
value = 1
|
||||
|
||||
if isCenterCurve:
|
||||
objType = "Center"
|
||||
else:
|
||||
objType = "Mirror"
|
||||
|
||||
for loopRule in invertRules:
|
||||
for loopMode in modes:
|
||||
for loopTransRot in transRot:
|
||||
rule = "%sObjs%s%s"%(objType, loopTransRot, loopMode.title())
|
||||
|
||||
if loopRule == rule:
|
||||
if eval("animMod.isNode%s('%s', '%s')"%(loopTransRot, aCurve, loopMode)):
|
||||
value = -1
|
||||
|
||||
|
||||
return value
|
||||
|
||||
def unselectMirrorObjs(self, side):
|
||||
objects = animMod.getObjsSel()
|
||||
|
||||
if side == "center":
|
||||
objs = animMod.getMirrorObjs(objects, side="left")
|
||||
objects.extend(objs)
|
||||
objs.extend(animMod.getMirrorObjs(objects, side="right"))
|
||||
objects.extend(objs)
|
||||
objs.extend(animMod.getMirrorObjs(objects, side="left"))
|
||||
|
||||
centerObjs = [loopObj for loopObj in objects if loopObj not in objs and loopObj and cmds.objExists(loopObj)]
|
||||
|
||||
if len(centerObjs) >0: cmds.select(centerObjs, deselect=True)
|
||||
else:
|
||||
if side == "left": side = "right"
|
||||
elif side == "right": side = "left"
|
||||
objs = animMod.getMirrorObjs(objects, side=side)
|
||||
objs = [loopObj for loopObj in objs if loopObj and cmds.objExists(loopObj)]
|
||||
|
||||
if len(objs) > 0: cmds.select(objs, deselect=True)
|
||||
|
||||
def selectMirrorObjs(self, add, lastObj=None):
|
||||
objects = animMod.getObjsSel()
|
||||
mirrorObjs = animMod.getMirrorObjs(objects)
|
||||
sel = []
|
||||
|
||||
if mirrorObjs:
|
||||
for n, loopObj in enumerate(mirrorObjs):
|
||||
if loopObj:
|
||||
if cmds.objExists(loopObj): sel.append(loopObj)
|
||||
else:
|
||||
#central controller
|
||||
sel.append(objects[n])
|
||||
|
||||
if len(sel) >0:
|
||||
|
||||
if lastObj:
|
||||
cmds.select(sel, addFirst=add)
|
||||
else:
|
||||
cmds.select(sel, add=add)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def applyMirror(self, pasteAndCycle=False):
|
||||
|
||||
cmds.waitCursor(state=True)
|
||||
|
||||
range = animMod.getTimelineRange()
|
||||
range[1] = int(range[1])
|
||||
total = range[1]-range[0]
|
||||
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
invertRules = self.getInvertRules()
|
||||
|
||||
if animCurves:
|
||||
status = "aTools - Applying mirror..."
|
||||
utilMod.startProgressBar(status)
|
||||
totalSteps = len(animCurves)
|
||||
firstStep = 0
|
||||
thisStep = 0
|
||||
estimatedTime = None
|
||||
startChrono = None
|
||||
|
||||
mirrorCurves = animMod.getMirrorObjs(animCurves)
|
||||
keyValues = animMod.getTarget("keyValues", animCurves, getFrom)
|
||||
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
|
||||
currValues = animMod.getTarget("currValues", animCurves, getFrom)
|
||||
keysIndexSel = animMod.getTarget("keysIndexSel", animCurves, getFrom)
|
||||
keyTangentsAngle = animMod.getTarget("keyTangentsAngle", animCurves, getFrom)
|
||||
keyTangentsType = animMod.getTarget("keyTangentsType", animCurves, getFrom)
|
||||
currTime = cmds.currentTime(query=True)
|
||||
|
||||
|
||||
|
||||
if keysIndexSel:
|
||||
|
||||
#create dummy key
|
||||
#objects = animMod.getObjsSel()
|
||||
#mirrorObjs = animMod.getMirrorObjs(objects)
|
||||
#animMod.createDummyKey(mirrorObjs)
|
||||
|
||||
for thisStep, aCurve in enumerate(animCurves):
|
||||
|
||||
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
|
||||
|
||||
mCurve = mirrorCurves[thisStep]
|
||||
isCenterCurve = (mCurve == None)
|
||||
mirrorInvertValue = self.mirrorInvert(aCurve, isCenterCurve, invertRules)
|
||||
if mCurve and cmds.objExists(mCurve):
|
||||
tCurve = mCurve
|
||||
else:
|
||||
tCurve = aCurve
|
||||
|
||||
if not cmds.objExists(tCurve): continue
|
||||
|
||||
|
||||
animMod.createDummyKey([tCurve])
|
||||
|
||||
if len(keysIndexSel[thisStep]) > 0:
|
||||
#delete keys
|
||||
cmds.cutKey(tCurve, time=(keyTimes[thisStep][keysIndexSel[thisStep][0]],keyTimes[thisStep][keysIndexSel[thisStep][-1]]), clear=True)
|
||||
|
||||
for key in keysIndexSel[thisStep]:
|
||||
keyValue = keyValues[thisStep][key] * mirrorInvertValue
|
||||
inTangAngleValue = keyTangentsAngle[thisStep][key][0] * mirrorInvertValue
|
||||
outTangAngleValue = keyTangentsAngle[thisStep][key][1] * mirrorInvertValue
|
||||
|
||||
|
||||
#apply keys
|
||||
if pasteAndCycle:
|
||||
t = keyTimes[thisStep][key] + (total/2.)
|
||||
|
||||
if t == range[1]:
|
||||
#repeat key at first frame
|
||||
t1 = t-total
|
||||
time = (t1,t1)
|
||||
cmds.setKeyframe(tCurve, time=time, value=keyValue)
|
||||
cmds.keyTangent(tCurve, time=time, inAngle=inTangAngleValue, outAngle=outTangAngleValue)
|
||||
cmds.keyTangent(tCurve, time=time, inTangentType=keyTangentsType[thisStep][key][0], outTangentType=keyTangentsType[thisStep][key][1])
|
||||
|
||||
elif t > range[1]:
|
||||
#fist half
|
||||
t -= total
|
||||
|
||||
time = (t,t)
|
||||
|
||||
|
||||
|
||||
else:
|
||||
time = (keyTimes[thisStep][key],keyTimes[thisStep][key])
|
||||
|
||||
|
||||
|
||||
cmds.setKeyframe(tCurve, time=time, value=keyValue)
|
||||
cmds.keyTangent(tCurve, time=time, inAngle=inTangAngleValue, outAngle=outTangAngleValue)
|
||||
cmds.keyTangent(tCurve, time=time, inTangentType=keyTangentsType[thisStep][key][0], outTangentType=keyTangentsType[thisStep][key][1])
|
||||
else: #no keys#invert translate x
|
||||
keyValue = currValues[thisStep] * mirrorInvertValue
|
||||
|
||||
|
||||
#apply keys
|
||||
cmds.setKeyframe(tCurve, time=(currTime,currTime), value=keyValue)
|
||||
|
||||
animMod.deleteDummyKey([tCurve])
|
||||
|
||||
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
|
||||
|
||||
|
||||
#delete dummy key
|
||||
#animMod.deleteDummyKey(mirrorObjs)
|
||||
|
||||
self.selectMirrorObjs(False)
|
||||
utilMod.setProgressBar(endProgress=True)
|
||||
|
||||
animMod.refresh()
|
||||
cmds.waitCursor(state=False)
|
||||
|
||||
|
@@ -0,0 +1,303 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
Modified: Michael Klimenko
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
class SpaceSwitch(object):
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu(postMenuCommand=self.populateMenu, button=1)
|
||||
|
||||
def populateMenu(self, menu, *args):
|
||||
|
||||
uiMod.clearMenuItems(menu)
|
||||
|
||||
tokenCustomDivider = False
|
||||
selObjects = cmds.ls(selection=True)
|
||||
|
||||
if not selObjects: return
|
||||
|
||||
channels = animMod.getAllChannels()
|
||||
channelList = {}
|
||||
tokenList = []
|
||||
|
||||
for n, loopObjectChannel in enumerate(channels):
|
||||
obj = selObjects[n]
|
||||
if loopObjectChannel:
|
||||
for loopChannel in loopObjectChannel:
|
||||
tokens = animMod.getTokens(obj, loopChannel)
|
||||
if tokens and len(tokens) > 1:
|
||||
if loopChannel not in channelList: channelList[loopChannel] = {"objects":[], "tokens":[]}
|
||||
channelList[loopChannel]["objects"].append(obj)
|
||||
channelList[loopChannel]["tokens"].append(tokens)
|
||||
|
||||
|
||||
for loopChannelList in channelList:
|
||||
newMenu = cmds.menuItem(subMenu=True, label=utilMod.toTitle(loopChannelList), parent=menu)
|
||||
objects = channelList[loopChannelList]["objects"]
|
||||
tokens = channelList[loopChannelList]["tokens"]
|
||||
mergedTokens = utilMod.mergeLists(tokens)
|
||||
tokenDict = []
|
||||
|
||||
for loopMergedTokens in mergedTokens:
|
||||
tokenDict.append({"token":loopMergedTokens, "objects":[]})
|
||||
for n, loopObject in enumerate(objects):
|
||||
t = tokens[n]
|
||||
if loopMergedTokens in t:
|
||||
tokenDict[-1]["objects"].append(loopObject)
|
||||
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
|
||||
for n, loopTokenDict in enumerate(tokenDict):
|
||||
tokenCustomDivider = True
|
||||
token = loopTokenDict["token"]
|
||||
objects = loopTokenDict["objects"]
|
||||
selectedList = [cmds.getAttr("%s.%s"%(loopObj, loopChannelList)) for loopObj in objects]
|
||||
radioSelected = False
|
||||
|
||||
|
||||
if len(set(selectedList)) == 1:
|
||||
if selectedList[0] == n:
|
||||
radioSelected = True
|
||||
|
||||
cmds.menuItem(label=utilMod.toTitle(token), radioButton=radioSelected, parent=newMenu, command=lambda x, objects=objects, channel=loopChannelList, token=token, *args:self.spaceSwitch([objects, channel, token]))
|
||||
|
||||
|
||||
#ALL KEYS
|
||||
cmds.menuItem( divider=True, parent=newMenu)
|
||||
newMenu = cmds.menuItem(subMenu=True, label='All Keys', parent=newMenu)
|
||||
|
||||
cmds.radioMenuItemCollection(parent=newMenu)
|
||||
|
||||
for n, loopTokenDict in enumerate(tokenDict):
|
||||
token = loopTokenDict["token"]
|
||||
objects = loopTokenDict["objects"]
|
||||
selectedList = [cmds.getAttr("%s.%s"%(loopObj, loopChannelList)) for loopObj in objects]
|
||||
radioSelected = False
|
||||
|
||||
if len(set(selectedList)) == 1:
|
||||
if selectedList[0] == n:
|
||||
radioSelected = True
|
||||
|
||||
cmds.menuItem(label=utilMod.toTitle(token), radioButton=radioSelected, parent=newMenu, command=lambda x, objects=objects, channel=loopChannelList, token=token, *args:self.spaceSwitch([objects, channel, token], all=True))
|
||||
|
||||
# CUSTOM SWITCH
|
||||
allCustomSwitch = aToolsMod.loadInfoWithUser("spaceSwitch", "customSwitch") or []
|
||||
channelboxSelObjs = animMod.channelBoxSel()
|
||||
|
||||
if channelboxSelObjs:
|
||||
obj = ".".join(channelboxSelObjs[0].split(".")[:-1])
|
||||
selectedSwitch = [loopAttr.split(".")[-1] for loopAttr in channelboxSelObjs if utilMod.isDynamic(obj, loopAttr.split(".")[-1])]
|
||||
if len(selectedSwitch) > 0 and selectedSwitch not in allCustomSwitch:
|
||||
allCustomSwitch.append(selectedSwitch)
|
||||
aToolsMod.saveInfoWithUser("spaceSwitch", "customSwitch", allCustomSwitch)
|
||||
|
||||
|
||||
# populate menu
|
||||
if len(allCustomSwitch) > 0:
|
||||
|
||||
divider = False
|
||||
customSwitchesAdded = []
|
||||
customSwitchesMenu = []
|
||||
|
||||
for loopObj in selObjects:
|
||||
|
||||
for loopCustomSwitch in sorted(allCustomSwitch, key=len, reverse=True):
|
||||
|
||||
if len(loopCustomSwitch) == 0: continue
|
||||
|
||||
switchName = utilMod.getNameSpace([loopObj])[1][0].split(".")[0]
|
||||
exit = False
|
||||
|
||||
for loopAttr in loopCustomSwitch:
|
||||
objAttr = "%s.%s"%(loopObj, loopAttr)
|
||||
if not cmds.objExists(objAttr):
|
||||
exit = True
|
||||
break
|
||||
|
||||
if exit: continue
|
||||
|
||||
customSwitchesMenu.append({"objects":[loopObj], "switches":loopCustomSwitch})
|
||||
|
||||
for loopMenu in customSwitchesMenu[:-1]:
|
||||
if loopObj in loopMenu["objects"] and len(loopCustomSwitch) < len(loopMenu["switches"]) and utilMod.listIntersection(loopMenu["switches"], loopCustomSwitch) == loopCustomSwitch:
|
||||
customSwitchesMenu.pop()
|
||||
break
|
||||
if loopCustomSwitch == loopMenu["switches"]:
|
||||
loopMenu["objects"].append(loopObj)
|
||||
customSwitchesMenu.pop()
|
||||
break
|
||||
|
||||
|
||||
for loopSwitchMenu in customSwitchesMenu:
|
||||
|
||||
objects = loopSwitchMenu["objects"]
|
||||
switches = loopSwitchMenu["switches"]
|
||||
switchName = ", ".join(list(set(utilMod.getNameSpace(objects)[1])))
|
||||
|
||||
if not divider and tokenCustomDivider: divider = cmds.menuItem(divider=True, parent=menu)
|
||||
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
|
||||
newMenu = cmds.menuItem(subMenu=True, label=switchName, parent=menu)
|
||||
radioSelected = []
|
||||
|
||||
for loopCustomSwitchAttr in switches:
|
||||
switchAttr = loopCustomSwitchAttr.split(".")[-1]
|
||||
objAttr = "%s.%s"%(objects[0], switchAttr)
|
||||
minValue = cmds.addAttr(objAttr, query=True, minValue=True)
|
||||
maxValue = cmds.addAttr(objAttr, query=True, maxValue=True)
|
||||
currValue = cmds.getAttr(objAttr)
|
||||
radioSelected.append((currValue == maxValue))
|
||||
|
||||
cmds.menuItem(label=switchAttr, radioButton=radioSelected[-1], parent=newMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], mode="custom"))
|
||||
|
||||
switchAttr = "message"
|
||||
radioSelected = (list(set(radioSelected)) == [False])
|
||||
cmds.menuItem(label="None", radioButton=radioSelected, parent=newMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], mode="custom"))
|
||||
|
||||
#ALL KEYS
|
||||
|
||||
cmds.menuItem( divider=True, parent=newMenu)
|
||||
allMenu = cmds.menuItem(subMenu=True, label='All Keys', parent=newMenu)
|
||||
radioSelected = []
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
|
||||
|
||||
for loopCustomSwitchAttr in switches:
|
||||
switchAttr = loopCustomSwitchAttr.split(".")[-1]
|
||||
objAttr = "%s.%s"%(objects[0], switchAttr)
|
||||
minValue = cmds.addAttr(objAttr, query=True, minValue=True)
|
||||
maxValue = cmds.addAttr(objAttr, query=True, maxValue=True)
|
||||
currValue = cmds.getAttr(objAttr)
|
||||
radioSelected.append((currValue == maxValue))
|
||||
cmds.menuItem(label=switchAttr, radioButton=radioSelected[-1], parent=allMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], all=True, mode="custom"))
|
||||
|
||||
switchAttr = "message"
|
||||
radioSelected = (list(set(radioSelected)) == [False])
|
||||
cmds.menuItem(label="None", radioButton=radioSelected, parent=allMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], all=True, mode="custom"))
|
||||
|
||||
#DELETE
|
||||
|
||||
cmds.menuItem(label="Remove", parent=newMenu, command=lambda x, switches=switches, *args:self.removeCustomSwitch(switches))
|
||||
|
||||
def removeCustomSwitch(self, switch):
|
||||
allCustomSwitch = aToolsMod.loadInfoWithUser("spaceSwitch", "customSwitch") or []
|
||||
|
||||
allCustomSwitch.remove(switch)
|
||||
aToolsMod.saveInfoWithUser("spaceSwitch", "customSwitch", allCustomSwitch)
|
||||
|
||||
def spaceSwitch(self, args, all=False, mode="token"):
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
if mode == "token": switch = self.spaceSwitchToken
|
||||
elif mode == "custom": switch = self.spaceSwitchCustom
|
||||
|
||||
objects = args[0]
|
||||
attr = args[1]
|
||||
currSel = cmds.ls(selection=True)
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
if animCurves:
|
||||
if all: keysSel = animMod.getTarget("keyTimes", animCurves, getFrom)
|
||||
else: keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
|
||||
keysSel = utilMod.mergeLists(keysSel)
|
||||
if keysSel == []:
|
||||
keysSel = [currFrame]
|
||||
else:
|
||||
keysSel = [currFrame]
|
||||
|
||||
frames = keysSel
|
||||
|
||||
for loopObj in currSel:
|
||||
if loopObj not in objects: continue
|
||||
if not cmds.objExists("%s.%s"%(loopObj, attr)):continue
|
||||
|
||||
animMod.createDummyKey([loopObj])
|
||||
|
||||
getCurves = animMod.getAnimCurves(True)
|
||||
animCurves = getCurves[0]
|
||||
|
||||
animMod.deleteDummyKey([loopObj])
|
||||
|
||||
for loopFrame in frames:
|
||||
cmds.currentTime(loopFrame)
|
||||
|
||||
matrix = cmds.xform(loopObj, query=True, ws=True, matrix=True)
|
||||
rotation = cmds.xform(loopObj, query=True, ws=True, rotation=True)
|
||||
|
||||
switch(loopObj, args)
|
||||
cmds.xform(loopObj, ws=True, matrix=matrix)
|
||||
cmds.xform(loopObj, ws=True, rotation=rotation)
|
||||
|
||||
|
||||
animMod.eulerFilterCurve(animCurves)
|
||||
|
||||
|
||||
cmds.currentTime(currFrame)
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
def spaceSwitchCustom(self, obj, args):
|
||||
|
||||
objects, attr, switchAttList = args
|
||||
objAttr = "%s.%s"%(obj, attr)
|
||||
|
||||
for loopAttr in switchAttList:
|
||||
|
||||
loopObjAttr = "%s.%s"%(obj, loopAttr)
|
||||
minValue = cmds.addAttr(loopObjAttr, query=True, minValue=True)
|
||||
maxValue = cmds.addAttr(loopObjAttr, query=True, maxValue=True)
|
||||
value = minValue if objAttr != loopObjAttr else maxValue
|
||||
|
||||
cmds.setAttr(loopObjAttr, value)
|
||||
|
||||
def spaceSwitchToken(self, obj, args):
|
||||
|
||||
objects, attr, switchTo = args
|
||||
enumTokens = animMod.getTokens(obj, attr)
|
||||
value = 0
|
||||
switchToNum = None
|
||||
|
||||
for loopToken in enumTokens:
|
||||
splitValue = loopToken.split("=")
|
||||
|
||||
if splitValue:
|
||||
if len(splitValue) > 1:
|
||||
loopToken = splitValue[0]
|
||||
value = eval(splitValue[1])
|
||||
|
||||
|
||||
if switchTo == loopToken:
|
||||
switchToNum = value
|
||||
break
|
||||
|
||||
value += 1
|
||||
|
||||
|
||||
if switchToNum != None:
|
||||
cmds.setAttr("%s.%s"%(obj, attr), switchToNum)
|
||||
|
@@ -0,0 +1,189 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
import maya.OpenMaya as om
|
||||
|
||||
#============================================================================================================
|
||||
class TempCustomPivot(object):
|
||||
|
||||
def __init__(self):
|
||||
self.STORE_NODE = "tempCustomPivot"
|
||||
self.CONSTRAINTS = "constraintObjects"
|
||||
self.LOCATORS = "locatorObjects"
|
||||
self.CTRLS = "ctrlsObjects"
|
||||
self.CURRENTFRAME = "currentFrame"
|
||||
self.sel = []
|
||||
self.deniedCtx = ["dragAttrContext", "manipMoveContext", "manipRotateContext", "manipScaleContext"]
|
||||
|
||||
self.clear()
|
||||
|
||||
def popupMenu(self, *args):
|
||||
cmds.popupMenu()
|
||||
cmds.menuItem(label="Clear temporary custom pivots", command=self.clear)
|
||||
|
||||
|
||||
def create(self, *args):
|
||||
|
||||
|
||||
img = cmds.iconTextButton("TempCustomPivotBtn", query=True, image=True)
|
||||
onOff = (img[-10:-4] == "active")
|
||||
if onOff:
|
||||
self.clear()
|
||||
cmds.select(self.sel)
|
||||
return
|
||||
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
|
||||
self.clear()
|
||||
|
||||
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
if animCurves:
|
||||
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
|
||||
|
||||
self.sel = cmds.ls(selection=True)
|
||||
if not self.sel: return
|
||||
|
||||
cmds.iconTextButton("TempCustomPivotBtn", edit=True, image= uiMod.getImagePath("specialTools_create_temp_custom_pivot_active"), highlightImage= uiMod.getImagePath("specialTools_create_temp_custom_pivot_active"))
|
||||
|
||||
targetObj = self.sel[-1]
|
||||
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.CTRLS, self.sel)
|
||||
|
||||
currentFrame = cmds.currentTime(query=True)
|
||||
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.CURRENTFRAME, currentFrame)
|
||||
|
||||
locators = []
|
||||
for loopSel in self.sel:
|
||||
nameSpace = utilMod.getNameSpace([loopSel])
|
||||
loopSelName = "%s_%s"%(nameSpace[0][0], nameSpace[1][0])
|
||||
locatorName = "tempCustomPivot_%s"%loopSelName
|
||||
|
||||
locator = animMod.createNull(locatorName)
|
||||
locators.append(locator)
|
||||
|
||||
G.aToolsBar.align.align([locator], loopSel)
|
||||
|
||||
|
||||
locatorGroup = "tempCustomPivot_group"
|
||||
animMod.group(name=locatorGroup)
|
||||
G.aToolsBar.align.align([locatorGroup], targetObj)
|
||||
with G.aToolsBar.createAToolsNode: cmds.parent(locators, locatorGroup)
|
||||
cmds.select(locatorGroup, replace=True)
|
||||
|
||||
locators.append(locatorGroup)
|
||||
|
||||
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.LOCATORS, locators)
|
||||
|
||||
#parent ctrls to locator
|
||||
constraints = ["%s_tempCustomPivot_constraint"%loopConstraint for loopConstraint in self.sel]
|
||||
|
||||
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.CONSTRAINTS, constraints)
|
||||
|
||||
for n, loopSel in enumerate(self.sel):
|
||||
with G.aToolsBar.createAToolsNode: cmds.parentConstraint(locators[n], loopSel, name=constraints[n], maintainOffset=True)
|
||||
constraintNode = "%s.blendParent1"%loopSel
|
||||
if not cmds.objExists(constraintNode): continue
|
||||
cmds.setKeyframe(constraintNode)
|
||||
if keyTimes:
|
||||
for loopTime in keyTimes[0]:
|
||||
cmds.setKeyframe("%s.tx"%locatorGroup, time=(loopTime,loopTime))
|
||||
if loopTime != currentFrame:
|
||||
cmds.setKeyframe(constraintNode, time=(loopTime,loopTime), value=0)
|
||||
|
||||
#enter edit mode
|
||||
cmds.setToolTo(cmds.currentCtx())
|
||||
cmds.ctxEditMode()
|
||||
|
||||
#scriptjob
|
||||
cmds.scriptJob(runOnce = True, killWithScene = True, event =('SelectionChanged', self.scriptJob_SelectionChanged))
|
||||
|
||||
def scriptJob_SelectionChanged(self):
|
||||
self.clear()
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
|
||||
def clear(self, *args):
|
||||
|
||||
|
||||
if cmds.iconTextButton("TempCustomPivotBtn", query=True, exists=True):
|
||||
cmds.iconTextButton("TempCustomPivotBtn", edit=True, image= uiMod.getImagePath("specialTools_create_temp_custom_pivot"), highlightImage= uiMod.getImagePath("specialTools_create_temp_custom_pivot copy"))
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
|
||||
loadConstraints = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.CONSTRAINTS)
|
||||
loadLocators = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.LOCATORS)
|
||||
loadCtrls = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.CTRLS)
|
||||
currentFrame = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.CURRENTFRAME)
|
||||
|
||||
#exit edit mode
|
||||
|
||||
if cmds.currentCtx() not in self.deniedCtx: cmds.setToolTo(cmds.currentCtx())
|
||||
|
||||
|
||||
if currentFrame:
|
||||
cmds.currentTime(eval(currentFrame))
|
||||
|
||||
#get values
|
||||
"""
|
||||
translation = []
|
||||
rotation = []
|
||||
if loadCtrls:
|
||||
ctrlObjs = eval(loadCtrls)
|
||||
for loopCtrl in ctrlObjs:
|
||||
translation.append(cmds.xform(loopCtrl, query=True, ws=True, rotatePivot=True))
|
||||
rotation.append(cmds.xform(loopCtrl, query=True, ws=True, rotation=True))
|
||||
"""
|
||||
|
||||
|
||||
if loadConstraints:
|
||||
constraintObjs = eval(loadConstraints)
|
||||
for loopConstraint in constraintObjs:
|
||||
if cmds.objExists(loopConstraint): cmds.delete(loopConstraint)
|
||||
|
||||
if loadCtrls and loadLocators:
|
||||
locatorObjs = eval(loadLocators)
|
||||
ctrlObjs = eval(loadCtrls)
|
||||
for n, loopCtrl in enumerate(ctrlObjs):
|
||||
if cmds.objExists(loopCtrl) and cmds.objExists(locatorObjs[n]):
|
||||
G.aToolsBar.align.align([loopCtrl], locatorObjs[n])
|
||||
|
||||
for loopLocator in locatorObjs:
|
||||
if cmds.objExists(loopLocator): cmds.delete(loopLocator)
|
||||
|
||||
cmds.currentTime(currFrame)
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,347 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
Modified: Michael Klimenko
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from maya import OpenMaya
|
||||
from maya import OpenMayaAnim
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
|
||||
|
||||
class TransformAll(object):
|
||||
|
||||
utilMod.killScriptJobs("G.transformAllScriptJobs")
|
||||
|
||||
def __init__(self):
|
||||
|
||||
G.deferredManager.removeFromQueue("transformAll")
|
||||
G.deferredManager.removeFromQueue("TA_blinking")
|
||||
|
||||
if G.aToolsBar.transformAll: return
|
||||
G.aToolsBar.transformAll = self
|
||||
|
||||
self.currentValues = {}
|
||||
self.allValues = {}
|
||||
self.range = None
|
||||
self.onOff = False
|
||||
self.blendRangeMode = False
|
||||
self.blendImg = ""
|
||||
G.TA_messages = G.TA_messages or {"anim":[], "node":[], "scene":[]}
|
||||
|
||||
self.killJobs()
|
||||
|
||||
def blinkingButton(self, onOff):
|
||||
|
||||
if onOff: G.aToolsBar.timeoutInterval.setInterval(self.toggleButtonActive, .3, id="TA_blinking")
|
||||
else: G.aToolsBar.timeoutInterval.stopInterval("TA_blinking")
|
||||
|
||||
|
||||
def toggleButtonActive(self):
|
||||
onOff = "active" in cmds.iconTextButton("transformAllBtn", query=True, image=True)
|
||||
|
||||
self.setButtonImg(not onOff)
|
||||
|
||||
def popupMenu(self, *args):
|
||||
|
||||
cmds.popupMenu ()
|
||||
cmds.menuItem ("blendRangeModeMenu", label="Blend Range Mode", checkBox=self.blendRangeMode, command=self.setBlendRangeMode)
|
||||
|
||||
def setBlendRangeMode(self, *args):
|
||||
self.blendRangeMode = args[0]
|
||||
if self.blendRangeMode: self.blendImg = "_blend"
|
||||
else: self.blendImg = ""
|
||||
|
||||
self.setButtonImg(self.onOff)
|
||||
self.warn()
|
||||
|
||||
def setButtonImg(self, onOff):
|
||||
if onOff:
|
||||
cmds.iconTextButton("transformAllBtn", edit=True, image=uiMod.getImagePath("specialTools_transform_all%s_active"%self.blendImg), highlightImage= uiMod.getImagePath("specialTools_transform_all%s_active"%self.blendImg))
|
||||
else:
|
||||
cmds.iconTextButton("transformAllBtn", edit=True, image=uiMod.getImagePath("specialTools_transform_all%s"%self.blendImg), highlightImage= uiMod.getImagePath("specialTools_transform_all%s copy"%self.blendImg))
|
||||
|
||||
|
||||
def switch(self):
|
||||
|
||||
mod = uiMod.getModKeyPressed()
|
||||
|
||||
if mod == "ctrl":
|
||||
self.setBlendRangeMode(not self.blendRangeMode)
|
||||
if self.onOff: self.onOff = False
|
||||
|
||||
|
||||
self.onOff = (not self.onOff)
|
||||
self.setButtonImg(self.onOff)
|
||||
self.blinkingButton(self.onOff)
|
||||
|
||||
self.setMode(self.onOff)
|
||||
|
||||
def killJobs(self):
|
||||
G.deferredManager.removeFromQueue("transformAll")
|
||||
self.animCurvesToSend = []
|
||||
self.removeMessages()
|
||||
utilMod.killScriptJobs("G.transformAllScriptJobs")
|
||||
|
||||
|
||||
def setMode(self, onOff):
|
||||
|
||||
self.killJobs()
|
||||
|
||||
if onOff:
|
||||
|
||||
#self.allAnimCurves = utilMod.getAllAnimCurves()
|
||||
self.allValues = {}
|
||||
self.setRange()
|
||||
self.updateCurrentValues()
|
||||
utilMod.deselectTimelineRange()
|
||||
|
||||
G.transformAllScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('timeChanged', self.updateCurrentValues )))
|
||||
G.transformAllScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.updateCurrentValues )))
|
||||
|
||||
self.warn()
|
||||
|
||||
|
||||
else:
|
||||
cmds.warning("Transform All is OFF.")
|
||||
|
||||
def addAnimMessages(self):
|
||||
|
||||
self.removeMessages()
|
||||
G.TA_messages["anim"].append(OpenMayaAnim.MAnimMessage.addAnimCurveEditedCallback(self.sendToSetValues))
|
||||
|
||||
|
||||
def removeMessages(self):
|
||||
|
||||
try:
|
||||
for loopId in G.TA_messages["anim"]:
|
||||
OpenMayaAnim.MAnimMessage.removeCallback(loopId)
|
||||
except: pass
|
||||
|
||||
G.TA_messages["anim"] = []
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def sendToSetValues(self, *args):
|
||||
|
||||
curveMsg = args[0]
|
||||
animCurves = [OpenMaya.MFnDependencyNode(curveMsg[n]).name() for n in range(curveMsg.length())]
|
||||
|
||||
if OpenMaya.MGlobal.isUndoing() or OpenMaya.MGlobal.isRedoing():
|
||||
self.updateCurrentValues(animCurves)
|
||||
return
|
||||
|
||||
self.animCurvesToSend.extend(animCurves)
|
||||
|
||||
|
||||
animCurves = list(set(self.animCurvesToSend))
|
||||
|
||||
G.deferredManager.removeFromQueue("transformAll")
|
||||
function = lambda *args:self.setValues(animCurves)
|
||||
G.deferredManager.sendToQueue(function, 1, "transformAll")
|
||||
|
||||
|
||||
def getRange(self):
|
||||
|
||||
animCurves = cmds.keyframe(query=True, name=True, selected=True)
|
||||
|
||||
if animCurves:
|
||||
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, "graphEditor")
|
||||
keysSel = utilMod.mergeLists(keysSel)
|
||||
range = [min(keysSel), max(keysSel)]
|
||||
|
||||
else:
|
||||
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
|
||||
range = cmds.timeControl(G.playBackSliderPython, query=True, rangeArray=True)
|
||||
|
||||
range[1] -= 1
|
||||
|
||||
return range
|
||||
|
||||
def getCurrentValues(self, animCurves):
|
||||
if animCurves:
|
||||
result = {"keyValues":[], "timeValues":[]}
|
||||
for loopCurve in animCurves:
|
||||
time = cmds.keyframe(loopCurve, selected=True, query=True, timeChange=True)
|
||||
|
||||
if time:
|
||||
time = [time[0], time[-1]]
|
||||
result["keyValues"].append(cmds.keyframe(loopCurve, query=True, time=(time[0],time[-1]), valueChange=True))
|
||||
else:
|
||||
time = cmds.currentTime(query=True); time = [time, time]
|
||||
result["keyValues"].append(cmds.keyframe(loopCurve, query=True, eval=True, valueChange=True))
|
||||
|
||||
result["timeValues"].append(time)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def updateCurrentValues(self, animCurves=None, *args):
|
||||
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
|
||||
self.removeMessages()
|
||||
|
||||
if not animCurves: animCurves = utilMod.getAllAnimCurves(selection=True)
|
||||
if not animCurves: return
|
||||
|
||||
for loopCurve in animCurves:
|
||||
#if loopCurve in self.allAnimCurves:
|
||||
self.currentValues[loopCurve] = self.getCurrentValues([loopCurve])["keyValues"][0]
|
||||
self.allValues[loopCurve] = animMod.getTarget("keyValues", [loopCurve])[0]
|
||||
|
||||
|
||||
self.addAnimMessages()
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
|
||||
def setValues(self, animCurves):
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
|
||||
self.removeMessages()
|
||||
self.warn()
|
||||
|
||||
values = self.getCurrentValues(animCurves)
|
||||
newKeyValues = values["keyValues"]
|
||||
timeValues = values["timeValues"]
|
||||
offsetValues = []
|
||||
offsetPercentsA = []
|
||||
offsetPercentsB = []
|
||||
pivotAs = []
|
||||
pivotBs = []
|
||||
self.animCurvesToSend = []
|
||||
|
||||
|
||||
for n, loopCurve in enumerate(animCurves):
|
||||
|
||||
oldVal = self.currentValues[loopCurve][0]
|
||||
newVal = newKeyValues[n][0]
|
||||
|
||||
if self.blendRangeMode:
|
||||
|
||||
pivotA = cmds.keyframe(loopCurve, query=True, eval=True, time=(self.range[0],self.range[0]), valueChange=True)[0]
|
||||
pivotB = cmds.keyframe(loopCurve, query=True, eval=True, time=(self.range[1],self.range[1]), valueChange=True)[0]
|
||||
|
||||
|
||||
if oldVal == pivotA:
|
||||
pivotA = newVal
|
||||
offsetPercentA = 0
|
||||
else:
|
||||
offsetPercentA = float((newVal-pivotA)/(oldVal-pivotA))
|
||||
if oldVal == pivotB:
|
||||
pivotB = newVal
|
||||
offsetPercentB = 0
|
||||
else:
|
||||
offsetPercentB = float((newVal-pivotB)/(oldVal-pivotB))
|
||||
|
||||
offsetPercentsA.append(offsetPercentA)
|
||||
offsetPercentsB.append(offsetPercentB)
|
||||
pivotAs.append(pivotA)
|
||||
pivotBs.append(pivotB)
|
||||
|
||||
else:
|
||||
offsetVal = newVal - oldVal
|
||||
|
||||
offsetValues.append(offsetVal)
|
||||
|
||||
|
||||
#reset change
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
for loopCurve in list(self.allValues.keys()):
|
||||
if loopCurve in animCurves:
|
||||
valueChange = self.allValues[loopCurve]
|
||||
for n, loopValue in enumerate(valueChange):
|
||||
cmds.keyframe(loopCurve, edit=True, index=(n,n), valueChange=loopValue)
|
||||
#self.allValues[] = {}
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
|
||||
#set values for all keys
|
||||
curvesToUpdate = []
|
||||
|
||||
if self.blendRangeMode:
|
||||
for n, loopCurve in enumerate(animCurves):
|
||||
time = timeValues[n]
|
||||
timeOffsetA = .01
|
||||
timeOffsetB = .01
|
||||
|
||||
if time[0] == self.range[0]: timeOffsetA = 0
|
||||
if time[1] == self.range[1]: timeOffsetB = 0
|
||||
|
||||
if timeOffsetA != 0 and timeOffsetB != 0 and not self.range[0] < time[0] <= time[1] < self.range[1]:
|
||||
cmds.warning("Selected keys out of range %s"%self.range)
|
||||
continue
|
||||
|
||||
offsetPercentA = offsetPercentsA[n]
|
||||
offsetPercentB = offsetPercentsB[n]
|
||||
#if offsetPercentA != 0 or offsetPercentB != 0:
|
||||
pivotA = pivotAs[n]
|
||||
pivotB = pivotBs[n]
|
||||
curvesToUpdate.append(loopCurve)
|
||||
cmds.scaleKey(loopCurve, time=(self.range[0]+timeOffsetA, time[1]), valuePivot=pivotA, valueScale=offsetPercentA)
|
||||
cmds.scaleKey(loopCurve, time=(time[1]+.01, self.range[1]-timeOffsetB), valuePivot=pivotB, valueScale=offsetPercentB)
|
||||
|
||||
else:
|
||||
for n, loopCurve in enumerate(animCurves):
|
||||
if offsetValues[n] != 0:
|
||||
curvesToUpdate.append(loopCurve)
|
||||
if self.range == "All Keys":
|
||||
#pass
|
||||
cmds.keyframe(loopCurve, edit=True, valueChange=offsetValues[n], relative=True)
|
||||
else:
|
||||
cmds.keyframe(loopCurve, edit=True, time=(self.range[0], self.range[1]), valueChange=offsetValues[n], relative=True)
|
||||
|
||||
|
||||
self.updateCurrentValues(curvesToUpdate)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
|
||||
def warn(self):
|
||||
if self.blendRangeMode:
|
||||
blendTxt = "Blend Range Mode "
|
||||
else:
|
||||
blendTxt = ""
|
||||
|
||||
cmds.warning("Transform All %sis ON. Please remember to turn it OFF when you are done. Acting on range: %s"%(blendTxt, self.range))
|
||||
|
||||
def setRange(self):
|
||||
self.range = self.getRange()
|
||||
|
||||
if self.range[1] - self.range[0] <= 1: #if only one key selected
|
||||
if self.blendRangeMode: self.range = [cmds.playbackOptions(query=True, minTime=True), cmds.playbackOptions(query=True, maxTime=True)]
|
||||
else: self.range = "All Keys"
|
||||
|
||||
|
||||
|
||||
|
305
Scripts/Animation/aTools/animTools/animBar/subUIs/tUtilities.py
Normal file
@@ -0,0 +1,305 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds, mel
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
STORE_NODE = "tUtilities"
|
||||
CAMERA_ATTR = "cameraSelected"
|
||||
RANGE_ATTR = "timelineRange"
|
||||
|
||||
G.TU_movie = None
|
||||
G.TU_audioFile = None
|
||||
G.TU_audioOffsetSec = None
|
||||
|
||||
class TUtilities_Gui(uiMod.BaseSubUI):
|
||||
|
||||
|
||||
def createLayout(self):
|
||||
|
||||
cmds.rowLayout(numberOfColumns=5, parent=self.parentLayout)
|
||||
|
||||
timelineRange = TimelineRange()
|
||||
cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("tUtilities_range"), highlightImage= uiMod.getImagePath("tUtilities_range copy"), command=timelineRange.setTimelineRange, annotation="Set timeline range\nRight click for options")
|
||||
timelineRange.popupMenu()
|
||||
|
||||
cameraTools = CameraTools()
|
||||
cmds.iconTextButton (style='iconAndTextVertical', w=self.wb, h=self.hb, image= uiMod.getImagePath("tUtilities_camera"), highlightImage= uiMod.getImagePath("tUtilities_camera copy"), command=cameraTools.playblastCamera, annotation="Playblast camera\nRight click to select camera")
|
||||
cameraTools.popupMenu()
|
||||
|
||||
|
||||
|
||||
|
||||
# end createLayout
|
||||
|
||||
class TimelineRange(object):
|
||||
|
||||
def __init__(self):
|
||||
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
|
||||
|
||||
def popupMenu(self, *args):
|
||||
cmds.popupMenu("timelineRangeMenu", postMenuCommand=self.populateMenu)
|
||||
|
||||
def populateMenu(self, menu, *args):
|
||||
uiMod.clearMenuItems(menu)
|
||||
uiMod.clearMenuItems(menu)
|
||||
#cmds.menuItem(label="Clear motion trails", command=self.clear)
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
|
||||
currRange = [cmds.playbackOptions(query=True, minTime=True), cmds.playbackOptions(query=True, maxTime=True)]
|
||||
currRangeStr = "%s - %s"%(int(currRange[0]), int(currRange[1]))
|
||||
|
||||
#populate list
|
||||
ranges = self.getTimelineRanges()
|
||||
if ranges: ranges = eval(ranges)
|
||||
if ranges:
|
||||
for loopRange in ranges:
|
||||
loopRangeStr = "%s - %s"%(int(loopRange[0]), int(loopRange[1]-1))
|
||||
radioButton = (currRangeStr == loopRangeStr)
|
||||
cmds.menuItem("menu_%s"%loopRange, radioButton=radioButton, label=loopRangeStr, parent=menu, command=lambda x, loopRange=loopRange, *args: self.setTimelineRange(loopRange))
|
||||
cmds.menuItem( divider=True, parent=menu)
|
||||
newMenu = cmds.menuItem(subMenu=True, label='Delete', parent=menu)
|
||||
cmds.menuItem( divider=True, parent=menu)
|
||||
for loopRange in ranges:
|
||||
loopRangeStr = "%s - %s"%(int(loopRange[0]), int(loopRange[1]-1))
|
||||
cmds.menuItem("menu_%s"%loopRange, label=loopRangeStr, parent=newMenu, command=lambda x, loopRange=loopRange, *args: self.deleteTimelineRange(loopRange))
|
||||
cmds.menuItem( divider=True, parent=newMenu)
|
||||
cmds.menuItem("menu_deleteAll", label="Delete All", parent=newMenu, command=self.deleteAllTimelineRange)
|
||||
cmds.menuItem("toggleLipSyncModeMenu", label='Lip Sync Mode', checkBox=self.isLipSyncMode(), command=self.toggleLipSyncMode, parent=menu)
|
||||
|
||||
|
||||
|
||||
def getTimelineRanges(self):
|
||||
return aToolsMod.loadInfoWithScene(STORE_NODE, RANGE_ATTR)
|
||||
|
||||
|
||||
def setTimelineRange(self, range=None, *args):
|
||||
|
||||
rangeVisible = cmds.timeControl( G.playBackSliderPython, query=True, rangeVisible=True )
|
||||
|
||||
if not rangeVisible and not range:
|
||||
range = [cmds.playbackOptions(query=True, minTime=True), cmds.playbackOptions(query=True, maxTime=True)+1]
|
||||
|
||||
if range or rangeVisible:
|
||||
|
||||
if not range: range = animMod.getTimelineRange(float=False)
|
||||
rFrom = range[0]
|
||||
rTo = range[1]-1
|
||||
|
||||
cmds.playbackOptions(minTime=rFrom, maxTime=rTo)
|
||||
|
||||
|
||||
if self.getTimelineRanges() != None:
|
||||
ranges = eval(self.getTimelineRanges())
|
||||
else:
|
||||
ranges = []
|
||||
if not range in ranges:
|
||||
ranges.append(range)
|
||||
aToolsMod.saveInfoWithScene(STORE_NODE, RANGE_ATTR, ranges)
|
||||
|
||||
|
||||
utilMod.deselectTimelineRange()
|
||||
|
||||
|
||||
def deleteTimelineRange(self, range=None, *args):
|
||||
|
||||
ranges = eval(self.getTimelineRanges())
|
||||
if not ranges: ranges = []
|
||||
if range in ranges: ranges.remove(range)
|
||||
aToolsMod.saveInfoWithScene(STORE_NODE, RANGE_ATTR, ranges)
|
||||
|
||||
def deleteAllTimelineRange(self, *args):
|
||||
aToolsMod.saveInfoWithScene(STORE_NODE, RANGE_ATTR, [])
|
||||
|
||||
|
||||
def toggleLipSyncMode(self, *args):
|
||||
|
||||
if self.isLipSyncMode():
|
||||
cmds.timeControl(G.playBackSliderPython, edit=True, height=28)
|
||||
else:
|
||||
cmds.timeControl(G.playBackSliderPython, edit=True, height=200)
|
||||
|
||||
def isLipSyncMode(self, *args):
|
||||
timelineHeight = cmds.timeControl(G.playBackSliderPython, query=True, height=True)
|
||||
|
||||
return timelineHeight > 28
|
||||
|
||||
|
||||
class CameraTools(object):
|
||||
|
||||
|
||||
def __init__(self):
|
||||
animMod.getShotCamera()
|
||||
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu(postMenuCommand=self.populateMenu)
|
||||
|
||||
def populateMenu(self, menu, *args):
|
||||
|
||||
uiMod.clearMenuItems(menu)
|
||||
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
|
||||
#populate list
|
||||
for loopCamera in utilMod.getAllCameras():
|
||||
radioSelected = (animMod.getShotCamera() == loopCamera)
|
||||
cameraName = cmds.listRelatives(loopCamera, allParents=True)[0]
|
||||
cmds.menuItem("menu_%s"%loopCamera, label=str(cameraName), radioButton=radioSelected, parent=menu, command=lambda x, loopCamera=loopCamera, *args: aToolsMod.saveInfoWithScene(STORE_NODE, CAMERA_ATTR, loopCamera))
|
||||
|
||||
# last playblast menu
|
||||
cmds.menuItem(divider=True, parent=menu)
|
||||
checkBoxSelected = aToolsMod.getUserPref("saveAfterPlayblasting", default=True)
|
||||
cmds.menuItem("saveAfterPlayblastingMenu", label='Save Maya File After Playblasting', checkBox=checkBoxSelected, command=self.setSaveAfterPlayblastingPref, parent=menu)
|
||||
cmds.menuItem(divider=True, parent=menu)
|
||||
cmds.menuItem (label="Duplicate Selected Camera", command=self.duplicateCamera, parent=menu)
|
||||
cmds.menuItem (label="Playblast Viewport", command=self.playblastViewport, parent=menu)
|
||||
cmds.menuItem (label="Play Last Playblast", command=self.playLastPlayblast, parent=menu)
|
||||
|
||||
def setSaveAfterPlayblastingPref(self, onOff):
|
||||
self.setPref("saveAfterPlayblasting", onOff)
|
||||
|
||||
def setPref(self, pref, onOff):
|
||||
aToolsMod.setUserPref(pref, onOff)
|
||||
|
||||
|
||||
def playblastViewport(self, *args):
|
||||
currCamera = utilMod.getCurrentCamera()
|
||||
if currCamera:
|
||||
self.doPlayblast(currCamera)
|
||||
else:
|
||||
cmds.warning( "Please set focus on a viewport" )
|
||||
|
||||
def playblastCamera(self, *args):
|
||||
camera = animMod.getShotCamera()
|
||||
if camera: self.doPlayblast(camera)
|
||||
|
||||
def doPlayblast(self, camera):
|
||||
|
||||
G.TU_movie = None
|
||||
G.TU_audioFile = None
|
||||
G.TU_audioOffsetSec = None
|
||||
winName = 'playblastWindow'
|
||||
overscan = cmds.getAttr("%s.overscan"%camera)
|
||||
audioTrack = cmds.timeControl(G.playBackSliderPython, query=True, sound=True)
|
||||
rangeVisible = cmds.timeControl(G.playBackSliderPython, query=True, rangeVisible=True )
|
||||
widthHeight = utilMod.getRenderResolution()
|
||||
|
||||
if cmds.window(winName, query=True, exists=True): cmds.deleteUI(winName)
|
||||
|
||||
window = cmds.window(winName, widthHeight=widthHeight)
|
||||
form = cmds.formLayout()
|
||||
editor = cmds.modelEditor()
|
||||
column = cmds.columnLayout('true')
|
||||
|
||||
cmds.formLayout( form, edit=True, attachForm=[(column, 'top', 0), (column, 'left', 0), (editor, 'top', 0), (editor, 'bottom', 0), (editor, 'right', 0)], attachNone=[(column, 'bottom'), (column, 'right')], attachControl=(editor, 'left', 0, column))
|
||||
cmds.modelEditor(editor, edit=True, camera=camera, activeView=True)
|
||||
cmds.showWindow( window )
|
||||
cmds.window( winName, edit=True, topLeftCorner=(0, 0), widthHeight=[200,200])
|
||||
utilMod.cameraViewMode(editor)
|
||||
cmds.setAttr("%s.overscan"%camera, 1)
|
||||
|
||||
|
||||
if rangeVisible:
|
||||
range = animMod.getTimelineRange(float=False)
|
||||
rFrom = range[0]
|
||||
rTo = range[1]-1
|
||||
else:
|
||||
rFrom = cmds.playbackOptions(query=True, minTime=True)
|
||||
rTo = cmds.playbackOptions(query=True, maxTime=True)
|
||||
|
||||
|
||||
if G.currentStudio == None:
|
||||
G.TU_movie = cmds.playblast(format="qt", sound=audioTrack, startTime=rFrom ,endTime=rTo , viewer=1, showOrnaments=0, offScreen=True, fp=4, percent=50, compression="png", quality=70, widthHeight=widthHeight, clearCache=True)
|
||||
|
||||
else:
|
||||
|
||||
fps = mel.eval("currentTimeUnitToFPS")
|
||||
if audioTrack:
|
||||
G.TU_audioFile = cmds.sound(audioTrack, query=True, file=True)
|
||||
audioOffset = cmds.sound(audioTrack, query=True, offset=True)
|
||||
G.TU_audioOffsetSec = str((rFrom - audioOffset)/-fps)
|
||||
|
||||
movieName = cmds.playblast(format="image", startTime=rFrom ,endTime=rTo , viewer=0, showOrnaments=0, offScreen=True, fp=4, percent=50, compression="jpg", quality=70, widthHeight=widthHeight, clearCache=True)
|
||||
if movieName:
|
||||
G.TU_movie = "%s.%s-%s#.jpg"%(movieName.split(".")[0], int(rFrom), int(rTo))
|
||||
if audioTrack: G.TU_audioOffsetSec = audioOffset
|
||||
self.playMovie(G.TU_movie, G.TU_audioFile, G.TU_audioOffsetSec)
|
||||
|
||||
if cmds.window(winName, query=True, exists=True): cmds.deleteUI(winName)
|
||||
|
||||
cmds.setAttr("%s.overscan"%camera, overscan)
|
||||
|
||||
if not G.TU_movie: return
|
||||
save = aToolsMod.getUserPref("saveAfterPlayblasting", default=True)
|
||||
if save and not rangeVisible: cmds.file(save=True)
|
||||
|
||||
|
||||
def playMovie(self, movie, audioFile, audioOffsetSec):
|
||||
|
||||
|
||||
if not movie:
|
||||
cmds.warning( "No movie to play." )
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def playLastPlayblast(self, *args):
|
||||
|
||||
self.playMovie(G.TU_movie, G.TU_audioFile, G.TU_audioOffsetSec)
|
||||
|
||||
def duplicateCamera(self, *args):
|
||||
sel = cmds.ls(selection=True)
|
||||
camNode = utilMod.getCamFromSelection(sel)
|
||||
|
||||
if camNode:
|
||||
dupCamNode = cmds.camera()
|
||||
camTransformNode = camNode[0]
|
||||
camShapeNode = camNode[1]
|
||||
dupCamTransformNode = dupCamNode[0]
|
||||
dupCamShapeNode = dupCamNode[1]
|
||||
|
||||
utilMod.transferAttributes(camTransformNode, dupCamTransformNode)
|
||||
utilMod.transferAttributes(camShapeNode, dupCamShapeNode)
|
||||
G.aToolsBar.align.align([dupCamTransformNode], camTransformNode)
|
||||
cmds.select(dupCamTransformNode)
|
||||
|
||||
return
|
||||
|
||||
cmds.warning("No camera was created.")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
770
Scripts/Animation/aTools/animTools/animBar/subUIs/tangents.py
Normal file
@@ -0,0 +1,770 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
Modified: Michael Klimenko
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
import math
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import utilMod
|
||||
|
||||
class Tangents_Gui(uiMod.BaseSubUI):
|
||||
|
||||
def createLayout(self):
|
||||
|
||||
tangents = Tangents()
|
||||
buttons = ["flow", "bounce", "auto", "spline", "linear", "flat", "step"]
|
||||
|
||||
cmds.rowLayout(numberOfColumns=8, parent=self.parentLayout)
|
||||
|
||||
for loopButton in buttons:
|
||||
cmds.iconTextButton(style='iconAndTextVertical', image= uiMod.getImagePath("tangents_%s"%loopButton), highlightImage= uiMod.getImagePath("tangents_%s copy"%loopButton), w=self.wb, h=self.hb, command=lambda loopButton=loopButton, *args: tangents.setTangent(loopButton), annotation="%s tangent\\nRight click for options"%str.title(loopButton))
|
||||
tangents.popupMenu(loopButton)
|
||||
|
||||
# end createLayout
|
||||
|
||||
class Tangents(object):
|
||||
|
||||
def __init__(self):
|
||||
if G.aToolsBar.tangents: return
|
||||
G.aToolsBar.tangents = self
|
||||
|
||||
def popupMenu(self, button, *args):
|
||||
menu = cmds.popupMenu()
|
||||
cmds.popupMenu(menu, edit=True, postMenuCommand=lambda *args:self.populateMenu(menu, button), postMenuCommandOnce=True)
|
||||
|
||||
|
||||
def populateMenu(self, menu, button, *args):
|
||||
|
||||
print(("menu, button, *args", menu, button, args))
|
||||
|
||||
|
||||
if button != "step":
|
||||
cmds.menuItem(label='In Tangent', command=lambda *args: self.setTangent(button, 'in'), parent=menu)
|
||||
cmds.menuItem(label='Out Tangent', command=lambda *args: self.setTangent(button, 'out'), parent=menu)
|
||||
cmds.menuItem(divider=True, parent=menu)
|
||||
cmds.menuItem(label='First Frame', command=lambda *args: self.setTangent(button, 'out', 'first'), parent=menu)
|
||||
cmds.menuItem(label='Last Frame', command=lambda *args: self.setTangent(button, 'in', 'last'), parent=menu)
|
||||
cmds.menuItem(label='Both Ends', command=lambda *args: self.setTangent(button, 'inOut', 'both'), parent=menu)
|
||||
|
||||
cmds.menuItem(divider=True, parent=menu)
|
||||
cmds.menuItem(label='All Keys', command=lambda *args: self.setTangent(button, 'inOut', 'all'), parent=menu)
|
||||
|
||||
|
||||
|
||||
|
||||
def flowAround(self, frames = 2, excludeCurrKey = False):
|
||||
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
if animCurves:
|
||||
#if getFrom == "graphEditor":
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
tangentType = "flow"
|
||||
time = None
|
||||
|
||||
#animMod.expandKeySelection(frames)
|
||||
|
||||
index = animMod.getTarget("keysIndexSel", animCurves, getFrom)
|
||||
indexTimes = animMod.getTarget("keyIndexTimes", animCurves, getFrom)
|
||||
|
||||
#expand selection
|
||||
for n, loopCurve in enumerate(index):
|
||||
for x in range(frames):
|
||||
if loopCurve[0] >= 1:
|
||||
loopCurve.insert(0, loopCurve[0]-1)
|
||||
if loopCurve[-1] < indexTimes[n][-1]:
|
||||
loopCurve.append(loopCurve[-1]+1)
|
||||
|
||||
#if excludeCurrKey:
|
||||
|
||||
|
||||
|
||||
self.applyTangent(animCurves, tangentType, getFrom, time, index)
|
||||
|
||||
#select back keys
|
||||
if keysSel:
|
||||
cmds.selectKey(clear=True)
|
||||
for n, aCurve in enumerate(animCurves):
|
||||
for key in keysSel[n]:
|
||||
cmds.selectKey(aCurve, addTo=True, time=(key, key))
|
||||
|
||||
def applyTangent(self, animCurves, tangentType, getFrom, time, index, tangentInOut="inOut"):
|
||||
|
||||
|
||||
|
||||
if self.isDefaultTangent(tangentType): #default maya tangents
|
||||
if tangentType == "step":
|
||||
cmds.keyTangent(animCurves, edit=True, time=time, outTangentType=tangentType)
|
||||
|
||||
else:
|
||||
if tangentInOut =="inOut" or tangentInOut == "in":
|
||||
#print "applied in", time, tangentType
|
||||
cmds.keyTangent(animCurves, edit=True, time=time, inTangentType=tangentType)
|
||||
if tangentInOut =="inOut" or tangentInOut == "out":
|
||||
#print "applied out", time, tangentType
|
||||
cmds.keyTangent(animCurves, edit=True, time=time, outTangentType=tangentType)
|
||||
|
||||
else: #custom tangents
|
||||
|
||||
|
||||
|
||||
keyTimes = animMod.getTarget("keyTimes", animCurves)
|
||||
keyIndexTimes = animMod.getTarget("keyIndexTimes", animCurves)
|
||||
keysIndexSel = index
|
||||
keyValues = animMod.getTarget("keyValues", animCurves)
|
||||
|
||||
|
||||
cycleArray = []
|
||||
tangentArray = []
|
||||
|
||||
for n, aCurve in enumerate(animCurves):
|
||||
cycleArray.append([])
|
||||
tangentArray.append([])
|
||||
|
||||
if keysIndexSel != None and keyTimes[n] != None and keysIndexSel[n] != None and len(keyTimes[n]) >=2:
|
||||
|
||||
if keyValues[n][0] == keyValues[n][-1] and keysIndexSel[n] == keyIndexTimes[n]: #it's a cycle
|
||||
cycleArray[n] = True
|
||||
else:
|
||||
cycleArray[n] = False
|
||||
|
||||
#define tangent array
|
||||
for i in keysIndexSel[n]:
|
||||
tangentArray[n].append(cmds.keyTangent(aCurve, query=True, index=(i, i), inTangentType=True, outTangentType=True, inAngle=True, outAngle=True))
|
||||
|
||||
|
||||
passes = [self.averageTangent, self.flowTangent]
|
||||
#passes = [averageTangent]
|
||||
#self.fixTangentOvershoot, self.fixTangentOpposite
|
||||
self.applyPass(passes, animCurves, keyTimes, keyValues, keysIndexSel, tangentType)
|
||||
|
||||
|
||||
|
||||
|
||||
# put back saved in out sides
|
||||
for n, aCurve in enumerate(animCurves):
|
||||
|
||||
if keysIndexSel != None and keyTimes[n] != None and keysIndexSel[n] != None and len(keyTimes[n]) >=2:
|
||||
|
||||
for nn, i in enumerate(keysIndexSel[n]):
|
||||
|
||||
tangent = tangentArray[n][nn]
|
||||
|
||||
if tangentInOut == "in":
|
||||
cmds.keyTangent(aCurve, edit=True, index=(i, i), lock=False)
|
||||
cmds.keyTangent(aCurve, edit=True, index=(i, i), outTangentType=tangent[3], outAngle=tangent[1])
|
||||
cmds.keyTangent(aCurve, edit=True, index=(i, i), lock=True)
|
||||
|
||||
elif tangentInOut == "out":
|
||||
cmds.keyTangent(aCurve, edit=True, index=(i, i), lock=False)
|
||||
cmds.keyTangent(aCurve, edit=True, index=(i, i), inTangentType=tangent[2], inAngle=tangent[0])
|
||||
cmds.keyTangent(aCurve, edit=True, index=(i, i), lock=True)
|
||||
|
||||
|
||||
|
||||
if tangentType == "flow":
|
||||
# bounce ends
|
||||
|
||||
for n, aCurve in enumerate(animCurves):
|
||||
first = None
|
||||
last = None
|
||||
|
||||
if 0 in keysIndexSel[n]: first = True
|
||||
if len(keyTimes[n])-1 in keysIndexSel[n]: last = True
|
||||
|
||||
if first and last:
|
||||
self.bounceEnds([aCurve], "bounce", getFrom, tangentInOut, [keyTimes[n]], [keyIndexTimes[n]], "both")
|
||||
elif first:
|
||||
self.bounceEnds([aCurve], "bounce", getFrom, tangentInOut, [keyTimes[n]], [keyIndexTimes[n]], "first")
|
||||
elif last:
|
||||
self.bounceEnds([aCurve], "bounce", getFrom, tangentInOut, [keyTimes[n]], [keyIndexTimes[n]], "last")
|
||||
|
||||
#print "fl", first, last
|
||||
|
||||
# cycle?
|
||||
for n, aCurve in enumerate(animCurves):
|
||||
if cycleArray[n]:
|
||||
angle = cmds.keyTangent(aCurve, query=True, index=(0, 0), outAngle=True)[0]
|
||||
cmds.keyTangent(aCurve, time=(keyTimes[n][-1], keyTimes[n][-1]), inAngle=angle, outAngle=angle)
|
||||
|
||||
|
||||
|
||||
|
||||
def applyPass(self, passes, animCurves, keyTimes, keyValues, keysIndexSel, tangentType):
|
||||
|
||||
|
||||
|
||||
newKeysIndexSel = utilMod.dupList(keysIndexSel)
|
||||
|
||||
for loopFunction in passes:
|
||||
|
||||
#utilMod.timer("s")
|
||||
|
||||
for n, aCurve in enumerate(animCurves):
|
||||
|
||||
if keysIndexSel != None and keyTimes[n] != None and keysIndexSel[n] != None and len(keyTimes[n]) >=2:
|
||||
|
||||
#utilMod.timer()
|
||||
|
||||
#unlock weights
|
||||
weighted = cmds.keyTangent(aCurve, query=True, weightedTangents=True)[0]
|
||||
locked = cmds.keyTangent(aCurve, query=True, lock=True)
|
||||
|
||||
#utilMod.timer()
|
||||
|
||||
if weighted: cmds.keyTangent(aCurve, edit=True, weightedTangents=False) #weight to balance in and out tangents
|
||||
cmds.keyTangent(aCurve, edit=True, weightedTangents=True)
|
||||
|
||||
#utilMod.timer()
|
||||
|
||||
if loopFunction == self.fixTangentOpposite:
|
||||
#remove last index
|
||||
if len(keysIndexSel[n]) > 0: keysIndexSel[n].pop()
|
||||
if len(newKeysIndexSel[n]) > 0: newKeysIndexSel[n].pop()
|
||||
#reorder index according with size of segment
|
||||
keysIndexSel[n] = self.tangentOppositeReorder(keysIndexSel[n], keyValues[n])
|
||||
|
||||
#utilMod.timer()
|
||||
|
||||
# apply the damn function
|
||||
for loopIndex in keysIndexSel[n]:
|
||||
|
||||
curTangType = self.tangType(keyValues[n], keyTimes[n], loopIndex)
|
||||
|
||||
applied = loopFunction(aCurve, keyValues[n], loopIndex, tangentType, curTangType, keysIndexSel[n], keyTimes[n])
|
||||
|
||||
if loopFunction == self.fixTangentOvershoot and applied:
|
||||
#remove the applied index to avoid changind that tangent again
|
||||
if newKeysIndexSel[n]: newKeysIndexSel[n].remove(loopIndex)
|
||||
|
||||
#utilMod.timer()
|
||||
|
||||
# put back
|
||||
for i, loopLocked in enumerate(locked):
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
if loopLocked: cmds.keyTangent(aCurve, edit=True, index=(i,i), lock=loopLocked)
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
#utilMod.timer()
|
||||
|
||||
if weighted: cmds.keyTangent(aCurve, edit=True, weightedTangents=False) #weight to balance in and out tangents
|
||||
cmds.keyTangent(aCurve, edit=True, weightedTangents=weighted)
|
||||
|
||||
#utilMod.timer("e", loopFunction)
|
||||
|
||||
|
||||
def tangentOppositeReorder(self, indexes, values):
|
||||
#put bigger segments first
|
||||
|
||||
difList = []
|
||||
for n, loopVal in enumerate(values[2:-3]):
|
||||
dif = values[n+1+2] - values[n+2]
|
||||
difList.append(abs(dif))
|
||||
|
||||
indexList = []
|
||||
tmpDifList = utilMod.dupList(difList)
|
||||
for n, loopDif in enumerate(tmpDifList):
|
||||
maxDif = max(tmpDifList)
|
||||
index = difList.index(maxDif)
|
||||
tmpDifList[index] = -1
|
||||
indexList.append(index)
|
||||
|
||||
newIndexes = []
|
||||
for loopIndex in indexList:
|
||||
if loopIndex in indexes:
|
||||
newIndexes.append(loopIndex)
|
||||
|
||||
"""
|
||||
print "indexList",indexList
|
||||
print "values",values
|
||||
print "difList",difList
|
||||
print "indexes",indexes
|
||||
print "newIndexes",newIndexes
|
||||
"""
|
||||
|
||||
return newIndexes
|
||||
|
||||
def setTangent(self, tangentType, tangentInOut="inOut", targetKeys="selected", *args):
|
||||
|
||||
#utilMod.timer(mode="s", function="MAIN FUNCTION")
|
||||
|
||||
cmds.waitCursor(state=True)
|
||||
|
||||
"""
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
"""
|
||||
|
||||
#tangentType = flow, bounce, auto, etc
|
||||
#targetKeys = all, selected
|
||||
#tangentInOut = inOut, in, out
|
||||
|
||||
#set default tangent type
|
||||
if tangentType == "flow":
|
||||
cmds.keyTangent(edit=True, g=True, inTangentType="auto", outTangentType="auto")
|
||||
elif tangentType == "step":
|
||||
cmds.keyTangent(edit=True, g=True, outTangentType=tangentType)
|
||||
elif tangentType != "bounce":
|
||||
cmds.keyTangent(edit=True, g=True, inTangentType=tangentType, outTangentType=tangentType)
|
||||
|
||||
|
||||
# get target curves
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
#if there is no curves, exit
|
||||
if animCurves:
|
||||
status = "aTools - Tangents..."
|
||||
utilMod.startProgressBar(status)
|
||||
totalSteps = len(animCurves)
|
||||
firstStep = 0
|
||||
thisStep = 0
|
||||
estimatedTime = None
|
||||
startChrono = None
|
||||
|
||||
index = None
|
||||
time = None
|
||||
|
||||
if targetKeys == "all": # apply for all keys
|
||||
time = (-50000, 500000)
|
||||
|
||||
if not self.isDefaultTangent(tangentType):
|
||||
index = animMod.getTarget("keyIndexTimes", animCurves, getFrom)
|
||||
|
||||
self.applyTangent(animCurves, tangentType, getFrom, time, index)
|
||||
|
||||
elif targetKeys == "selected": #apply on a range
|
||||
if getFrom == "timeline":
|
||||
time = animMod.getTimelineRange(); time = (time[0], time[1])#flow and bounce
|
||||
if not self.isDefaultTangent(tangentType): index = animMod.getTarget("keysIndexSel", animCurves, getFrom)
|
||||
self.applyTangent(animCurves, tangentType, getFrom, time, index, tangentInOut)
|
||||
|
||||
else:
|
||||
if self.isDefaultTangent(tangentType): # if the tangent types are default maya types
|
||||
#apply individually on each key
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
|
||||
for thisStep, aCurve in enumerate(animCurves):
|
||||
if cmds.progressBar(G.progBar, query=True, isCancelled=True ):
|
||||
utilMod.setProgressBar(endProgress=True)
|
||||
break
|
||||
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
|
||||
|
||||
for loopKey in keysSel[thisStep] :
|
||||
time = (loopKey, loopKey)
|
||||
self.applyTangent(aCurve, tangentType, getFrom, time, index, tangentInOut)
|
||||
|
||||
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
|
||||
|
||||
else: #flow and bounce
|
||||
index = animMod.getTarget("keysIndexSel", animCurves, getFrom)
|
||||
self.applyTangent(animCurves, tangentType, getFrom, time, index, tangentInOut)
|
||||
else:# first and last frame
|
||||
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
|
||||
keyIndexTimes = animMod.getTarget("keyIndexTimes", animCurves, getFrom)
|
||||
|
||||
self.bounceEnds(animCurves, tangentType, getFrom, tangentInOut, keyTimes, keyIndexTimes, targetKeys)
|
||||
|
||||
|
||||
utilMod.setProgressBar(endProgress=True)
|
||||
#cmds.undoInfo(closeChunk=True)
|
||||
|
||||
cmds.waitCursor(state=False)
|
||||
|
||||
#utilMod.timer(mode="e", function="MAIN FUNCTION")
|
||||
|
||||
def bounceEnds(self, animCurves, tangentType, getFrom, tangentInOut, keyTimes, keyIndexTimes, targetKeys):
|
||||
for n, aCurve in enumerate(animCurves):
|
||||
if targetKeys == "first" or targetKeys == "both":
|
||||
|
||||
firstTime = keyTimes[n][0]
|
||||
firstIndex = keyIndexTimes[n][0]
|
||||
time = (firstTime,firstTime)
|
||||
index = [firstIndex]
|
||||
|
||||
self.applyTangent([aCurve], tangentType, getFrom, [time], [index], tangentInOut)
|
||||
|
||||
if targetKeys == "last" or targetKeys == "both":
|
||||
lastTime = keyTimes[n][-1]
|
||||
lastIndex = keyIndexTimes[n][-1]
|
||||
time = (lastTime,lastTime)
|
||||
index = [lastIndex]
|
||||
|
||||
self.applyTangent([aCurve], tangentType, getFrom, [time], [index], tangentInOut)
|
||||
|
||||
|
||||
def isDefaultTangent(self, tangentType):
|
||||
return (tangentType != "flow" and tangentType != "bounce")
|
||||
|
||||
def tangType(self, keyVal, keyTimes, index):
|
||||
|
||||
keyValTmp = utilMod.dupList(keyVal)
|
||||
|
||||
keyLocation = self.getKeyLocation(keyValTmp, index)
|
||||
nKeys = len(keyValTmp)
|
||||
|
||||
if keyLocation == "first":
|
||||
if keyValTmp[index] == keyValTmp[index+1] == keyValTmp[index+2]:
|
||||
return "Zero"
|
||||
elif keyLocation == "last":
|
||||
if keyValTmp[index] == keyValTmp[index-1] == keyValTmp[index-2]:
|
||||
return "Zero"
|
||||
else:
|
||||
index += 2
|
||||
for x in range(2):
|
||||
keyValTmp.insert(0, keyValTmp[0])
|
||||
keyValTmp.append(keyValTmp[-1])
|
||||
|
||||
if keyValTmp[index] == keyValTmp[index+1] == keyValTmp[index+2] or keyValTmp[index] == keyValTmp[index-1] == keyValTmp[index-2] or keyValTmp[index] == keyValTmp[index+1] == keyValTmp[index-1]:
|
||||
return "Zero"
|
||||
|
||||
#or....
|
||||
return "Average"
|
||||
|
||||
|
||||
def getAverageAngle(self, keyVal, keyTimes, index):
|
||||
|
||||
keyLocation = self.getKeyLocation(keyVal, index)
|
||||
|
||||
if keyLocation == "mid":
|
||||
|
||||
relTimeInA = keyTimes[index] - keyTimes[index-1]
|
||||
relValInA = keyVal[index-1] - keyVal[index]
|
||||
relTimeOutA = keyTimes[index+1] - keyTimes[index]
|
||||
relValOutA = keyVal[index+1] - keyVal[index]
|
||||
outAngleA = math.degrees(math.atan(relValOutA/relTimeOutA))
|
||||
outOpp = relTimeInA*math.tan(math.radians(outAngleA))
|
||||
|
||||
return -math.degrees(math.atan(((relValInA-outOpp)/2)/relTimeInA))
|
||||
|
||||
return 0
|
||||
|
||||
# end getAverageAngle
|
||||
|
||||
def getKeyLocation(self, keyVal, index):
|
||||
if index == 0:
|
||||
return "first"
|
||||
elif index == len(keyVal)-1:
|
||||
return "last"
|
||||
else:
|
||||
return "mid"
|
||||
|
||||
def fixTangentOvershoot(self, aCurve, keyVal, index, tangentType, curTangType, keysIndexSelN, *args):
|
||||
|
||||
#print "qual index? ", index
|
||||
if index == None: return
|
||||
|
||||
#fix tangent limit ----------------------------------------------------------------------------
|
||||
applied = False
|
||||
|
||||
|
||||
power = .8
|
||||
|
||||
#get in values
|
||||
iy = cmds.keyTangent(aCurve, query=True, index=(index, index), iy=True)[0]/3*power #in tangent handle y position
|
||||
oy = cmds.keyTangent(aCurve, query=True, index=(index, index), oy=True)[0]/3*power #out tangent handle y position
|
||||
|
||||
prevVal = keyVal[index-1]
|
||||
currVal = keyVal[index]
|
||||
nextVal = keyVal[index+1]
|
||||
|
||||
|
||||
#convert to radians if rotate
|
||||
isRotate = animMod.isAnimCurveRotate(aCurve)
|
||||
if isRotate:
|
||||
prevVal = math.radians(prevVal)
|
||||
currVal = math.radians(currVal)
|
||||
nextVal = math.radians(nextVal)
|
||||
|
||||
|
||||
|
||||
difNext = (nextVal-currVal)*power
|
||||
difPrev = (currVal-prevVal)*power
|
||||
|
||||
if (difNext < 0 and oy < difNext) or (difNext > 0 and oy > difNext):
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="auto", outTangentType="auto")
|
||||
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), oy=difNext*3)
|
||||
applied = True
|
||||
|
||||
|
||||
if (difPrev < 0 and iy < difPrev) or (difPrev > 0 and iy > difPrev):
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="auto", outTangentType="auto")
|
||||
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), iy=difPrev*3)
|
||||
|
||||
#print "aplicou index:", index
|
||||
|
||||
if index-1 in keysIndexSelN:
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index-1, index-1), inTangentType="auto", outTangentType="auto")
|
||||
|
||||
self.flowTangent(aCurve, keyVal, index-1, tangentType)
|
||||
applied = True
|
||||
|
||||
#print "flow index:", index-1
|
||||
"""
|
||||
print "--------------------------------"
|
||||
print "index", index
|
||||
print "iy",iy
|
||||
print "oy",oy
|
||||
print "difPrev",difPrev
|
||||
print "prevVal",prevVal
|
||||
print "nextVal",nextVal
|
||||
print "currVal",currVal
|
||||
"""
|
||||
|
||||
|
||||
return applied
|
||||
|
||||
def fixTangentOpposite(self, aCurve, keyVal, index, tangentType, curTangType, keysIndexSelN, *args):
|
||||
|
||||
if index == None: return
|
||||
|
||||
currVal = keyVal[index]
|
||||
nextVal = keyVal[index+1]
|
||||
currTime = cmds.keyframe(aCurve, query=True, index=(index,index), timeChange=True)[0]#current time value
|
||||
nextTime = cmds.keyframe(aCurve, query=True, index=(index+1,index+1), timeChange=True)[0]#current time value
|
||||
|
||||
power = 2
|
||||
|
||||
|
||||
#get in values for next key
|
||||
ix = cmds.keyTangent(aCurve, query=True, index=(index+1,index+1), ix=True)[0] #in tangent handle x position
|
||||
iy = cmds.keyTangent(aCurve, query=True, index=(index+1,index+1), iy=True)[0] #in tangent handle y position
|
||||
|
||||
#get out values
|
||||
ox = cmds.keyTangent(aCurve, query=True, index=(index,index), ox=True)[0] #out tangent handle x position
|
||||
oy = cmds.keyTangent(aCurve, query=True, index=(index,index), oy=True)[0] #out tangent handle y position
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#curve position at handle
|
||||
valIn = nextVal - cmds.keyframe(aCurve, query=True, eval=True, time=(nextTime-ix/.125,nextTime-ix/.125), valueChange=True)[0]
|
||||
valOut = cmds.keyframe(aCurve, query=True, eval=True, time=(currTime+ox/.125,currTime+ox/.125), valueChange=True)[0] - currVal
|
||||
|
||||
#convert to radians if rotate
|
||||
isRotate = animMod.isAnimCurveRotate(aCurve)
|
||||
if isRotate:
|
||||
currVal = math.radians(currVal)
|
||||
nextVal = math.radians(nextVal)
|
||||
valIn = math.radians(valIn)
|
||||
valOut = math.radians(valOut)
|
||||
|
||||
#difference btw val and y
|
||||
difIn = iy/3 - valIn
|
||||
difOut = oy/3 - valOut
|
||||
|
||||
|
||||
|
||||
|
||||
#detect
|
||||
if (difIn > 0 and difOut > 0) or (difIn < 0 and difOut < 0):
|
||||
|
||||
if abs(difIn) > abs(difOut):
|
||||
inOut = "in"
|
||||
|
||||
else:
|
||||
inOut = "out"
|
||||
|
||||
|
||||
for x in range(5):
|
||||
currVal = keyVal[index]
|
||||
nextVal = keyVal[index+1]
|
||||
#get in values for next key
|
||||
ix = cmds.keyTangent(aCurve, query=True, index=(index+1,index+1), ix=True)[0] #in tangent handle x position
|
||||
iy = cmds.keyTangent(aCurve, query=True, index=(index+1,index+1), iy=True)[0] #in tangent handle y position
|
||||
|
||||
#get out values
|
||||
ox = cmds.keyTangent(aCurve, query=True, index=(index,index), ox=True)[0] #out tangent handle x position
|
||||
oy = cmds.keyTangent(aCurve, query=True, index=(index,index), oy=True)[0] #out tangent handle y position
|
||||
|
||||
#curve position at handle
|
||||
valIn = nextVal - cmds.keyframe(aCurve, query=True, eval=True, time=(nextTime-ix/.125,nextTime-ix/.125), valueChange=True)[0]
|
||||
valOut = cmds.keyframe(aCurve, query=True, eval=True, time=(currTime+ox/.125,currTime+ox/.125), valueChange=True)[0] - currVal
|
||||
|
||||
#convert to radians if rotate
|
||||
isRotate = animMod.isAnimCurveRotate(aCurve)
|
||||
if isRotate:
|
||||
currVal = math.radians(currVal)
|
||||
nextVal = math.radians(nextVal)
|
||||
valIn = math.radians(valIn)
|
||||
valOut = math.radians(valOut)
|
||||
|
||||
#difference btw val and y
|
||||
difIn = iy/3 - valIn
|
||||
difOut = oy/3 - valOut
|
||||
|
||||
if inOut == "in":
|
||||
#print"IN"
|
||||
|
||||
#if next key is is array
|
||||
if index+1 in keysIndexSelN:
|
||||
|
||||
newY = (iy/3) + (valOut-(oy/3))*power
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index+1, index+1), iy=newY*3, oy=newY*3, ox=ix)
|
||||
|
||||
|
||||
else:
|
||||
#print"OUT"
|
||||
newY = (oy/3) + (valIn-(iy/3))*power
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), iy=newY*3, oy=newY*3, ix=ox)
|
||||
|
||||
|
||||
|
||||
"""
|
||||
print "index",index
|
||||
print "difIn",difIn
|
||||
print "difOut",difOut
|
||||
print "iy",iy
|
||||
print "oy",oy
|
||||
print "iy/3",iy/3
|
||||
print "oy/3",oy/3
|
||||
print "valIn",valIn
|
||||
print "valOut",valOut
|
||||
print "currVal",currVal
|
||||
print "nextVal",nextVal
|
||||
print "------------------------------"
|
||||
"""
|
||||
|
||||
def averageTangent(self, aCurve, keyVal, index, tangentType, curTangType, keysIndexSelN, keyTimes, *args):
|
||||
# average
|
||||
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="linear", outTangentType="linear")
|
||||
|
||||
if tangentType == "flow":
|
||||
if curTangType == "Zero":
|
||||
mAngle = 0
|
||||
else:
|
||||
mAngle = self.getAverageAngle(keyVal, keyTimes, index)
|
||||
|
||||
if index == 0:
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), outTangentType="linear")
|
||||
return
|
||||
if index == len(keyVal)-1:
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="linear")
|
||||
return
|
||||
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), inAngle=mAngle, outAngle=mAngle)
|
||||
|
||||
|
||||
#if tangentType == "bounce":
|
||||
#cmds.keyTangent(aCurve, edit=True, index=(index, index), inTangentType="linear", outTangentType="linear")
|
||||
|
||||
def flowTangent(self, aCurve, keyVal, index, tangentType, curTangType, *args):
|
||||
|
||||
if curTangType == "Zero" and tangentType == "flow": return
|
||||
|
||||
if index == None: return
|
||||
|
||||
#is it first or last key?
|
||||
keyLocation = self.getKeyLocation(keyVal, index)
|
||||
|
||||
if keyLocation != "mid" and tangentType != "bounce": return
|
||||
|
||||
currVal = keyVal[index]
|
||||
currTime = cmds.keyframe(aCurve, query=True, index=(index,index), timeChange=True)[0]#current time value
|
||||
|
||||
#get in values
|
||||
ix = cmds.keyTangent(aCurve, query=True, index=(index,index), ix=True)[0] #in tangent handle x position
|
||||
iy = cmds.keyTangent(aCurve, query=True, index=(index,index), iy=True)[0] #in tangent handle y position
|
||||
|
||||
#get out values
|
||||
ox = cmds.keyTangent(aCurve, query=True, index=(index,index), ox=True)[0] #out tangent handle x position
|
||||
oy = cmds.keyTangent(aCurve, query=True, index=(index,index), oy=True)[0] #out tangent handle y position
|
||||
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
cmds.keyTangent(aCurve, index=(index,index), lock=False)
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
if tangentType == "flow":
|
||||
if ox>ix:
|
||||
ox = ix
|
||||
oy = iy
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), ox=ox, oy=oy)
|
||||
else:
|
||||
ix = ox
|
||||
iy = oy
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), ix=ix, iy=iy)
|
||||
|
||||
|
||||
#curve position at handle
|
||||
valIn = cmds.keyframe(aCurve, query=True, eval=True, time=(currTime-ix/.125,currTime-ix/.125), valueChange=True)[0]
|
||||
valOut = cmds.keyframe(aCurve, query=True, eval=True, time=(currTime+ox/.125,currTime+ox/.125), valueChange=True)[0]
|
||||
|
||||
|
||||
#if the anim curve is rotate, convert to radians
|
||||
isRotate = animMod.isAnimCurveRotate(aCurve)
|
||||
if isRotate:
|
||||
currVal = math.radians(currVal)
|
||||
valIn = math.radians(valIn)
|
||||
valOut = math.radians(valOut)
|
||||
#print "isrotate"
|
||||
|
||||
#distance between the curve position and the key value
|
||||
distValueIn = (valIn-currVal)
|
||||
distValueOut = (valOut-currVal)
|
||||
|
||||
#distance between the curve position and the tangent y position
|
||||
distTangIn = distValueIn+(iy/3)
|
||||
distTangOut = distValueOut-(oy/3)
|
||||
|
||||
|
||||
if tangentType == "flow":
|
||||
|
||||
# calculate the difference btween the distances between the curve position and the tangent y position
|
||||
dif = (distTangIn-distTangOut)
|
||||
|
||||
newOy = (oy/3)-dif
|
||||
|
||||
#newIy = (iy/3)-dif
|
||||
newIy = newOy
|
||||
|
||||
#print "newIy",newIy,"(iy/3)",(iy/3),"(oy/3)",(oy/3),"currVal",currVal,"valOut",valOut,"distIn",distTangIn,"distOut",distTangOut,"dif",dif,"distValueIn",distValueIn,"distValueOut",distValueOut
|
||||
|
||||
elif tangentType == "bounce":
|
||||
newIy = -distValueIn+(-distValueIn-(iy/3))
|
||||
newOy = distValueOut+(distValueOut-(oy/3))
|
||||
|
||||
"""
|
||||
print "---------------------------"
|
||||
print "newIy",newIy
|
||||
print "newOy",newOy
|
||||
print "(iy/3)",(iy/3)
|
||||
print "(oy/3)",(oy/3)
|
||||
print "currVal",currVal
|
||||
print "valOut",valOut
|
||||
print "distIn",distTangIn
|
||||
print "distOut",distTangOut
|
||||
print "distValueIn",distValueIn
|
||||
print "distValueOut",distValueOut
|
||||
"""
|
||||
|
||||
#apply
|
||||
|
||||
cmds.keyTangent(aCurve, edit=True, index=(index, index), iy=newIy*3, oy=newOy*3)
|
||||
|
@@ -0,0 +1,284 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import commandsMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
G.TM_coloredKeys = None
|
||||
G.TM_lastTweenCommand = G.TM_lastTweenCommand or None
|
||||
|
||||
class TweenMachine_Gui(uiMod.BaseSubUI):
|
||||
|
||||
def createLayout(self):
|
||||
tweenMachine = TweenMachine()
|
||||
|
||||
cmds.rowColumnLayout(numberOfColumns=100, parent=self.parentLayout)
|
||||
|
||||
#linear
|
||||
cmds.text( label=' ', h=1 )
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_left"), highlightImage= uiMod.getImagePath("tweenMachine_left copy"), command=lambda *args: tweenMachine.setTween("linear_prev"), annotation="Overshoot linear tween")
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hb, image= uiMod.getImagePath("tweenMachine_L"), highlightImage= uiMod.getImagePath("tweenMachine_L copy"), command=lambda *args: tweenMachine.setTween("linear"), annotation="Linear tween")
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_right"), highlightImage= uiMod.getImagePath("tweenMachine_right copy"), command=lambda *args: tweenMachine.setTween("linear_next"), annotation="Overshoot linear tween")
|
||||
|
||||
#tween
|
||||
cmds.text( label=' ', h=1 )
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_left"), highlightImage= uiMod.getImagePath("tweenMachine_left copy"), command=lambda *args: tweenMachine.setTween(-50), annotation="Overshoot 50% with previous key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(-30), annotation="Overshoot 30% with previous key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(-10), annotation="Overshoot 10% with previous key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hb, image= uiMod.getImagePath("tweenMachine_key"), highlightImage= uiMod.getImagePath("tweenMachine_key copy"), command=lambda *args: tweenMachine.setTween(0), annotation="Copy previous key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(10), annotation="Tween 90% with previous key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(20), annotation="Tween 80% with previous key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(33), annotation="Tween 66% with previous key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hb, image= uiMod.getImagePath("tweenMachine_T"), highlightImage= uiMod.getImagePath("tweenMachine_T copy"), command=lambda *args: tweenMachine.setTween(50), annotation="Tween 50%"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(66), annotation="Tween 66% with next key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(80), annotation="Tween 80% with next key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(90), annotation="Tween 90% with next key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hb, image= uiMod.getImagePath("tweenMachine_key"), highlightImage= uiMod.getImagePath("tweenMachine_key copy"), command=lambda *args: tweenMachine.setTween(100), annotation="Copy next key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(110), annotation="Overshoot 10% with next key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_mid"), highlightImage= uiMod.getImagePath("tweenMachine_mid copy"), command=lambda *args: tweenMachine.setTween(130), annotation="Overshoot 30% with next key"); tweenMachine.popUpColor()
|
||||
cmds.iconTextButton(style='iconOnly', marginWidth=0, w=self.ws, h=self.hs, image= uiMod.getImagePath("tweenMachine_right"),highlightImage= uiMod.getImagePath("tweenMachine_right copy"), command=lambda *args: tweenMachine.setTween(150), annotation="Overshoot 50% with next key"); tweenMachine.popUpColor()
|
||||
|
||||
|
||||
class TweenMachine(object):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
if G.aToolsBar.tweenMachine: return
|
||||
G.aToolsBar.tweenMachine = self
|
||||
|
||||
# end createLayout
|
||||
def popUpColor(self):
|
||||
cmds.popupMenu(postMenuCommand=self.populateColorMenu, postMenuCommandOnce=True)
|
||||
|
||||
def populateColorMenu(self, parent, *args):
|
||||
|
||||
cmds.menuItem(label="Color Keyframes", checkBox=self.getColoredKeys(), command=self.setColoredKeys, parent=parent)
|
||||
cmds.menuItem(divider=True, parent=parent )
|
||||
cmds.menuItem(label="Apply Special Key Color", command=lambda *args:self.applyTickColor(True), parent=parent)
|
||||
cmds.menuItem(label="Apply Default Key Color", command=lambda *args:self.applyTickColor(False), parent=parent)
|
||||
|
||||
|
||||
def getColoredKeys(self):
|
||||
|
||||
if not G.TM_coloredKeys:
|
||||
r = aToolsMod.loadInfoWithUser("userPrefs", "coloredKeys")
|
||||
else:
|
||||
r = G.TM_coloredKeys
|
||||
|
||||
if r == None:
|
||||
default = True
|
||||
r = default
|
||||
|
||||
G.TM_coloredKeys = r
|
||||
|
||||
return r
|
||||
|
||||
def setColoredKeys(self, onOff):
|
||||
onOff = not self.getColoredKeys()
|
||||
|
||||
G.TM_coloredKeys = onOff
|
||||
|
||||
aToolsMod.saveInfoWithUser("userPrefs", "coloredKeys", onOff)
|
||||
|
||||
|
||||
def repeatLastCommand(self):
|
||||
if G.TM_lastTweenCommand: eval(G.TM_lastTweenCommand)
|
||||
|
||||
|
||||
def setTween(self, percent, *args):
|
||||
|
||||
#utilMod.timer("s")
|
||||
|
||||
|
||||
G.TM_lastTweenCommand = "self.setTween(%s)"%percent
|
||||
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
if animCurves:
|
||||
status = "aTools - Tween Machine..."
|
||||
utilMod.startProgressBar(status)
|
||||
totalSteps = len(animCurves)
|
||||
firstStep = 0
|
||||
thisStep = 0
|
||||
estimatedTime = None
|
||||
startChrono = None
|
||||
|
||||
cmds.waitCursor(state=True)
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
keyTimes = animMod.getTarget("keyTimes", animCurves)
|
||||
timelineTime = None
|
||||
#keysSelMerged = utilMod.mergeLists(keysSel)
|
||||
|
||||
if isinstance(percent, int):
|
||||
# reverse order to get ease in and out smoothly
|
||||
if 0 < percent <= 50 or percent == 100:
|
||||
for loopVal in keysSel:
|
||||
loopVal.reverse()
|
||||
|
||||
#utilMod.timer()
|
||||
|
||||
"""
|
||||
if len(keysSelMerged) == 0:
|
||||
if not timelineTime: timelineTime = [animMod.getTimelineTime()]
|
||||
cmds.setKeyframe(animCurves, time=timelineTime[0])
|
||||
elif len(keysSelMerged) == 1:
|
||||
cmds.setKeyframe(animCurves, time=keysSelMerged[0])
|
||||
"""
|
||||
|
||||
|
||||
for thisStep, loopCurve in enumerate(animCurves):
|
||||
|
||||
if cmds.progressBar(G.progBar, query=True, isCancelled=True ):
|
||||
utilMod.setProgressBar(endProgress=True)
|
||||
break
|
||||
|
||||
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
|
||||
|
||||
if not keysSel[thisStep]:
|
||||
if not timelineTime: timelineTime = [animMod.getTimelineTime()]
|
||||
time = timelineTime
|
||||
else:
|
||||
time = [(loopTime,loopTime) for loopTime in keysSel[thisStep]]
|
||||
# if all keys selected, use timeline time instead
|
||||
if len(time) == len(keyTimes[thisStep]):
|
||||
if not timelineTime: timelineTime = [animMod.getTimelineTime()]
|
||||
time = timelineTime
|
||||
|
||||
|
||||
|
||||
for loopTime in time:
|
||||
|
||||
|
||||
prevKeyTime = cmds.findKeyframe(loopCurve, time=loopTime, which="previous")
|
||||
nextKeyTime = cmds.findKeyframe(loopCurve, time=loopTime, which="next")
|
||||
|
||||
if prevKeyTime == nextKeyTime and prevKeyTime != loopTime[0] and percent != "linear_next" and percent != "linear_prev": # if there is no previous or next key and at least one key
|
||||
cmds.setKeyframe(loopCurve, time=loopTime)
|
||||
|
||||
elif prevKeyTime != time[0]:
|
||||
|
||||
if percent == "linear_prev":
|
||||
|
||||
prevKeyTime = nextKeyTime
|
||||
nextKeyTime = cmds.findKeyframe(loopCurve, time=(prevKeyTime,prevKeyTime), which="next")
|
||||
prevKeyVal = cmds.keyframe(loopCurve, query=True, time=(prevKeyTime, prevKeyTime), valueChange=True)[0]
|
||||
nextKeyVal = cmds.keyframe(loopCurve, query=True, time=(nextKeyTime, nextKeyTime), valueChange=True)[0]
|
||||
|
||||
if nextKeyTime == prevKeyTime:
|
||||
value = prevKeyVal
|
||||
else:
|
||||
value = prevKeyVal + ((nextKeyVal - prevKeyVal)/(nextKeyTime - prevKeyTime)*(loopTime[0] - prevKeyTime))
|
||||
|
||||
elif percent == "linear_next":
|
||||
|
||||
nextKeyTime = prevKeyTime
|
||||
prevKeyTime = cmds.findKeyframe(loopCurve, time=(nextKeyTime,nextKeyTime), which="previous")
|
||||
prevKeyVal = cmds.keyframe(loopCurve, query=True, time=(prevKeyTime, prevKeyTime), valueChange=True)[0]
|
||||
nextKeyVal = cmds.keyframe(loopCurve, query=True, time=(nextKeyTime, nextKeyTime), valueChange=True)[0]
|
||||
|
||||
if nextKeyTime == prevKeyTime:
|
||||
value = prevKeyVal
|
||||
else:
|
||||
value = prevKeyVal + ((nextKeyVal - prevKeyVal)/(nextKeyTime - prevKeyTime)*(loopTime[0] - prevKeyTime))
|
||||
|
||||
else:
|
||||
|
||||
animMod.eulerFilterCurve([loopCurve])
|
||||
|
||||
prevKeyVal = cmds.keyframe(loopCurve, query=True, time=(prevKeyTime, prevKeyTime), valueChange=True)[0]
|
||||
nextKeyVal = cmds.keyframe(loopCurve, query=True, time=(nextKeyTime, nextKeyTime), valueChange=True)[0]
|
||||
|
||||
#print "prevKeyVal", prevKeyVal, nextKeyVal
|
||||
|
||||
#if prevKeyVal == nextKeyVal:
|
||||
#if not time[0] in keysSel[thisStep]: cmds.setKeyframe(loopCurve, time=loopTime)
|
||||
#continue
|
||||
|
||||
|
||||
if percent == "linear": value = prevKeyVal + ((nextKeyVal - prevKeyVal)/(nextKeyTime - prevKeyTime)*(loopTime[0] - prevKeyTime))
|
||||
else: value = ((nextKeyVal-prevKeyVal)/100.*percent)+prevKeyVal
|
||||
|
||||
|
||||
tangentType = cmds.keyTangent(loopCurve, query=True, outTangentType=True, time=(prevKeyTime,prevKeyTime))[0]
|
||||
inTangentType = tangentType.replace("fixed", "auto").replace("step", "auto")
|
||||
outTangentType = tangentType.replace("fixed", "auto")
|
||||
|
||||
if not time[0] in keysSel[thisStep]: cmds.setKeyframe(loopCurve, time=loopTime)
|
||||
|
||||
cmds.keyframe(loopCurve, edit=True, time=loopTime, valueChange=value)
|
||||
cmds.keyTangent(loopCurve, edit=True, time=loopTime, inTangentType=inTangentType, outTangentType=outTangentType)
|
||||
#keycolor
|
||||
if (isinstance(percent, int) and (1 <= percent <= 99)) or percent == "linear": cmds.keyframe(loopCurve ,edit=True,time=loopTime, tickDrawSpecial=self.getColoredKeys())
|
||||
|
||||
|
||||
|
||||
if getFrom == "graphEditor":
|
||||
#curvesToSelect.append([loopCurve, loopTime])
|
||||
cmds.selectKey(loopCurve, addTo=True, time=loopTime)
|
||||
|
||||
|
||||
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
|
||||
|
||||
#utilMod.timer()
|
||||
"""
|
||||
#APPLY
|
||||
if len(curvesToKey) > 0: cmds.setKeyframe(curvesToKey)
|
||||
|
||||
for loopVar in curvesToValue:
|
||||
cmds.keyframe(loopVar[0], edit=True, time=loopVar[1], valueChange=loopVar[2])
|
||||
cmds.keyTangent(loopVar[0], edit=True, time=loopVar[1], inTangentType=loopVar[3], outTangentType=loopVar[4])
|
||||
|
||||
for loopVar in curvesToColor: cmds.keyframe(loopVar[0], edit=True, time=loopVar[1], tickDrawSpecial=self.getColoredKeys())
|
||||
for loopVar in curvesToSelect: cmds.selectKey(loopVar[0], addTo=True, time=loopVar[1])
|
||||
"""
|
||||
|
||||
|
||||
cmds.refresh(suspend=False)
|
||||
cmds.waitCursor(state=False)
|
||||
utilMod.setProgressBar(endProgress=True)
|
||||
|
||||
#utilMod.timer("e", "tween")
|
||||
#end tweenValue
|
||||
|
||||
|
||||
|
||||
def applyTickColor(self, special=True, *args):
|
||||
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
|
||||
if animCurves:
|
||||
|
||||
for n, loopCurve in enumerate(animCurves):
|
||||
time = [(loopTime,loopTime) for loopTime in keysSel[n]]
|
||||
|
||||
for loopTime in time:
|
||||
#keycolor
|
||||
cmds.keyframe(loopCurve ,edit=True,time=loopTime, tickDrawSpecial=special)
|
||||
|
971
Scripts/Animation/aTools/animTools/animationCrashRecovery.py
Normal 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
|
||||
|
||||
"""
|
||||
|
84
Scripts/Animation/aTools/animTools/framePlaybackRange.py
Normal 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)
|
||||
|
||||
|
56
Scripts/Animation/aTools/animTools/jumpToSelectedKey.py
Normal 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]
|
||||
|
4
Scripts/Animation/aTools/commonMods/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import *
|
230
Scripts/Animation/aTools/commonMods/aToolsMod.py
Normal 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
|
||||
|
941
Scripts/Animation/aTools/commonMods/animMod.py
Normal 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
|
||||
|
383
Scripts/Animation/aTools/commonMods/commandsMod.py
Normal 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)
|
||||
|
||||
|
71
Scripts/Animation/aTools/commonMods/uiMod.py
Normal 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)
|
||||
|
||||
|
548
Scripts/Animation/aTools/commonMods/utilMod.py
Normal 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
|
4
Scripts/Animation/aTools/generalTools/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import *
|
317
Scripts/Animation/aTools/generalTools/aToolsClasses.py
Normal 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()
|
||||
|
24
Scripts/Animation/aTools/generalTools/aToolsGlobals.py
Normal 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()
|
||||
|
900
Scripts/Animation/aTools/generalTools/generalToolsUI.py
Normal 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")
|
354
Scripts/Animation/aTools/generalTools/hotkeys.py
Normal 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]
|
||||
|
||||
|
||||
|
47
Scripts/Animation/aTools/generalTools/offlineInstall.py
Normal 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()
|
111
Scripts/Animation/aTools/generalTools/tumbleOnObjects.py
Normal 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)
|
||||
|
||||
|
||||
|
||||
|
BIN
Scripts/Animation/aTools/img/ACR_green.png
Normal file
After Width: | Height: | Size: 396 B |
BIN
Scripts/Animation/aTools/img/ACR_off.png
Normal file
After Width: | Height: | Size: 1016 B |
BIN
Scripts/Animation/aTools/img/ACR_red.png
Normal file
After Width: | Height: | Size: 365 B |
BIN
Scripts/Animation/aTools/img/ACR_red_bright.png
Normal file
After Width: | Height: | Size: 600 B |
BIN
Scripts/Animation/aTools/img/ACR_red_half.png
Normal file
After Width: | Height: | Size: 167 B |
BIN
Scripts/Animation/aTools/img/ACR_white_bright.png
Normal file
After Width: | Height: | Size: 622 B |
BIN
Scripts/Animation/aTools/img/ACR_white_half.png
Normal file
After Width: | Height: | Size: 1016 B |
BIN
Scripts/Animation/aTools/img/aTools copy.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
Scripts/Animation/aTools/img/aTools.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/aTools_big.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
Scripts/Animation/aTools/img/animBot.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
Scripts/Animation/aTools/img/atools_animbot.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/beer copy.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
Scripts/Animation/aTools/img/beer.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_+ copy.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_+.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_- copy.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_-.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_bd copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_bd.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_bf copy.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_bf.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_bm copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_bm.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_bn copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_bn.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_divider.png
Normal file
After Width: | Height: | Size: 165 B |
BIN
Scripts/Animation/aTools/img/keyTransform_dot_a copy.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_dot_a.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_dropper copy.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_dropper.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_dropper_active.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_ea copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_ea.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_keykey copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_keykey.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_mini_dropper copy.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_mini_dropper.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_no copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_no.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_nudge_left copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_nudge_left.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_nudge_right copy.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_nudge_right.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_pp copy.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_pp.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_reset copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_reset.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sa copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sa.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sd copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sd.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_set_inbetween copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_set_inbetween.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sl copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sl.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_slider copy.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_slider.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_slider_active.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sn copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sn.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sr copy.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
Scripts/Animation/aTools/img/keyTransform_sr.png
Normal file
After Width: | Height: | Size: 2.9 KiB |