def export_framecurve_from_this_knob(): fc_path = nuke.getFilename("Name the framecurve file to write to", "*.framecurve.txt", default="shot.framecurve.txt", favorites="", type="", multiple=False) fc = framecurve.Curve() curve_name_with_suffix = nuke.animations()[0] knob_name = curve_name_with_suffix.split(".")[0] this_knob = nuke.thisNode()[knob_name] with open(fc_path, "w") as fc_file: for curve in nuke.animations(): for frame in all_script_frames(): fc.append(framecurve.FrameCorrelation(at=frame, value=this_knob.getValueAt(frame))) framecurve.serialize(fc_file, framecurve.simplify(fc))
def __init__(self, node): #get reference of tKey knob knob_names = nuke.animations() knob_name_with_suffix = knob_names[0] #print"knob_name_with_suffix " #print knob_name_with_suffix knob_name = getKnobName(knob_name_with_suffix) k = nuke.thisNode()[knob_name] #so that our default frame range can be the length of it's keyframes tFirst = first_keyframe_location(k) tLast = last_keyframe_location(k) nukescripts.PythonPanel.__init__( self, 'Reduce keyframes in selected animation?') # CREATE KNOBS self.tFrameRange = nuke.String_Knob('tFrameRange', 'Frame Range', '%s-%s' % (tFirst, tLast)) self.tErrorPercent = nuke.Double_Knob('tErrorPercent', 'Error threshold (%)') self.tErrorPercent.setValue(10) self.tErrorPercent.setRange(1, 100) self.pcText = nuke.Text_Knob('%') self.pcText.clearFlag(nuke.STARTLINE) # ADD KNOBS for k in (self.tFrameRange, self.tErrorPercent): self.addKnob(k)
def animation_reverse(): a = nuke.animations() for i in a: anim = nuke.animation(i, "expression") if anim is not None and anim == "curve(first_frame+last_frame-frame)": nuke.animation(i, "expression", ("curve", )) else: nuke.animation(i, "expression", ("curve(first_frame+last_frame-frame)", ))
def animation_loop(): p = nuke.Panel("Loop") p.addSingleLineInput("First frame of loop:", 1) p.addSingleLineInput("Last frame of loop:", nuke.animationEnd()) result = p.show() if result: anim = nuke.animations() for i in anim: loopstart = p.value("First frame of loop:") loopend = p.value("Last frame of loop:") nuke.animation(i, "expression", ("curve(((frame-" + loopstart + ")%(" + loopend + "-" + loopstart + "+1))+" + loopstart + ")", ))
def getKnobIndex(): # useful function by Ivan Busquets index = nuke.animations() if len(index) > 1: return -1 else: try: if 'x' in index[0].split('.')[1]: return 0 else: return 1 except: return 0
def load_framecurve_into_focused_knob(): """ Can be used as a callback on an animated knob in the Animation menu. It will replace the animation in the currently selected knob's curve with a curve loaded from Framecurve """ # Load the framecurve into tuples framecurve_path = grab_file() if framecurve_path == None: return with open(framecurve_path) as fc_file: curve = load_and_validate_stream(fc_file) knob_names = nuke.animations() # Returns the animations names under this knob for knob_name_with_suffix in knob_names: # Since the names are like "translate.x" what we gotta do is to chop off the suffix knob_name = knob_name_with_suffix.split(".")[0] # so that we can get at the knob object and do... k = nuke.thisNode()[knob_name] load_curve_into_knob(curve, k)
def doReduceKeyframes(): p = doReduceKeyframesPanel(nuke.selectedNode()) if p.showModalDialog(): #user did not hit cancel button undo = nuke.Undo() undo.begin("Reduce keyframes") tErrorPercent = p.tErrorPercent.value() if (tErrorPercent > 100): tErrorPercent = 100 if (tErrorPercent < 0.000001): tErrorPercent = 0.000001 #print "tErrorPercent " + str(tErrorPercent) tFrameRange = nuke.FrameRange(p.tFrameRange.value()) tFirstFrame = tFrameRange.first() tLastFrame = tFrameRange.last() knob_names = nuke.animations( ) # Returns the animations names under this knob i = getKnobIndex( ) #find out if user only clicked on a single knob index, or the entire knob #print "knob index: " + str(i) j = 0 #index for knob for knob_name_with_suffix in knob_names: if (i > -1): j = i #print "for knob_name_with_suffix in knob_names:" knob_name = getKnobName(knob_name_with_suffix) # so that we can get at the knob object and do... k = nuke.thisNode()[knob_name] if (k.isAnimated(j)): tOriginalCurve = k.animation(j) tKeys = tOriginalCurve.keys() tOrigFirstFrame = tKeys[0].x tOrigLastFrame = tKeys[len(tKeys) - 1].x tOrigKeys = len(tOriginalCurve.keys()) fErrorHeight = getCurveHeight(tOriginalCurve, tFirstFrame, tLastFrame) tErrorThreshold = fErrorHeight * (tErrorPercent / 100) #print "tErrorThreshold " + str(tErrorThreshold) if (tOrigKeys > 2): #no point in reducing a straight line! x = nuke.selectedNode() #create a temp knob to copy new keyframes into tempname = "temp_" + knob_name + str(j) tTempKnob = nuke.Double_Knob(tempname) tTempKnob.setAnimated() tTempKnob.setValueAt(tOriginalCurve.evaluate(tFirstFrame), tFirstFrame) tTempKnob.setValueAt(tOriginalCurve.evaluate(tLastFrame), tLastFrame) tTempCurve = tTempKnob.animation(0) #if we are only reducing keyframes on a smaller frame range, then copy the original keyframes into the other frames if (tFirstFrame > tOrigFirstFrame) | (tLastFrame < tOrigLastFrame): tKeys = x[knob_name].animation(j).keys() tCopyKeys = [] for tKey in tKeys: if ((tKey.x < tFirstFrame) | (tKey.x > tLastFrame)): tCopyKeys.append(tKey) tTempKnob.animation(0).addKey(tCopyKeys) #do a quick check to see if 2 keyframes are enough deltaH = (tLastFrame - tFirstFrame) deltaV = (tTempKnob.getValueAt(tLastFrame) - tTempKnob.getValueAt(tFirstFrame)) tMasterSlope = 90 - getAngle(deltaH, deltaV) if (tMasterSlope < 0): tMasterSlope = tMasterSlope + 360 if (findErrorHeight(tOriginalCurve, tTempCurve, tFirstFrame, tLastFrame, tMasterSlope) < tErrorThreshold): print "Looks like this selection of frames was a straight line. Reduce the error threshold % if it isn't" else: #otherwise we run the keyframe reducing function on the selected frame range recursion = findGreatestErrorFrame( tOriginalCurve, tFirstFrame, tLastFrame, tErrorThreshold, tTempKnob, tTempCurve, 0) #copy our reduced keyframes from the temp knob back into our original knob x[knob_name].copyAnimation(j, tTempKnob.animation(0)) #calculate how much we have reduced number of keyframes tFinalKeys = len(x[knob_name].animation(j).keys()) tReductionPC = int( (float(tFinalKeys) / float(tOrigKeys)) * 100) print knob_name + "[" + str(j) + "] had " + str( tOrigKeys) + " keys reduced to " + str( tFinalKeys) + " keys (" + str(tReductionPC) + "%)" else: print "No animation found in " + knob_name + " index " + str(j) #break the loop if we are only running script on single knob index if (i > -1): break else: j = j + 1 undo.end()
def animation_negate(): anim = nuke.animations() for i in anim: expr = "-(" + nuke.animation(i, "expression") + ")" nuke.animation(i, "expression", (expr, ))
def doFixGimbalFlip(): p = doFixGimbalFlipPanel(nuke.selectedNode()) if p.showModalDialog(): #user did not hit cancel button undo = nuke.Undo() undo.begin("Fix Gimbal Flip") tErrorPercent = p.tErrorPercent.value() if (tErrorPercent > 100): tErrorPercent = 100 if (tErrorPercent < 0.000001): tErrorPercent = 0.000001 tFrameRange = nuke.FrameRange(p.tFrameRange.value()) tFirstFrame = tFrameRange.first() tLastFrame = tFrameRange.last() knob_names = nuke.animations( ) # Returns the animations names under this knob i = getKnobIndex( ) #find out if user only clicked on a single knob index, or the entire knob print "knob index: " + str(i) j = 0 #index for knob #print " knob_names " + str( knob_names) for knob_name_with_suffix in knob_names: #print "knob_name_with_suffix " + str(knob_name_with_suffix) if (i > -1): j = i #print "for knob_name_with_suffix in knob_names:" knob_name = getKnobName(knob_name_with_suffix) # so that we can get at the knob object and do... k = nuke.thisNode()[knob_name] print knob_name + "." + str(j) if (k.isAnimated(j)): tOriginalCurve = k.animation(j) tKeys = tOriginalCurve.keys() #tOrigFirstFrame = tKeys[0].x #tOrigLastFrame = tKeys[len(tKeys)-1].x tKeysLen = len(tKeys) tLastValue = tKeys[0].y #print "tErrorThreshold " + str(tErrorThreshold) n = nuke.selectedNode() for f in range(0, tKeysLen): tFrame = tKeys[f].x if (tFrame >= tFirstFrame) and (tFrame <= tLastFrame): tValue = tKeys[f].y #print "tValue " + str(tValue) tLastDiff = tLastValue - tValue tPredictedValue = tValue + tLastDiff tDiff = tPredictedValue - tValue #print str(tFrame) + " tLastValue " + str(tLastValue) + " tValue " + str(tValue) + " tLastDiff " + str(tLastDiff) #print str(tFrame) + " tPredictedValue " + str(tPredictedValue) + " tValue " + str(tValue) + " tDiff " + str(tDiff) if (tDiff > (180 - tErrorPercent)) | (tDiff < -(180 - tErrorPercent)): print "gimbal flip at " + str(tFrame) print str(tFrame) + " tPredictedValue " + str( tPredictedValue) + " tValue " + str( tValue) + " tDiff " + str(tDiff) #print "fixing keys " + str(i) + " to " + str(tKeysLen) print "fixing frames " + str( tKeys[f].x) + " to " + str( tKeys[tKeysLen - 1].x) for k in range(f, tKeysLen): #k.animation(j) tFixFrame = tKeys[k].x if (tFixFrame >= tFirstFrame) and (tFixFrame <= tLastFrame): tOldValue = tKeys[k].y if (tDiff > 0): tNewValue = tOldValue + 180 else: tNewValue = tOldValue - 180 #print str(tFixFrame) + " tOldValue " + str(tOldValue) + " tNewValue " + str(tNewValue) tOriginalCurve.setKey(tFixFrame, tNewValue) if (tDiff > 0): tLastValue = tValue + 180 else: tLastValue = tValue - 180 else: tLastValue = tValue else: print "No animation found in " + knob_name + " index " + str(j) #break the loop if we are only running script on single knob index if (i > -1): #print "breaking" break else: j = j + 1 #print "j " + str(j) undo.end()