Updated
This commit is contained in:
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1,177 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
|
||||
class Align(object):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
if G.aToolsBar.align: return
|
||||
G.aToolsBar.align = self
|
||||
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu()
|
||||
cmds.menuItem(label="All Keys", command=self.alignAllKeys)
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem(label="Align Position", command=lambda *args: self.alignSelection(True, False))
|
||||
cmds.menuItem(label="Align Rotation", command=lambda *args: self.alignSelection(False, True))
|
||||
|
||||
|
||||
def alignAllKeys(self, *args):
|
||||
self.alignSelection(translate=True, rotate=True, all=True)
|
||||
|
||||
def alignSelection(self, translate=True, rotate=True, all=False):
|
||||
|
||||
selection = cmds.ls(selection=True)
|
||||
|
||||
if len(selection) < 2:
|
||||
cmds.warning("You need to select at least 2 objects.")
|
||||
return
|
||||
|
||||
sourceObjs = selection[0:-1]
|
||||
targetObj = selection[-1]
|
||||
frames = None
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
showProgress = all
|
||||
|
||||
|
||||
if animCurves:
|
||||
if all: keysSel = animMod.getTarget("keyTimes", animCurves, getFrom)
|
||||
else: keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
|
||||
frames = utilMod.mergeLists(keysSel)
|
||||
|
||||
if frames == []:
|
||||
frames = [currFrame]
|
||||
else:
|
||||
frames = [currFrame]
|
||||
|
||||
self.align(sourceObjs, targetObj, frames, translate, rotate, showProgress, selectSorceObjs=True)
|
||||
|
||||
|
||||
def align(self, sourceObjs, targetObj, frames=None, translate=True, rotate=True, showProgress=False, selectSorceObjs=False):
|
||||
|
||||
if not sourceObjs or not targetObj: return
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
constraints = []
|
||||
setValues = []
|
||||
modes = []
|
||||
status = "aTools - Aligning nodes..."
|
||||
|
||||
if translate: modes.append({"mode":"translate", "constrain":"pointConstraint"})
|
||||
if rotate: modes.append({"mode":"rotate", "constrain":"orientConstraint"})
|
||||
|
||||
if showProgress: utilMod.startProgressBar(status)
|
||||
|
||||
if not frames:
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
|
||||
if animCurves:
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
frames = utilMod.mergeLists(keysSel)
|
||||
|
||||
if frames == []:
|
||||
frames = [currFrame]
|
||||
else:
|
||||
frames = [currFrame]
|
||||
|
||||
if showProgress:
|
||||
totalSteps = len(sourceObjs + frames)
|
||||
firstStep = 0
|
||||
thisStep = 0
|
||||
estimatedTime = None
|
||||
startChrono = None
|
||||
|
||||
|
||||
#get values
|
||||
for thisStep, loopSourceObj in enumerate(sourceObjs):
|
||||
|
||||
if showProgress: startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
|
||||
|
||||
setValues.append({"modes":[], "values":[], "skips":[]})
|
||||
|
||||
for loopMode in modes:
|
||||
|
||||
mode = loopMode["mode"]
|
||||
constrainType = loopMode["constrain"]
|
||||
|
||||
allAttrs = cmds.listAttr(loopSourceObj, settable=True, keyable=True)
|
||||
skip = [loopXyz for loopXyz in ["x", "y", "z"] if "%s%s"%(mode, loopXyz.upper()) not in allAttrs]
|
||||
contrainFn = eval("cmds.%s"%constrainType)
|
||||
|
||||
with G.aToolsBar.createAToolsNode: constraints.append(contrainFn(targetObj, loopSourceObj, skip=skip)[0])
|
||||
|
||||
setValues[-1]["modes"].append(mode)
|
||||
setValues[-1]["values"].append([cmds.getAttr("%s.%s"%(loopSourceObj, mode), time=loopKey)[0] for loopKey in frames])
|
||||
setValues[-1]["skips"].append(skip)
|
||||
|
||||
|
||||
if showProgress: estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
|
||||
|
||||
#del constraints
|
||||
for loopConstrain in constraints: cmds.delete(loopConstrain)
|
||||
|
||||
for n, loopKey in enumerate(frames):
|
||||
|
||||
if showProgress:
|
||||
thisStep = thisStep + n + 1
|
||||
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
|
||||
|
||||
for nn, loopSourceObj in enumerate(sourceObjs):
|
||||
loopSetValue = setValues[nn]
|
||||
values = loopSetValue["values"]
|
||||
skips = loopSetValue["skips"]
|
||||
|
||||
for nnn, loopMode in enumerate(modes):
|
||||
mode = loopMode["mode"]
|
||||
xyz = [loopXyz for loopXyz in ["x", "y", "z"] if loopXyz not in skips[nnn]]
|
||||
|
||||
|
||||
for nnnn, loopXyz in enumerate(xyz):
|
||||
attr = "%s%s"%(mode, loopXyz.upper())
|
||||
value = values[nnn][n][nnnn]
|
||||
|
||||
if len(frames) > 1:
|
||||
cmds.setKeyframe(loopSourceObj, attribute=attr, time=(loopKey,loopKey), value=value)
|
||||
|
||||
if currFrame == loopKey: cmds.setAttr("%s.%s"%(loopSourceObj, attr), value)
|
||||
|
||||
#euler filter
|
||||
if n == len(frames)-1 and rotate:
|
||||
animCurves = utilMod.mergeLists([cmds.keyframe(loopSourceObj, query=True, name=True) for loopSourceObj in sourceObjs])
|
||||
animMod.eulerFilterCurve(animCurves)
|
||||
|
||||
if showProgress: estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
|
||||
|
||||
if showProgress: utilMod.setProgressBar(endProgress=True)
|
||||
if selectSorceObjs: cmds.select(sourceObjs)
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
|
@ -0,0 +1,116 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
|
||||
class AnimationCopier(object):
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu()
|
||||
cmds.menuItem( label="Copy All Animation", command=lambda *args: self.copyAnimation(range="all"))
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem("onlySelectedNodesMenu", label="Paste To Selected", checkBox=False)
|
||||
cmds.menuItem( label="Paste Animation in Place", command=lambda *args: self.pasteAnimation(pasteInPlace=True))
|
||||
cmds.menuItem( label="Paste Original Animation", command=lambda *args: self.pasteAnimation(pasteInPlace=False))
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem( label="Paste To Another Character", command=self.remapNamespaces)
|
||||
|
||||
|
||||
def copyAnimation(self, range="selected", *args):
|
||||
cmds.waitCursor(state=True)
|
||||
|
||||
if range == "all":
|
||||
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
animData = animMod.getAnimData(animCurves, showProgress=True)
|
||||
else:
|
||||
animData = animMod.getAnimData(showProgress=True)
|
||||
|
||||
aToolsMod.saveInfoWithUser("copyPasteAnim", "animData", animData)
|
||||
|
||||
if cmds.window("remapNamespacesWindow", query=True, exists=True): self.remapNamespaces()
|
||||
|
||||
cmds.waitCursor(state=False)
|
||||
|
||||
def pasteAnimation(self, animData=None, pasteInPlace=True, onlySelectedNodes=None, *args):
|
||||
cmds.waitCursor(state=True)
|
||||
|
||||
if not onlySelectedNodes: onlySelectedNodes = cmds.menuItem("onlySelectedNodesMenu", query=True, checkBox=True)
|
||||
if not animData: animData = aToolsMod.loadInfoWithUser("copyPasteAnim", "animData")
|
||||
animMod.applyAnimData(animData, pasteInPlace, onlySelectedNodes, showProgress=True)
|
||||
|
||||
cmds.waitCursor(state=False)
|
||||
|
||||
def remapNamespaces(self, *args):
|
||||
winName = "remapNamespacesWindow"
|
||||
if cmds.window(winName, query=True, exists=True): cmds.deleteUI(winName)
|
||||
window = cmds.window( winName, title = "Remap Namespaces")
|
||||
|
||||
cmds.columnLayout(adjustableColumn=True)
|
||||
cmds.rowColumnLayout( numberOfColumns=3)
|
||||
|
||||
animData = aToolsMod.loadInfoWithUser("copyPasteAnim", "animData")
|
||||
inputNameSpaces = list(set(utilMod.getNameSpace(animData["objects"])[0]))
|
||||
outputNameSpaces = utilMod.listAllNamespaces()
|
||||
|
||||
for loopNameSpace in inputNameSpaces:
|
||||
|
||||
nameSpace = loopNameSpace[:-1]
|
||||
|
||||
eval("cmds.text('input%s', align='right', w=150, h=26, label='%s: ')"%(nameSpace, nameSpace))
|
||||
eval("cmds.textField('output%s', w=150, h=26, text='%s')"%(nameSpace, nameSpace))
|
||||
eval("cmds.button('output%s', w=26, h=26, label='...')"%(nameSpace))
|
||||
if outputNameSpaces:
|
||||
cmds.popupMenu(button=1)
|
||||
for loopOutput in outputNameSpaces:
|
||||
cmds.menuItem ("menu%s"%loopOutput, label=str(loopOutput), command=lambda x, loopOutput=loopOutput, nameSpace=nameSpace, *args: self.setOutputValue(loopOutput, nameSpace))
|
||||
|
||||
cmds.setParent( '..' )
|
||||
|
||||
|
||||
cmds.button(label="Paste Animation in Place", command=lambda *args: self.remapAndPasteAnimation(animData, inputNameSpaces, pasteInPlace=True))
|
||||
cmds.button(label="Paste Original Animation", command=lambda *args: self.remapAndPasteAnimation(animData, inputNameSpaces, pasteInPlace=False))
|
||||
|
||||
cmds.showWindow( window )
|
||||
|
||||
def setOutputValue(self, output, nameSpace):
|
||||
cmds.textField('output%s'%nameSpace, edit=True, text=str(output))
|
||||
|
||||
def remapAndPasteAnimation(self, animData, nameSpaces, pasteInPlace):
|
||||
|
||||
|
||||
separator = ":"
|
||||
|
||||
for loopNameSpace in nameSpaces:
|
||||
|
||||
nameSpace = loopNameSpace[:-1]
|
||||
|
||||
input = nameSpace
|
||||
output = cmds.textField('output%s'%nameSpace, query=True, text=True)
|
||||
|
||||
animStr = str(animData)
|
||||
animData = eval(animStr.replace("%s%s"%(input, separator), "%s%s"%(output, separator)))
|
||||
|
||||
self.pasteAnimation(animData, pasteInPlace)
|
||||
|
||||
|
@ -0,0 +1,236 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
|
||||
|
||||
class FakeConstrain(object):
|
||||
|
||||
def __init__(self):
|
||||
self.copyCache = []
|
||||
self.locators = []
|
||||
self.locatorGroup = ""
|
||||
self.locatorGroupName = "fakeConstrain_group"
|
||||
self.selection = None
|
||||
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu(postMenuCommand=self.populateMenu)
|
||||
|
||||
def populateMenu(self, menu, *args):
|
||||
|
||||
uiMod.clearMenuItems(menu)
|
||||
|
||||
if self.copyCache != []:
|
||||
cmds.menuItem(label='Copy', command=self.copy, parent=menu)
|
||||
cmds.menuItem(label='Paste to All Frames' , command=lambda *args: self.paste('allFrames'), parent=menu)
|
||||
cmds.menuItem(divider=True, parent=menu)
|
||||
|
||||
|
||||
cmds.menuItem(label='Copy Relative to World' , command=self.copyWorld, parent=menu)
|
||||
|
||||
def copyPaste(self):
|
||||
|
||||
if len(self.copyCache) > 0: self.paste()
|
||||
else: self.copy()
|
||||
|
||||
def copy(self, *args):
|
||||
#print "copy"
|
||||
self.selection = cmds.ls(selection=True)
|
||||
|
||||
if len(self.selection) < 1:
|
||||
cmds.warning("You need to select at least 2 objects.")
|
||||
return
|
||||
if len(self.selection) == 1:
|
||||
self.copyWorld()
|
||||
return
|
||||
|
||||
if len(self.selection) > 20:
|
||||
message = "Too many objects selected, continue?"
|
||||
confirm = cmds.confirmDialog( title='Confirm', message=message, button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No' )
|
||||
if confirm != 'Yes': return
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
self.flushCopyCache(force=True)
|
||||
self.scriptJob()
|
||||
|
||||
self.sourceObjs = self.selection[0:-1]
|
||||
self.targetObj = self.selection[-1]
|
||||
selObjects = utilMod.getNameSpace(self.selection)[1]
|
||||
self.locators = []
|
||||
|
||||
self.locatorGroup = animMod.group(name=self.locatorGroupName)
|
||||
G.aToolsBar.align.align([self.locatorGroup], self.targetObj)
|
||||
self.locators.append(self.locatorGroup)
|
||||
|
||||
|
||||
for loopObj in self.sourceObjs:
|
||||
|
||||
nameSpace = utilMod.getNameSpace([loopObj])
|
||||
loopSelName = "%s_%s"%(nameSpace[0][0], nameSpace[1][0])
|
||||
locatorName = "fakeConstrain_%s"%loopSelName
|
||||
|
||||
locator = animMod.createNull(locatorName)
|
||||
self.locators.append(locator)
|
||||
with G.aToolsBar.createAToolsNode: cmds.parent(locator, self.locatorGroup)
|
||||
G.aToolsBar.align.align([locator], loopObj)
|
||||
|
||||
matrix = cmds.xform(locator, query=True, matrix=True)
|
||||
|
||||
self.copyCache.append(matrix)
|
||||
|
||||
self.clearLocators()
|
||||
|
||||
cmds.select(self.selection)
|
||||
|
||||
cmds.iconTextButton("fakeConstrainBtn", edit=True, image= uiMod.getImagePath("specialTools_fake_constrain_active"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain_active copy"))
|
||||
|
||||
cmds.refresh(suspend=False)
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
def copyWorld(self, *args):
|
||||
#print "copyworld"
|
||||
self.selection = cmds.ls(selection=True)
|
||||
|
||||
if len(self.selection) < 1: return
|
||||
|
||||
if len(self.selection) > 20:
|
||||
message = "Too many objects selected, continue?"
|
||||
confirm = cmds.confirmDialog( title='Confirm', message=message, button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No' )
|
||||
if confirm != 'Yes': return
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
|
||||
self.flushCopyCache(force=True)
|
||||
self.scriptJob()
|
||||
|
||||
self.sourceObjs = self.selection
|
||||
self.targetObj = "world"
|
||||
|
||||
for loopObj in self.sourceObjs:
|
||||
matrix = cmds.xform(loopObj, query=True, ws=True, matrix=True)
|
||||
|
||||
self.copyCache.append(matrix)
|
||||
|
||||
|
||||
cmds.iconTextButton("fakeConstrainBtn", edit=True, image= uiMod.getImagePath("specialTools_fake_constrain_active"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain_active copy"))
|
||||
|
||||
cmds.refresh(suspend=False)
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
def paste(self, type="onlyKeys"):
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
selObjects = utilMod.getNameSpace(self.selection)[1]
|
||||
self.locators = []
|
||||
|
||||
if self.targetObj != "world":
|
||||
#CREATE
|
||||
self.locatorGroup = animMod.group(name=self.locatorGroupName)
|
||||
|
||||
for n, loopObj in enumerate(self.sourceObjs):
|
||||
|
||||
nameSpace = utilMod.getNameSpace([loopObj])
|
||||
loopSelName = "%s_%s"%(nameSpace[0][0], nameSpace[1][0])
|
||||
locatorName = "fakeConstrain_%s"%loopSelName
|
||||
|
||||
locator = animMod.createNull(locatorName)
|
||||
self.locators.append(locator)
|
||||
with G.aToolsBar.createAToolsNode: cmds.parent(locator, self.locatorGroup)
|
||||
|
||||
self.locators.append(self.locatorGroup)
|
||||
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
if animCurves:
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
keysSel = utilMod.mergeLists(keysSel)
|
||||
if keysSel == []:
|
||||
keysSel = [currFrame]
|
||||
else:
|
||||
keysSel = [currFrame]
|
||||
|
||||
frames = keysSel
|
||||
|
||||
if type == "allFrames":
|
||||
frameRange = animMod.getTimelineRange(float=False)
|
||||
frames = list(range(int(frameRange[0]),int(frameRange[1])))
|
||||
|
||||
if self.targetObj != "world":
|
||||
G.aToolsBar.align.align([self.locatorGroup], self.targetObj, frames=frames)
|
||||
|
||||
for n, loopObj in enumerate(self.sourceObjs):
|
||||
|
||||
matrix = self.copyCache[n]
|
||||
|
||||
if self.targetObj != "world":
|
||||
cmds.xform(self.locators[n], matrix=matrix)
|
||||
|
||||
G.aToolsBar.align.align([loopObj], self.locators[n], frames=frames, showProgress=True)
|
||||
|
||||
else:
|
||||
for loopFrame in frames:
|
||||
cmds.currentTime(loopFrame)
|
||||
cmds.xform(loopObj, ws=True, matrix=matrix)
|
||||
|
||||
cmds.currentTime(currFrame)
|
||||
|
||||
for loopFrame in frames:
|
||||
for loopAttr in ["translate", "rotate"]:
|
||||
breakdown = (loopFrame not in keysSel)
|
||||
cmds.keyframe(loopObj, edit=True, attribute=loopAttr, time=(loopFrame, loopFrame), breakdown=breakdown)
|
||||
|
||||
|
||||
if self.targetObj != "world":
|
||||
self.clearLocators()
|
||||
cmds.select(self.selection)
|
||||
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
|
||||
def clearLocators(self):
|
||||
|
||||
for loopLocator in self.locators:
|
||||
if cmds.objExists(loopLocator): cmds.delete(loopLocator)
|
||||
|
||||
if cmds.objExists(self.locatorGroup): cmds.delete(self.locatorGroup)
|
||||
|
||||
def flushCopyCache(self, force=False):
|
||||
|
||||
if not force and cmds.ls(selection=True) == self.selection:
|
||||
self.scriptJob()
|
||||
return
|
||||
|
||||
cmds.iconTextButton("fakeConstrainBtn", edit=True, image= uiMod.getImagePath("specialTools_fake_constrain"), highlightImage= uiMod.getImagePath("specialTools_fake_constrain copy"))
|
||||
|
||||
self.clearLocators()
|
||||
self.copyCache = []
|
||||
|
||||
def scriptJob(self):
|
||||
#scriptjob
|
||||
cmds.scriptJob(runOnce = True, killWithScene = True, event =('SelectionChanged', self.flushCopyCache))
|
||||
|
@ -0,0 +1,321 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
Modified: Michael Klimenko
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
import maya.OpenMaya as om
|
||||
|
||||
#============================================================================================================
|
||||
class MicroTransform(object):
|
||||
|
||||
utilMod.killScriptJobs("G.microTransformScriptJobs")
|
||||
|
||||
def __init__(self):
|
||||
|
||||
G.deferredManager.removeFromQueue("MT_blinking")
|
||||
|
||||
if G.aToolsBar.microTransform: return
|
||||
G.aToolsBar.microTransform = self
|
||||
|
||||
self.attributes = ['translate', 'translateX','translateY','translateZ','rotate', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scaleX','scaleY','scaleZ']
|
||||
|
||||
self.multiplierValues = [ {"name":"ultraSlow", "value":.05
|
||||
},{"name":"superSlow", "value":.2
|
||||
},{"name":"slow", "value":.5
|
||||
},{"name":"medium", "value":1
|
||||
}]
|
||||
self.defaultMultiplier = "slow"
|
||||
self.microTransformStartTimer = {}
|
||||
self.microTransformValues = {}
|
||||
self.onOff = False
|
||||
self.rotationOrientMode = cmds.manipRotateContext('Rotate', query=True, mode=True)
|
||||
|
||||
self.setMultiplier(self.getMultiplier())
|
||||
self.removeMicroTransform()
|
||||
self.blinkingButton(self.onOff)
|
||||
|
||||
|
||||
def blinkingButton(self, onOff):
|
||||
|
||||
if onOff: G.aToolsBar.timeoutInterval.setInterval(self.toggleButtonActive, .3, id="MT_blinking")
|
||||
else: G.aToolsBar.timeoutInterval.stopInterval("MT_blinking")
|
||||
|
||||
|
||||
def toggleButtonActive(self):
|
||||
onOff = "active" in cmds.iconTextButton("microTransformBtn", query=True, image=True)
|
||||
|
||||
self.setButtonImg(not onOff)
|
||||
|
||||
def setButtonImg(self, onOff):
|
||||
if onOff:
|
||||
cmds.iconTextButton("microTransformBtn", edit=True, image=uiMod.getImagePath("specialTools_micro_transform_active"), highlightImage= uiMod.getImagePath("specialTools_micro_transform_active"))
|
||||
else:
|
||||
cmds.iconTextButton("microTransformBtn", edit=True, image=uiMod.getImagePath("specialTools_micro_transform"), highlightImage= uiMod.getImagePath("specialTools_micro_transform copy"))
|
||||
|
||||
|
||||
def switch(self):
|
||||
|
||||
self.onOff = (not self.onOff)
|
||||
self.setButtonImg(self.onOff)
|
||||
self.blinkingButton(self.onOff)
|
||||
self.setMode(self.onOff)
|
||||
|
||||
|
||||
def setMode(self, onOff):
|
||||
|
||||
utilMod.killScriptJobs("G.microTransformScriptJobs")
|
||||
|
||||
if onOff:
|
||||
|
||||
self.rotationOrientMode = cmds.manipRotateContext('Rotate', query=True, mode=True)
|
||||
cmds.manipRotateContext('Rotate', edit=True, mode=2)#gimbal
|
||||
#update values on turning on
|
||||
self.addMicroTransform()
|
||||
|
||||
G.microTransformScriptJobs = []
|
||||
# get the current selected object values
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.addMicroTransform )))
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('timeChanged', self.updateValues )))
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('Undo', self.updateValues )))
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('Redo', self.updateValues )))
|
||||
G.microTransformScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('DragRelease', self.release )))
|
||||
|
||||
|
||||
|
||||
#print "microTransform is ON."
|
||||
|
||||
else:
|
||||
cmds.manipRotateContext('Rotate', edit=True, mode=self.rotationOrientMode)
|
||||
self.removeMicroTransform()
|
||||
#print "microTransform is OFF."
|
||||
|
||||
|
||||
def changedMicroTransform(self, msg, mplug, otherMplug, clientData):
|
||||
|
||||
#cmds.undoInfo(stateWithoutFlush=False)
|
||||
|
||||
|
||||
if om.MNodeMessage.kAttributeSet == (om.MNodeMessage.kAttributeSet & msg) and not om.MGlobal.isUndoing() and not om.MGlobal.isRedoing():
|
||||
nodeName, attrName = mplug.name().split('.')
|
||||
|
||||
#print "changed!"
|
||||
|
||||
if attrName not in self.attributes: return
|
||||
|
||||
nodeAttr = mplug.name()
|
||||
val = cmds.getAttr(nodeAttr)
|
||||
mtValue = self.microTransformValues["%s_%s"%(nodeName, attrName)]
|
||||
|
||||
if str(val) != str(mtValue):
|
||||
#timer
|
||||
if "%s"%nodeName not in self.microTransformStartTimer:
|
||||
self.microTransformStartTimer["%s"%nodeName] = cmds.timerX()
|
||||
microTransformTimer = cmds.timerX(startTime=self.microTransformStartTimer["%s"%nodeName])
|
||||
self.microTransformStartTimer["%s"%nodeName] = cmds.timerX()
|
||||
|
||||
microTransformTimer *= 50
|
||||
if microTransformTimer == 0: microTransformTimer = 1000
|
||||
mult = self.multiplier/microTransformTimer
|
||||
|
||||
|
||||
if mult >= self.multiplier: mult = self.multiplier
|
||||
|
||||
|
||||
self.undoChunkFn("open")
|
||||
#print "changedMicroTransform"
|
||||
|
||||
if type(val) is list:
|
||||
|
||||
temp = ()
|
||||
for n, loopVal in enumerate(val[0]):
|
||||
dif = loopVal-mtValue[0][n]
|
||||
temp = temp + (mtValue[0][n]+(dif*mult),)
|
||||
newVal = [temp]
|
||||
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName)] = newVal
|
||||
#xyz
|
||||
self.microTransformValues["%s_%sX"%(nodeName, attrName)] = newVal[0][0]
|
||||
self.microTransformValues["%s_%sY"%(nodeName, attrName)] = newVal[0][1]
|
||||
self.microTransformValues["%s_%sZ"%(nodeName, attrName)] = newVal[0][2]
|
||||
|
||||
eval("cmds.setAttr(nodeAttr, %s,%s,%s)"%(newVal[0][0],newVal[0][1],newVal[0][2]))
|
||||
#xyz
|
||||
cmds.setAttr("%sX"%nodeAttr, newVal[0][0])
|
||||
cmds.setAttr("%sY"%nodeAttr, newVal[0][1])
|
||||
cmds.setAttr("%sZ"%nodeAttr, newVal[0][2])
|
||||
|
||||
|
||||
else:
|
||||
dif = val-mtValue
|
||||
newVal = mtValue+(dif*mult)
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName)] = newVal
|
||||
|
||||
#xyz inverse
|
||||
val = cmds.getAttr("%s.%s"%(nodeName, attrName[:-1]))
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName[:-1])] = val
|
||||
|
||||
cmds.setAttr(nodeAttr, newVal)
|
||||
|
||||
|
||||
else:
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName)] = cmds.getAttr(nodeAttr)
|
||||
if type(val) is list:
|
||||
valX = cmds.getAttr("%s.%sX"%(nodeName, attrName))
|
||||
valY = cmds.getAttr("%s.%sY"%(nodeName, attrName))
|
||||
valZ = cmds.getAttr("%s.%sZ"%(nodeName, attrName))
|
||||
#xyz
|
||||
self.microTransformValues["%s_%sX"%(nodeName, attrName)] = valX
|
||||
self.microTransformValues["%s_%sY"%(nodeName, attrName)] = valY
|
||||
self.microTransformValues["%s_%sZ"%(nodeName, attrName)] = valZ
|
||||
|
||||
else:
|
||||
#xyz inverse
|
||||
val = cmds.getAttr("%s.%s"%(nodeName, attrName[:-1]))
|
||||
self.microTransformValues["%s_%s"%(nodeName, attrName[:-1])] = val
|
||||
|
||||
|
||||
#cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
def release(self):
|
||||
|
||||
self.undoChunkFn("close")
|
||||
self.updateValues()
|
||||
self.microTransformStartTimer = {}
|
||||
|
||||
|
||||
def undoChunkFn(self, openClose):
|
||||
if openClose == "open":
|
||||
if self.undoChunk == "closed":
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
self.undoChunk = "open"
|
||||
#print "openChunk"
|
||||
else:
|
||||
if self.undoChunk == "open":
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
self.undoChunk = "closed"
|
||||
#print "closeChunk"
|
||||
|
||||
def addMicroTransform(self):
|
||||
|
||||
self.updateValues()
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
|
||||
|
||||
sel = cmds.ls(selection=True)
|
||||
|
||||
if G.MT_lastSel:
|
||||
graphEditorFocus = cmds.getPanel(withFocus=True) == "graphEditor1"
|
||||
if sel == G.MT_lastSel and graphEditorFocus:
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
return
|
||||
|
||||
G.MT_lastSel = sel
|
||||
|
||||
if len(sel) <= 0:
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
return
|
||||
|
||||
self.removeMicroTransform()
|
||||
G.microTransformIds = []
|
||||
self.undoChunk = "closed"
|
||||
MSelectionList = om.MSelectionList()
|
||||
om.MGlobal.getActiveSelectionList(MSelectionList)
|
||||
node = om.MObject()
|
||||
|
||||
for n, loopSel in enumerate(sel):
|
||||
|
||||
MSelectionList.getDependNode(n, node)
|
||||
clientData = None
|
||||
G.microTransformIds.append(om.MNodeMessage.addAttributeChangedCallback(node, self.changedMicroTransform, clientData))
|
||||
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
|
||||
def removeMicroTransform(self):
|
||||
|
||||
try:
|
||||
for loopId in G.microTransformIds:
|
||||
om.MNodeMessage.removeCallback(loopId)
|
||||
except: pass
|
||||
|
||||
G.microTransformIds = None
|
||||
|
||||
|
||||
|
||||
|
||||
def updateValues(self):
|
||||
#print "updateValues"
|
||||
|
||||
self.microTransformValues = {}
|
||||
sel = cmds.ls(selection=True)
|
||||
|
||||
for loopSel in sel:
|
||||
for loopAttr in self.attributes:
|
||||
val = cmds.getAttr("%s.%s"%(loopSel, loopAttr))
|
||||
self.microTransformValues["%s_%s"%(loopSel, loopAttr)] = val
|
||||
|
||||
|
||||
def setMultiplier(self, option):
|
||||
name = None
|
||||
for loopOption in self.multiplierValues:
|
||||
if loopOption["name"] == option:
|
||||
value = loopOption["value"]
|
||||
name = loopOption["name"]
|
||||
|
||||
if not name: #in case file is corrupt
|
||||
self.setMultiplier(self.defaultMultiplier)
|
||||
return
|
||||
|
||||
self.multiplier = value
|
||||
aToolsMod.saveInfoWithUser("userPrefs", "microTransform", name)
|
||||
|
||||
def getMultiplier(self):
|
||||
name = aToolsMod.loadInfoWithUser("userPrefs", "microTransform")
|
||||
if name == None: name = self.defaultMultiplier
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def popupMenu(self, *args):
|
||||
menu = cmds.popupMenu()
|
||||
cmds.popupMenu(menu, edit=True, postMenuCommand=self.populateMenu, postMenuCommandOnce=True)
|
||||
|
||||
|
||||
def populateMenu(self, menu, *args):
|
||||
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
for loopOption in self.multiplierValues:
|
||||
radioSelected = (self.multiplier == loopOption["value"])
|
||||
option = loopOption["name"]
|
||||
cmds.menuItem (label=utilMod.toTitle(loopOption["name"]), radioButton=radioSelected, command=lambda x, option=option, *args: self.setMultiplier(option), parent=menu)
|
||||
|
||||
|
||||
|
@ -0,0 +1,319 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
class Mirror(object):
|
||||
|
||||
|
||||
utilMod.killScriptJobs("G.mirrorScriptJobs")
|
||||
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.INVERT_RULES_PREFS = [{ "name":"invertRulesMirrorObjsTranslateX",
|
||||
"default":True
|
||||
},{ "name":"invertRulesMirrorObjsTranslateY",
|
||||
"default":False
|
||||
},{ "name":"invertRulesMirrorObjsTranslateZ",
|
||||
"default":False
|
||||
},{ "name":"invertRulesMirrorObjsRotateX",
|
||||
"default":False
|
||||
},{ "name":"invertRulesMirrorObjsRotateY",
|
||||
"default":False
|
||||
},{ "name":"invertRulesMirrorObjsRotateZ",
|
||||
"default":False
|
||||
},{ "name":"invertRulesCenterObjsTranslateX",
|
||||
"default":True
|
||||
},{ "name":"invertRulesCenterObjsTranslateY",
|
||||
"default":False
|
||||
},{ "name":"invertRulesCenterObjsTranslateZ",
|
||||
"default":False
|
||||
},{ "name":"invertRulesCenterObjsRotateX",
|
||||
"default":False
|
||||
},{ "name":"invertRulesCenterObjsRotateY",
|
||||
"default":True
|
||||
},{ "name":"invertRulesCenterObjsRotateZ",
|
||||
"default":True
|
||||
}]
|
||||
|
||||
def start(self):
|
||||
mod = uiMod.getModKeyPressed()
|
||||
|
||||
if mod == "shift":
|
||||
self.selectMirrorObjs(True)
|
||||
elif mod == "ctrl":
|
||||
self.selectMirrorObjs(False)
|
||||
else:
|
||||
sel = cmds.ls(selection=True)
|
||||
if sel: self.applyMirror()
|
||||
else: self.toggleAutoSelectMirrorObjects()
|
||||
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu()
|
||||
cmds.menuItem("autoSelectMirrorObjectsMenu", label='Auto Select Mirror Objects' , checkBox=False, command=self.toggleAutoSelectMirrorObjects)
|
||||
cmds.menuItem("invertRulesMenu", subMenu=True, label='Invert Rules' , tearOff=True)
|
||||
for n, loopPref in enumerate(self.INVERT_RULES_PREFS):
|
||||
name = loopPref["name"]
|
||||
if n == 6: cmds.menuItem( divider=True )
|
||||
|
||||
cmds.menuItem('%sMenu'%name, label=utilMod.toTitle(name[11:]), command=lambda x, name=name, *args: aToolsMod.setPref(name, self.INVERT_RULES_PREFS), checkBox=aToolsMod.getPref(name, self.INVERT_RULES_PREFS))
|
||||
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem("loadDefaultsInvertRulesMenu", label="Load Defaults", command=lambda *args:utilMod.loadDefaultPrefs(self.INVERT_RULES_PREFS))
|
||||
cmds.setParent( '..', menu=True )
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem(label="Unselect Right", command=lambda *args: self.unselectMirrorObjs("right"))
|
||||
cmds.menuItem(label="Unselect Left", command=lambda *args: self.unselectMirrorObjs("left"))
|
||||
cmds.menuItem(label="Unselect Center", command=lambda *args: self.unselectMirrorObjs("center"))
|
||||
cmds.menuItem( divider=True )
|
||||
cmds.menuItem(label="Paste And Invert Cycle", command=lambda *args: self.applyMirror(pasteAndCycle=True))
|
||||
|
||||
|
||||
def toggleAutoSelectMirrorObjects(self, *args):
|
||||
|
||||
onOff = not cmds.menuItem("autoSelectMirrorObjectsMenu", query=True , checkBox=True)
|
||||
if args: onOff = not onOff #if checkbox pressed
|
||||
|
||||
if onOff: cmds.iconTextButton("mirrorBtn", edit=True, image=uiMod.getImagePath("specialTools_mirror_active"), highlightImage= uiMod.getImagePath("specialTools_mirror_active"))
|
||||
else: cmds.iconTextButton("mirrorBtn", edit=True, image=uiMod.getImagePath("specialTools_mirror"), highlightImage= uiMod.getImagePath("specialTools_mirror copy"))
|
||||
|
||||
self.setAutoSelectMirrorObjects(onOff)
|
||||
if not args:cmds.menuItem("autoSelectMirrorObjectsMenu", edit=True , checkBox=onOff)
|
||||
|
||||
|
||||
def setAutoSelectMirrorObjects(self, onOff):
|
||||
|
||||
utilMod.killScriptJobs("G.mirrorScriptJobs")
|
||||
|
||||
if onOff:
|
||||
self.autoSelectMirrorObjects()
|
||||
G.mirrorScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.autoSelectMirrorObjects )))
|
||||
|
||||
|
||||
|
||||
|
||||
def autoSelectMirrorObjects(self):
|
||||
sel = cmds.ls(selection=True)
|
||||
if sel: self.selectMirrorObjs(add=True, lastObj=sel[-1])
|
||||
|
||||
def getInvertRules(self):
|
||||
|
||||
invertRules = []
|
||||
|
||||
for loopPref in self.INVERT_RULES_PREFS:
|
||||
name = loopPref["name"]
|
||||
pref = aToolsMod.getPref(name, self.INVERT_RULES_PREFS)
|
||||
mode = name[11:]
|
||||
|
||||
if pref: invertRules.append(mode)
|
||||
|
||||
|
||||
return invertRules
|
||||
|
||||
def mirrorInvert(self, aCurve, isCenterCurve, invertRules):
|
||||
|
||||
transRot =["Translate", "Rotate"]
|
||||
modes = ["x", "y", "z"]
|
||||
value = 1
|
||||
|
||||
if isCenterCurve:
|
||||
objType = "Center"
|
||||
else:
|
||||
objType = "Mirror"
|
||||
|
||||
for loopRule in invertRules:
|
||||
for loopMode in modes:
|
||||
for loopTransRot in transRot:
|
||||
rule = "%sObjs%s%s"%(objType, loopTransRot, loopMode.title())
|
||||
|
||||
if loopRule == rule:
|
||||
if eval("animMod.isNode%s('%s', '%s')"%(loopTransRot, aCurve, loopMode)):
|
||||
value = -1
|
||||
|
||||
|
||||
return value
|
||||
|
||||
def unselectMirrorObjs(self, side):
|
||||
objects = animMod.getObjsSel()
|
||||
|
||||
if side == "center":
|
||||
objs = animMod.getMirrorObjs(objects, side="left")
|
||||
objects.extend(objs)
|
||||
objs.extend(animMod.getMirrorObjs(objects, side="right"))
|
||||
objects.extend(objs)
|
||||
objs.extend(animMod.getMirrorObjs(objects, side="left"))
|
||||
|
||||
centerObjs = [loopObj for loopObj in objects if loopObj not in objs and loopObj and cmds.objExists(loopObj)]
|
||||
|
||||
if len(centerObjs) >0: cmds.select(centerObjs, deselect=True)
|
||||
else:
|
||||
if side == "left": side = "right"
|
||||
elif side == "right": side = "left"
|
||||
objs = animMod.getMirrorObjs(objects, side=side)
|
||||
objs = [loopObj for loopObj in objs if loopObj and cmds.objExists(loopObj)]
|
||||
|
||||
if len(objs) > 0: cmds.select(objs, deselect=True)
|
||||
|
||||
def selectMirrorObjs(self, add, lastObj=None):
|
||||
objects = animMod.getObjsSel()
|
||||
mirrorObjs = animMod.getMirrorObjs(objects)
|
||||
sel = []
|
||||
|
||||
if mirrorObjs:
|
||||
for n, loopObj in enumerate(mirrorObjs):
|
||||
if loopObj:
|
||||
if cmds.objExists(loopObj): sel.append(loopObj)
|
||||
else:
|
||||
#central controller
|
||||
sel.append(objects[n])
|
||||
|
||||
if len(sel) >0:
|
||||
|
||||
if lastObj:
|
||||
cmds.select(sel, addFirst=add)
|
||||
else:
|
||||
cmds.select(sel, add=add)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def applyMirror(self, pasteAndCycle=False):
|
||||
|
||||
cmds.waitCursor(state=True)
|
||||
|
||||
range = animMod.getTimelineRange()
|
||||
range[1] = int(range[1])
|
||||
total = range[1]-range[0]
|
||||
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
invertRules = self.getInvertRules()
|
||||
|
||||
if animCurves:
|
||||
status = "aTools - Applying mirror..."
|
||||
utilMod.startProgressBar(status)
|
||||
totalSteps = len(animCurves)
|
||||
firstStep = 0
|
||||
thisStep = 0
|
||||
estimatedTime = None
|
||||
startChrono = None
|
||||
|
||||
mirrorCurves = animMod.getMirrorObjs(animCurves)
|
||||
keyValues = animMod.getTarget("keyValues", animCurves, getFrom)
|
||||
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
|
||||
currValues = animMod.getTarget("currValues", animCurves, getFrom)
|
||||
keysIndexSel = animMod.getTarget("keysIndexSel", animCurves, getFrom)
|
||||
keyTangentsAngle = animMod.getTarget("keyTangentsAngle", animCurves, getFrom)
|
||||
keyTangentsType = animMod.getTarget("keyTangentsType", animCurves, getFrom)
|
||||
currTime = cmds.currentTime(query=True)
|
||||
|
||||
|
||||
|
||||
if keysIndexSel:
|
||||
|
||||
#create dummy key
|
||||
#objects = animMod.getObjsSel()
|
||||
#mirrorObjs = animMod.getMirrorObjs(objects)
|
||||
#animMod.createDummyKey(mirrorObjs)
|
||||
|
||||
for thisStep, aCurve in enumerate(animCurves):
|
||||
|
||||
startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status)
|
||||
|
||||
mCurve = mirrorCurves[thisStep]
|
||||
isCenterCurve = (mCurve == None)
|
||||
mirrorInvertValue = self.mirrorInvert(aCurve, isCenterCurve, invertRules)
|
||||
if mCurve and cmds.objExists(mCurve):
|
||||
tCurve = mCurve
|
||||
else:
|
||||
tCurve = aCurve
|
||||
|
||||
if not cmds.objExists(tCurve): continue
|
||||
|
||||
|
||||
animMod.createDummyKey([tCurve])
|
||||
|
||||
if len(keysIndexSel[thisStep]) > 0:
|
||||
#delete keys
|
||||
cmds.cutKey(tCurve, time=(keyTimes[thisStep][keysIndexSel[thisStep][0]],keyTimes[thisStep][keysIndexSel[thisStep][-1]]), clear=True)
|
||||
|
||||
for key in keysIndexSel[thisStep]:
|
||||
keyValue = keyValues[thisStep][key] * mirrorInvertValue
|
||||
inTangAngleValue = keyTangentsAngle[thisStep][key][0] * mirrorInvertValue
|
||||
outTangAngleValue = keyTangentsAngle[thisStep][key][1] * mirrorInvertValue
|
||||
|
||||
|
||||
#apply keys
|
||||
if pasteAndCycle:
|
||||
t = keyTimes[thisStep][key] + (total/2.)
|
||||
|
||||
if t == range[1]:
|
||||
#repeat key at first frame
|
||||
t1 = t-total
|
||||
time = (t1,t1)
|
||||
cmds.setKeyframe(tCurve, time=time, value=keyValue)
|
||||
cmds.keyTangent(tCurve, time=time, inAngle=inTangAngleValue, outAngle=outTangAngleValue)
|
||||
cmds.keyTangent(tCurve, time=time, inTangentType=keyTangentsType[thisStep][key][0], outTangentType=keyTangentsType[thisStep][key][1])
|
||||
|
||||
elif t > range[1]:
|
||||
#fist half
|
||||
t -= total
|
||||
|
||||
time = (t,t)
|
||||
|
||||
|
||||
|
||||
else:
|
||||
time = (keyTimes[thisStep][key],keyTimes[thisStep][key])
|
||||
|
||||
|
||||
|
||||
cmds.setKeyframe(tCurve, time=time, value=keyValue)
|
||||
cmds.keyTangent(tCurve, time=time, inAngle=inTangAngleValue, outAngle=outTangAngleValue)
|
||||
cmds.keyTangent(tCurve, time=time, inTangentType=keyTangentsType[thisStep][key][0], outTangentType=keyTangentsType[thisStep][key][1])
|
||||
else: #no keys#invert translate x
|
||||
keyValue = currValues[thisStep] * mirrorInvertValue
|
||||
|
||||
|
||||
#apply keys
|
||||
cmds.setKeyframe(tCurve, time=(currTime,currTime), value=keyValue)
|
||||
|
||||
animMod.deleteDummyKey([tCurve])
|
||||
|
||||
estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps)
|
||||
|
||||
|
||||
#delete dummy key
|
||||
#animMod.deleteDummyKey(mirrorObjs)
|
||||
|
||||
self.selectMirrorObjs(False)
|
||||
utilMod.setProgressBar(endProgress=True)
|
||||
|
||||
animMod.refresh()
|
||||
cmds.waitCursor(state=False)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,303 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
Modified: Michael Klimenko
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
class SpaceSwitch(object):
|
||||
|
||||
def popupMenu(self):
|
||||
cmds.popupMenu(postMenuCommand=self.populateMenu, button=1)
|
||||
|
||||
def populateMenu(self, menu, *args):
|
||||
|
||||
uiMod.clearMenuItems(menu)
|
||||
|
||||
tokenCustomDivider = False
|
||||
selObjects = cmds.ls(selection=True)
|
||||
|
||||
if not selObjects: return
|
||||
|
||||
channels = animMod.getAllChannels()
|
||||
channelList = {}
|
||||
tokenList = []
|
||||
|
||||
for n, loopObjectChannel in enumerate(channels):
|
||||
obj = selObjects[n]
|
||||
if loopObjectChannel:
|
||||
for loopChannel in loopObjectChannel:
|
||||
tokens = animMod.getTokens(obj, loopChannel)
|
||||
if tokens and len(tokens) > 1:
|
||||
if loopChannel not in channelList: channelList[loopChannel] = {"objects":[], "tokens":[]}
|
||||
channelList[loopChannel]["objects"].append(obj)
|
||||
channelList[loopChannel]["tokens"].append(tokens)
|
||||
|
||||
|
||||
for loopChannelList in channelList:
|
||||
newMenu = cmds.menuItem(subMenu=True, label=utilMod.toTitle(loopChannelList), parent=menu)
|
||||
objects = channelList[loopChannelList]["objects"]
|
||||
tokens = channelList[loopChannelList]["tokens"]
|
||||
mergedTokens = utilMod.mergeLists(tokens)
|
||||
tokenDict = []
|
||||
|
||||
for loopMergedTokens in mergedTokens:
|
||||
tokenDict.append({"token":loopMergedTokens, "objects":[]})
|
||||
for n, loopObject in enumerate(objects):
|
||||
t = tokens[n]
|
||||
if loopMergedTokens in t:
|
||||
tokenDict[-1]["objects"].append(loopObject)
|
||||
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
|
||||
for n, loopTokenDict in enumerate(tokenDict):
|
||||
tokenCustomDivider = True
|
||||
token = loopTokenDict["token"]
|
||||
objects = loopTokenDict["objects"]
|
||||
selectedList = [cmds.getAttr("%s.%s"%(loopObj, loopChannelList)) for loopObj in objects]
|
||||
radioSelected = False
|
||||
|
||||
|
||||
if len(set(selectedList)) == 1:
|
||||
if selectedList[0] == n:
|
||||
radioSelected = True
|
||||
|
||||
cmds.menuItem(label=utilMod.toTitle(token), radioButton=radioSelected, parent=newMenu, command=lambda x, objects=objects, channel=loopChannelList, token=token, *args:self.spaceSwitch([objects, channel, token]))
|
||||
|
||||
|
||||
#ALL KEYS
|
||||
cmds.menuItem( divider=True, parent=newMenu)
|
||||
newMenu = cmds.menuItem(subMenu=True, label='All Keys', parent=newMenu)
|
||||
|
||||
cmds.radioMenuItemCollection(parent=newMenu)
|
||||
|
||||
for n, loopTokenDict in enumerate(tokenDict):
|
||||
token = loopTokenDict["token"]
|
||||
objects = loopTokenDict["objects"]
|
||||
selectedList = [cmds.getAttr("%s.%s"%(loopObj, loopChannelList)) for loopObj in objects]
|
||||
radioSelected = False
|
||||
|
||||
if len(set(selectedList)) == 1:
|
||||
if selectedList[0] == n:
|
||||
radioSelected = True
|
||||
|
||||
cmds.menuItem(label=utilMod.toTitle(token), radioButton=radioSelected, parent=newMenu, command=lambda x, objects=objects, channel=loopChannelList, token=token, *args:self.spaceSwitch([objects, channel, token], all=True))
|
||||
|
||||
# CUSTOM SWITCH
|
||||
allCustomSwitch = aToolsMod.loadInfoWithUser("spaceSwitch", "customSwitch") or []
|
||||
channelboxSelObjs = animMod.channelBoxSel()
|
||||
|
||||
if channelboxSelObjs:
|
||||
obj = ".".join(channelboxSelObjs[0].split(".")[:-1])
|
||||
selectedSwitch = [loopAttr.split(".")[-1] for loopAttr in channelboxSelObjs if utilMod.isDynamic(obj, loopAttr.split(".")[-1])]
|
||||
if len(selectedSwitch) > 0 and selectedSwitch not in allCustomSwitch:
|
||||
allCustomSwitch.append(selectedSwitch)
|
||||
aToolsMod.saveInfoWithUser("spaceSwitch", "customSwitch", allCustomSwitch)
|
||||
|
||||
|
||||
# populate menu
|
||||
if len(allCustomSwitch) > 0:
|
||||
|
||||
divider = False
|
||||
customSwitchesAdded = []
|
||||
customSwitchesMenu = []
|
||||
|
||||
for loopObj in selObjects:
|
||||
|
||||
for loopCustomSwitch in sorted(allCustomSwitch, key=len, reverse=True):
|
||||
|
||||
if len(loopCustomSwitch) == 0: continue
|
||||
|
||||
switchName = utilMod.getNameSpace([loopObj])[1][0].split(".")[0]
|
||||
exit = False
|
||||
|
||||
for loopAttr in loopCustomSwitch:
|
||||
objAttr = "%s.%s"%(loopObj, loopAttr)
|
||||
if not cmds.objExists(objAttr):
|
||||
exit = True
|
||||
break
|
||||
|
||||
if exit: continue
|
||||
|
||||
customSwitchesMenu.append({"objects":[loopObj], "switches":loopCustomSwitch})
|
||||
|
||||
for loopMenu in customSwitchesMenu[:-1]:
|
||||
if loopObj in loopMenu["objects"] and len(loopCustomSwitch) < len(loopMenu["switches"]) and utilMod.listIntersection(loopMenu["switches"], loopCustomSwitch) == loopCustomSwitch:
|
||||
customSwitchesMenu.pop()
|
||||
break
|
||||
if loopCustomSwitch == loopMenu["switches"]:
|
||||
loopMenu["objects"].append(loopObj)
|
||||
customSwitchesMenu.pop()
|
||||
break
|
||||
|
||||
|
||||
for loopSwitchMenu in customSwitchesMenu:
|
||||
|
||||
objects = loopSwitchMenu["objects"]
|
||||
switches = loopSwitchMenu["switches"]
|
||||
switchName = ", ".join(list(set(utilMod.getNameSpace(objects)[1])))
|
||||
|
||||
if not divider and tokenCustomDivider: divider = cmds.menuItem(divider=True, parent=menu)
|
||||
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
|
||||
newMenu = cmds.menuItem(subMenu=True, label=switchName, parent=menu)
|
||||
radioSelected = []
|
||||
|
||||
for loopCustomSwitchAttr in switches:
|
||||
switchAttr = loopCustomSwitchAttr.split(".")[-1]
|
||||
objAttr = "%s.%s"%(objects[0], switchAttr)
|
||||
minValue = cmds.addAttr(objAttr, query=True, minValue=True)
|
||||
maxValue = cmds.addAttr(objAttr, query=True, maxValue=True)
|
||||
currValue = cmds.getAttr(objAttr)
|
||||
radioSelected.append((currValue == maxValue))
|
||||
|
||||
cmds.menuItem(label=switchAttr, radioButton=radioSelected[-1], parent=newMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], mode="custom"))
|
||||
|
||||
switchAttr = "message"
|
||||
radioSelected = (list(set(radioSelected)) == [False])
|
||||
cmds.menuItem(label="None", radioButton=radioSelected, parent=newMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], mode="custom"))
|
||||
|
||||
#ALL KEYS
|
||||
|
||||
cmds.menuItem( divider=True, parent=newMenu)
|
||||
allMenu = cmds.menuItem(subMenu=True, label='All Keys', parent=newMenu)
|
||||
radioSelected = []
|
||||
cmds.radioMenuItemCollection(parent=menu)
|
||||
|
||||
|
||||
for loopCustomSwitchAttr in switches:
|
||||
switchAttr = loopCustomSwitchAttr.split(".")[-1]
|
||||
objAttr = "%s.%s"%(objects[0], switchAttr)
|
||||
minValue = cmds.addAttr(objAttr, query=True, minValue=True)
|
||||
maxValue = cmds.addAttr(objAttr, query=True, maxValue=True)
|
||||
currValue = cmds.getAttr(objAttr)
|
||||
radioSelected.append((currValue == maxValue))
|
||||
cmds.menuItem(label=switchAttr, radioButton=radioSelected[-1], parent=allMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], all=True, mode="custom"))
|
||||
|
||||
switchAttr = "message"
|
||||
radioSelected = (list(set(radioSelected)) == [False])
|
||||
cmds.menuItem(label="None", radioButton=radioSelected, parent=allMenu, command=lambda x, objects=objects, switchAttr=switchAttr, switches=switches, *args:self.spaceSwitch([objects, switchAttr, switches], all=True, mode="custom"))
|
||||
|
||||
#DELETE
|
||||
|
||||
cmds.menuItem(label="Remove", parent=newMenu, command=lambda x, switches=switches, *args:self.removeCustomSwitch(switches))
|
||||
|
||||
def removeCustomSwitch(self, switch):
|
||||
allCustomSwitch = aToolsMod.loadInfoWithUser("spaceSwitch", "customSwitch") or []
|
||||
|
||||
allCustomSwitch.remove(switch)
|
||||
aToolsMod.saveInfoWithUser("spaceSwitch", "customSwitch", allCustomSwitch)
|
||||
|
||||
def spaceSwitch(self, args, all=False, mode="token"):
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
if mode == "token": switch = self.spaceSwitchToken
|
||||
elif mode == "custom": switch = self.spaceSwitchCustom
|
||||
|
||||
objects = args[0]
|
||||
attr = args[1]
|
||||
currSel = cmds.ls(selection=True)
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
if animCurves:
|
||||
if all: keysSel = animMod.getTarget("keyTimes", animCurves, getFrom)
|
||||
else: keysSel = animMod.getTarget("keysSel", animCurves, getFrom)
|
||||
|
||||
keysSel = utilMod.mergeLists(keysSel)
|
||||
if keysSel == []:
|
||||
keysSel = [currFrame]
|
||||
else:
|
||||
keysSel = [currFrame]
|
||||
|
||||
frames = keysSel
|
||||
|
||||
for loopObj in currSel:
|
||||
if loopObj not in objects: continue
|
||||
if not cmds.objExists("%s.%s"%(loopObj, attr)):continue
|
||||
|
||||
animMod.createDummyKey([loopObj])
|
||||
|
||||
getCurves = animMod.getAnimCurves(True)
|
||||
animCurves = getCurves[0]
|
||||
|
||||
animMod.deleteDummyKey([loopObj])
|
||||
|
||||
for loopFrame in frames:
|
||||
cmds.currentTime(loopFrame)
|
||||
|
||||
matrix = cmds.xform(loopObj, query=True, ws=True, matrix=True)
|
||||
rotation = cmds.xform(loopObj, query=True, ws=True, rotation=True)
|
||||
|
||||
switch(loopObj, args)
|
||||
cmds.xform(loopObj, ws=True, matrix=matrix)
|
||||
cmds.xform(loopObj, ws=True, rotation=rotation)
|
||||
|
||||
|
||||
animMod.eulerFilterCurve(animCurves)
|
||||
|
||||
|
||||
cmds.currentTime(currFrame)
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
def spaceSwitchCustom(self, obj, args):
|
||||
|
||||
objects, attr, switchAttList = args
|
||||
objAttr = "%s.%s"%(obj, attr)
|
||||
|
||||
for loopAttr in switchAttList:
|
||||
|
||||
loopObjAttr = "%s.%s"%(obj, loopAttr)
|
||||
minValue = cmds.addAttr(loopObjAttr, query=True, minValue=True)
|
||||
maxValue = cmds.addAttr(loopObjAttr, query=True, maxValue=True)
|
||||
value = minValue if objAttr != loopObjAttr else maxValue
|
||||
|
||||
cmds.setAttr(loopObjAttr, value)
|
||||
|
||||
def spaceSwitchToken(self, obj, args):
|
||||
|
||||
objects, attr, switchTo = args
|
||||
enumTokens = animMod.getTokens(obj, attr)
|
||||
value = 0
|
||||
switchToNum = None
|
||||
|
||||
for loopToken in enumTokens:
|
||||
splitValue = loopToken.split("=")
|
||||
|
||||
if splitValue:
|
||||
if len(splitValue) > 1:
|
||||
loopToken = splitValue[0]
|
||||
value = eval(splitValue[1])
|
||||
|
||||
|
||||
if switchTo == loopToken:
|
||||
switchToNum = value
|
||||
break
|
||||
|
||||
value += 1
|
||||
|
||||
|
||||
if switchToNum != None:
|
||||
cmds.setAttr("%s.%s"%(obj, attr), switchToNum)
|
||||
|
@ -0,0 +1,189 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
from aTools.commonMods import aToolsMod
|
||||
|
||||
import maya.OpenMaya as om
|
||||
|
||||
#============================================================================================================
|
||||
class TempCustomPivot(object):
|
||||
|
||||
def __init__(self):
|
||||
self.STORE_NODE = "tempCustomPivot"
|
||||
self.CONSTRAINTS = "constraintObjects"
|
||||
self.LOCATORS = "locatorObjects"
|
||||
self.CTRLS = "ctrlsObjects"
|
||||
self.CURRENTFRAME = "currentFrame"
|
||||
self.sel = []
|
||||
self.deniedCtx = ["dragAttrContext", "manipMoveContext", "manipRotateContext", "manipScaleContext"]
|
||||
|
||||
self.clear()
|
||||
|
||||
def popupMenu(self, *args):
|
||||
cmds.popupMenu()
|
||||
cmds.menuItem(label="Clear temporary custom pivots", command=self.clear)
|
||||
|
||||
|
||||
def create(self, *args):
|
||||
|
||||
|
||||
img = cmds.iconTextButton("TempCustomPivotBtn", query=True, image=True)
|
||||
onOff = (img[-10:-4] == "active")
|
||||
if onOff:
|
||||
self.clear()
|
||||
cmds.select(self.sel)
|
||||
return
|
||||
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
|
||||
self.clear()
|
||||
|
||||
|
||||
getCurves = animMod.getAnimCurves()
|
||||
animCurves = getCurves[0]
|
||||
getFrom = getCurves[1]
|
||||
|
||||
if animCurves:
|
||||
keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom)
|
||||
|
||||
self.sel = cmds.ls(selection=True)
|
||||
if not self.sel: return
|
||||
|
||||
cmds.iconTextButton("TempCustomPivotBtn", edit=True, image= uiMod.getImagePath("specialTools_create_temp_custom_pivot_active"), highlightImage= uiMod.getImagePath("specialTools_create_temp_custom_pivot_active"))
|
||||
|
||||
targetObj = self.sel[-1]
|
||||
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.CTRLS, self.sel)
|
||||
|
||||
currentFrame = cmds.currentTime(query=True)
|
||||
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.CURRENTFRAME, currentFrame)
|
||||
|
||||
locators = []
|
||||
for loopSel in self.sel:
|
||||
nameSpace = utilMod.getNameSpace([loopSel])
|
||||
loopSelName = "%s_%s"%(nameSpace[0][0], nameSpace[1][0])
|
||||
locatorName = "tempCustomPivot_%s"%loopSelName
|
||||
|
||||
locator = animMod.createNull(locatorName)
|
||||
locators.append(locator)
|
||||
|
||||
G.aToolsBar.align.align([locator], loopSel)
|
||||
|
||||
|
||||
locatorGroup = "tempCustomPivot_group"
|
||||
animMod.group(name=locatorGroup)
|
||||
G.aToolsBar.align.align([locatorGroup], targetObj)
|
||||
with G.aToolsBar.createAToolsNode: cmds.parent(locators, locatorGroup)
|
||||
cmds.select(locatorGroup, replace=True)
|
||||
|
||||
locators.append(locatorGroup)
|
||||
|
||||
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.LOCATORS, locators)
|
||||
|
||||
#parent ctrls to locator
|
||||
constraints = ["%s_tempCustomPivot_constraint"%loopConstraint for loopConstraint in self.sel]
|
||||
|
||||
aToolsMod.saveInfoWithScene(self.STORE_NODE, self.CONSTRAINTS, constraints)
|
||||
|
||||
for n, loopSel in enumerate(self.sel):
|
||||
with G.aToolsBar.createAToolsNode: cmds.parentConstraint(locators[n], loopSel, name=constraints[n], maintainOffset=True)
|
||||
constraintNode = "%s.blendParent1"%loopSel
|
||||
if not cmds.objExists(constraintNode): continue
|
||||
cmds.setKeyframe(constraintNode)
|
||||
if keyTimes:
|
||||
for loopTime in keyTimes[0]:
|
||||
cmds.setKeyframe("%s.tx"%locatorGroup, time=(loopTime,loopTime))
|
||||
if loopTime != currentFrame:
|
||||
cmds.setKeyframe(constraintNode, time=(loopTime,loopTime), value=0)
|
||||
|
||||
#enter edit mode
|
||||
cmds.setToolTo(cmds.currentCtx())
|
||||
cmds.ctxEditMode()
|
||||
|
||||
#scriptjob
|
||||
cmds.scriptJob(runOnce = True, killWithScene = True, event =('SelectionChanged', self.scriptJob_SelectionChanged))
|
||||
|
||||
def scriptJob_SelectionChanged(self):
|
||||
self.clear()
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
|
||||
def clear(self, *args):
|
||||
|
||||
|
||||
if cmds.iconTextButton("TempCustomPivotBtn", query=True, exists=True):
|
||||
cmds.iconTextButton("TempCustomPivotBtn", edit=True, image= uiMod.getImagePath("specialTools_create_temp_custom_pivot"), highlightImage= uiMod.getImagePath("specialTools_create_temp_custom_pivot copy"))
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
currFrame = cmds.currentTime(query=True)
|
||||
|
||||
loadConstraints = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.CONSTRAINTS)
|
||||
loadLocators = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.LOCATORS)
|
||||
loadCtrls = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.CTRLS)
|
||||
currentFrame = aToolsMod.loadInfoWithScene(self.STORE_NODE, self.CURRENTFRAME)
|
||||
|
||||
#exit edit mode
|
||||
|
||||
if cmds.currentCtx() not in self.deniedCtx: cmds.setToolTo(cmds.currentCtx())
|
||||
|
||||
|
||||
if currentFrame:
|
||||
cmds.currentTime(eval(currentFrame))
|
||||
|
||||
#get values
|
||||
"""
|
||||
translation = []
|
||||
rotation = []
|
||||
if loadCtrls:
|
||||
ctrlObjs = eval(loadCtrls)
|
||||
for loopCtrl in ctrlObjs:
|
||||
translation.append(cmds.xform(loopCtrl, query=True, ws=True, rotatePivot=True))
|
||||
rotation.append(cmds.xform(loopCtrl, query=True, ws=True, rotation=True))
|
||||
"""
|
||||
|
||||
|
||||
if loadConstraints:
|
||||
constraintObjs = eval(loadConstraints)
|
||||
for loopConstraint in constraintObjs:
|
||||
if cmds.objExists(loopConstraint): cmds.delete(loopConstraint)
|
||||
|
||||
if loadCtrls and loadLocators:
|
||||
locatorObjs = eval(loadLocators)
|
||||
ctrlObjs = eval(loadCtrls)
|
||||
for n, loopCtrl in enumerate(ctrlObjs):
|
||||
if cmds.objExists(loopCtrl) and cmds.objExists(locatorObjs[n]):
|
||||
G.aToolsBar.align.align([loopCtrl], locatorObjs[n])
|
||||
|
||||
for loopLocator in locatorObjs:
|
||||
if cmds.objExists(loopLocator): cmds.delete(loopLocator)
|
||||
|
||||
cmds.currentTime(currFrame)
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,347 @@
|
||||
'''
|
||||
========================================================================================================================
|
||||
Author: Alan Camilo
|
||||
www.alancamilo.com
|
||||
Modified: Michael Klimenko
|
||||
|
||||
Requirements: aTools Package
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To install aTools, please follow the instructions in the file how_to_install.txt
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
To unistall aTools, go to menu (the last button on the right), Uninstall
|
||||
|
||||
========================================================================================================================
|
||||
'''
|
||||
|
||||
from maya import cmds
|
||||
from maya import mel
|
||||
from maya import OpenMaya
|
||||
from maya import OpenMayaAnim
|
||||
from aTools.generalTools.aToolsGlobals import aToolsGlobals as G
|
||||
from aTools.commonMods import uiMod
|
||||
from aTools.commonMods import utilMod
|
||||
from aTools.commonMods import animMod
|
||||
|
||||
|
||||
class TransformAll(object):
|
||||
|
||||
utilMod.killScriptJobs("G.transformAllScriptJobs")
|
||||
|
||||
def __init__(self):
|
||||
|
||||
G.deferredManager.removeFromQueue("transformAll")
|
||||
G.deferredManager.removeFromQueue("TA_blinking")
|
||||
|
||||
if G.aToolsBar.transformAll: return
|
||||
G.aToolsBar.transformAll = self
|
||||
|
||||
self.currentValues = {}
|
||||
self.allValues = {}
|
||||
self.range = None
|
||||
self.onOff = False
|
||||
self.blendRangeMode = False
|
||||
self.blendImg = ""
|
||||
G.TA_messages = G.TA_messages or {"anim":[], "node":[], "scene":[]}
|
||||
|
||||
self.killJobs()
|
||||
|
||||
def blinkingButton(self, onOff):
|
||||
|
||||
if onOff: G.aToolsBar.timeoutInterval.setInterval(self.toggleButtonActive, .3, id="TA_blinking")
|
||||
else: G.aToolsBar.timeoutInterval.stopInterval("TA_blinking")
|
||||
|
||||
|
||||
def toggleButtonActive(self):
|
||||
onOff = "active" in cmds.iconTextButton("transformAllBtn", query=True, image=True)
|
||||
|
||||
self.setButtonImg(not onOff)
|
||||
|
||||
def popupMenu(self, *args):
|
||||
|
||||
cmds.popupMenu ()
|
||||
cmds.menuItem ("blendRangeModeMenu", label="Blend Range Mode", checkBox=self.blendRangeMode, command=self.setBlendRangeMode)
|
||||
|
||||
def setBlendRangeMode(self, *args):
|
||||
self.blendRangeMode = args[0]
|
||||
if self.blendRangeMode: self.blendImg = "_blend"
|
||||
else: self.blendImg = ""
|
||||
|
||||
self.setButtonImg(self.onOff)
|
||||
self.warn()
|
||||
|
||||
def setButtonImg(self, onOff):
|
||||
if onOff:
|
||||
cmds.iconTextButton("transformAllBtn", edit=True, image=uiMod.getImagePath("specialTools_transform_all%s_active"%self.blendImg), highlightImage= uiMod.getImagePath("specialTools_transform_all%s_active"%self.blendImg))
|
||||
else:
|
||||
cmds.iconTextButton("transformAllBtn", edit=True, image=uiMod.getImagePath("specialTools_transform_all%s"%self.blendImg), highlightImage= uiMod.getImagePath("specialTools_transform_all%s copy"%self.blendImg))
|
||||
|
||||
|
||||
def switch(self):
|
||||
|
||||
mod = uiMod.getModKeyPressed()
|
||||
|
||||
if mod == "ctrl":
|
||||
self.setBlendRangeMode(not self.blendRangeMode)
|
||||
if self.onOff: self.onOff = False
|
||||
|
||||
|
||||
self.onOff = (not self.onOff)
|
||||
self.setButtonImg(self.onOff)
|
||||
self.blinkingButton(self.onOff)
|
||||
|
||||
self.setMode(self.onOff)
|
||||
|
||||
def killJobs(self):
|
||||
G.deferredManager.removeFromQueue("transformAll")
|
||||
self.animCurvesToSend = []
|
||||
self.removeMessages()
|
||||
utilMod.killScriptJobs("G.transformAllScriptJobs")
|
||||
|
||||
|
||||
def setMode(self, onOff):
|
||||
|
||||
self.killJobs()
|
||||
|
||||
if onOff:
|
||||
|
||||
#self.allAnimCurves = utilMod.getAllAnimCurves()
|
||||
self.allValues = {}
|
||||
self.setRange()
|
||||
self.updateCurrentValues()
|
||||
utilMod.deselectTimelineRange()
|
||||
|
||||
G.transformAllScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('timeChanged', self.updateCurrentValues )))
|
||||
G.transformAllScriptJobs.append(cmds.scriptJob(runOnce = False, killWithScene = False, event =('SelectionChanged', self.updateCurrentValues )))
|
||||
|
||||
self.warn()
|
||||
|
||||
|
||||
else:
|
||||
cmds.warning("Transform All is OFF.")
|
||||
|
||||
def addAnimMessages(self):
|
||||
|
||||
self.removeMessages()
|
||||
G.TA_messages["anim"].append(OpenMayaAnim.MAnimMessage.addAnimCurveEditedCallback(self.sendToSetValues))
|
||||
|
||||
|
||||
def removeMessages(self):
|
||||
|
||||
try:
|
||||
for loopId in G.TA_messages["anim"]:
|
||||
OpenMayaAnim.MAnimMessage.removeCallback(loopId)
|
||||
except: pass
|
||||
|
||||
G.TA_messages["anim"] = []
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def sendToSetValues(self, *args):
|
||||
|
||||
curveMsg = args[0]
|
||||
animCurves = [OpenMaya.MFnDependencyNode(curveMsg[n]).name() for n in range(curveMsg.length())]
|
||||
|
||||
if OpenMaya.MGlobal.isUndoing() or OpenMaya.MGlobal.isRedoing():
|
||||
self.updateCurrentValues(animCurves)
|
||||
return
|
||||
|
||||
self.animCurvesToSend.extend(animCurves)
|
||||
|
||||
|
||||
animCurves = list(set(self.animCurvesToSend))
|
||||
|
||||
G.deferredManager.removeFromQueue("transformAll")
|
||||
function = lambda *args:self.setValues(animCurves)
|
||||
G.deferredManager.sendToQueue(function, 1, "transformAll")
|
||||
|
||||
|
||||
def getRange(self):
|
||||
|
||||
animCurves = cmds.keyframe(query=True, name=True, selected=True)
|
||||
|
||||
if animCurves:
|
||||
|
||||
keysSel = animMod.getTarget("keysSel", animCurves, "graphEditor")
|
||||
keysSel = utilMod.mergeLists(keysSel)
|
||||
range = [min(keysSel), max(keysSel)]
|
||||
|
||||
else:
|
||||
G.playBackSliderPython = G.playBackSliderPython or mel.eval('$aTools_playBackSliderPython=$gPlayBackSlider')
|
||||
range = cmds.timeControl(G.playBackSliderPython, query=True, rangeArray=True)
|
||||
|
||||
range[1] -= 1
|
||||
|
||||
return range
|
||||
|
||||
def getCurrentValues(self, animCurves):
|
||||
if animCurves:
|
||||
result = {"keyValues":[], "timeValues":[]}
|
||||
for loopCurve in animCurves:
|
||||
time = cmds.keyframe(loopCurve, selected=True, query=True, timeChange=True)
|
||||
|
||||
if time:
|
||||
time = [time[0], time[-1]]
|
||||
result["keyValues"].append(cmds.keyframe(loopCurve, query=True, time=(time[0],time[-1]), valueChange=True))
|
||||
else:
|
||||
time = cmds.currentTime(query=True); time = [time, time]
|
||||
result["keyValues"].append(cmds.keyframe(loopCurve, query=True, eval=True, valueChange=True))
|
||||
|
||||
result["timeValues"].append(time)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def updateCurrentValues(self, animCurves=None, *args):
|
||||
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
|
||||
self.removeMessages()
|
||||
|
||||
if not animCurves: animCurves = utilMod.getAllAnimCurves(selection=True)
|
||||
if not animCurves: return
|
||||
|
||||
for loopCurve in animCurves:
|
||||
#if loopCurve in self.allAnimCurves:
|
||||
self.currentValues[loopCurve] = self.getCurrentValues([loopCurve])["keyValues"][0]
|
||||
self.allValues[loopCurve] = animMod.getTarget("keyValues", [loopCurve])[0]
|
||||
|
||||
|
||||
self.addAnimMessages()
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
|
||||
def setValues(self, animCurves):
|
||||
|
||||
cmds.refresh(suspend=True)
|
||||
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.undoInfo(openChunk=True)
|
||||
|
||||
self.removeMessages()
|
||||
self.warn()
|
||||
|
||||
values = self.getCurrentValues(animCurves)
|
||||
newKeyValues = values["keyValues"]
|
||||
timeValues = values["timeValues"]
|
||||
offsetValues = []
|
||||
offsetPercentsA = []
|
||||
offsetPercentsB = []
|
||||
pivotAs = []
|
||||
pivotBs = []
|
||||
self.animCurvesToSend = []
|
||||
|
||||
|
||||
for n, loopCurve in enumerate(animCurves):
|
||||
|
||||
oldVal = self.currentValues[loopCurve][0]
|
||||
newVal = newKeyValues[n][0]
|
||||
|
||||
if self.blendRangeMode:
|
||||
|
||||
pivotA = cmds.keyframe(loopCurve, query=True, eval=True, time=(self.range[0],self.range[0]), valueChange=True)[0]
|
||||
pivotB = cmds.keyframe(loopCurve, query=True, eval=True, time=(self.range[1],self.range[1]), valueChange=True)[0]
|
||||
|
||||
|
||||
if oldVal == pivotA:
|
||||
pivotA = newVal
|
||||
offsetPercentA = 0
|
||||
else:
|
||||
offsetPercentA = float((newVal-pivotA)/(oldVal-pivotA))
|
||||
if oldVal == pivotB:
|
||||
pivotB = newVal
|
||||
offsetPercentB = 0
|
||||
else:
|
||||
offsetPercentB = float((newVal-pivotB)/(oldVal-pivotB))
|
||||
|
||||
offsetPercentsA.append(offsetPercentA)
|
||||
offsetPercentsB.append(offsetPercentB)
|
||||
pivotAs.append(pivotA)
|
||||
pivotBs.append(pivotB)
|
||||
|
||||
else:
|
||||
offsetVal = newVal - oldVal
|
||||
|
||||
offsetValues.append(offsetVal)
|
||||
|
||||
|
||||
#reset change
|
||||
cmds.undoInfo(stateWithoutFlush=False)
|
||||
for loopCurve in list(self.allValues.keys()):
|
||||
if loopCurve in animCurves:
|
||||
valueChange = self.allValues[loopCurve]
|
||||
for n, loopValue in enumerate(valueChange):
|
||||
cmds.keyframe(loopCurve, edit=True, index=(n,n), valueChange=loopValue)
|
||||
#self.allValues[] = {}
|
||||
cmds.undoInfo(stateWithoutFlush=True)
|
||||
|
||||
|
||||
|
||||
#set values for all keys
|
||||
curvesToUpdate = []
|
||||
|
||||
if self.blendRangeMode:
|
||||
for n, loopCurve in enumerate(animCurves):
|
||||
time = timeValues[n]
|
||||
timeOffsetA = .01
|
||||
timeOffsetB = .01
|
||||
|
||||
if time[0] == self.range[0]: timeOffsetA = 0
|
||||
if time[1] == self.range[1]: timeOffsetB = 0
|
||||
|
||||
if timeOffsetA != 0 and timeOffsetB != 0 and not self.range[0] < time[0] <= time[1] < self.range[1]:
|
||||
cmds.warning("Selected keys out of range %s"%self.range)
|
||||
continue
|
||||
|
||||
offsetPercentA = offsetPercentsA[n]
|
||||
offsetPercentB = offsetPercentsB[n]
|
||||
#if offsetPercentA != 0 or offsetPercentB != 0:
|
||||
pivotA = pivotAs[n]
|
||||
pivotB = pivotBs[n]
|
||||
curvesToUpdate.append(loopCurve)
|
||||
cmds.scaleKey(loopCurve, time=(self.range[0]+timeOffsetA, time[1]), valuePivot=pivotA, valueScale=offsetPercentA)
|
||||
cmds.scaleKey(loopCurve, time=(time[1]+.01, self.range[1]-timeOffsetB), valuePivot=pivotB, valueScale=offsetPercentB)
|
||||
|
||||
else:
|
||||
for n, loopCurve in enumerate(animCurves):
|
||||
if offsetValues[n] != 0:
|
||||
curvesToUpdate.append(loopCurve)
|
||||
if self.range == "All Keys":
|
||||
#pass
|
||||
cmds.keyframe(loopCurve, edit=True, valueChange=offsetValues[n], relative=True)
|
||||
else:
|
||||
cmds.keyframe(loopCurve, edit=True, time=(self.range[0], self.range[1]), valueChange=offsetValues[n], relative=True)
|
||||
|
||||
|
||||
self.updateCurrentValues(curvesToUpdate)
|
||||
cmds.undoInfo(closeChunk=True)
|
||||
cmds.refresh(suspend=False)
|
||||
|
||||
|
||||
def warn(self):
|
||||
if self.blendRangeMode:
|
||||
blendTxt = "Blend Range Mode "
|
||||
else:
|
||||
blendTxt = ""
|
||||
|
||||
cmds.warning("Transform All %sis ON. Please remember to turn it OFF when you are done. Acting on range: %s"%(blendTxt, self.range))
|
||||
|
||||
def setRange(self):
|
||||
self.range = self.getRange()
|
||||
|
||||
if self.range[1] - self.range[0] <= 1: #if only one key selected
|
||||
if self.blendRangeMode: self.range = [cmds.playbackOptions(query=True, minTime=True), cmds.playbackOptions(query=True, maxTime=True)]
|
||||
else: self.range = "All Keys"
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user