772 lines
33 KiB
Python
772 lines
33 KiB
Python
|
'''
|
||
|
========================================================================================================================
|
||
|
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)
|
||
|
|