// =========================================================================== // Copyright 2018 Autodesk, Inc. All rights reserved. // // Use of this software is subject to the terms of the Autodesk license // agreement provided at the time of installation or download, or which // otherwise accompanies this software in either electronic or hard copy form. // =========================================================================== //========================================================== // // Rotate Pivot Animation Controls // ------------------------------- // // There are four MEL procedures provided for animating // the rotate pivot of an object in a way that prevents // the object from jumping suddenly each time the pivot // moves. // // The functions are: // // 1) pivotKey(px,py,pz): keys the rotate pivot to // position (px,py,pz) in local space at the // current frame. // // 2) pivotKeyCur(): keys the rotate pivot to its // current position in local space at the current // frame. // // 3) pivotKeyUpdate(): runs through all pivot // keyframes and ensures that the object remains // stationary at the points where the pivot // moves. // // The pivotKey() and pivotKeyCur() functions use // stepped tangents, so the pivot point instantaneously // moves from one keyframed position to the next. This // helps to avoid unpredictable behaviour that can result // from smoothly varying both the rotate and rotate pivot // values at the same time. // // The following is an example sequence of commands: // // 1) - create a poly cube and select it // // 2) - frame 1 // - run pivotKeyCur() to set a pivot key // - keyframe object's rotation // // 3) - frame 20 // - rotate the object and key its rotation // // 4) - frame 21 // - run pivotKey( 0.5, 0.5, 0.5 ) to move the // pivot to (0.5,0.5,0.5) in local space and // set a key // // 5) - frame 40 // - rotate the object and key its rotation // // The result will be: // // - frames 1->20: object rotates about its center // - frame 21: pivot moves to object's corner // - frames 21->40: object rotates about corner // // When you play the animation, the object will // remain stationary at frame 21 when the pivot // changes. // // If, however, you go and modify the object's // rotation at frame 20, you will find that // a jump will occur when the pivot changes at frame // 21. To fix this, just run pivotKeyUpdate() with the // object selected. This will run through all keyframes // and ensure that no jumps occur when the pivot changes. // // The reason why pivotKeyUpdate() is necessary is that // in order to prevent the jumping when the pivot changes, // we are keying the rotatePivotTranslate attribute. The // required value for that attribute is dependent on the // object's rotation at that point, so if the rotation // changes, we need to update the rotatePivotTranslate // keys to avoid jumping. This function automatically // updates those keys. // //========================================================== global proc pivotKeyUpdate() // // Description: // // For the first selected transform, runs through // all keyframes for the rotatePivot attribute, and // updates the corresponding rotatePivotTranslate // keys to compensate for the object's rotation at // those frames. This will ensure that the object // does not jump when the pivot moves. // { // save current time // float $t = `currentTime -q`; // get the first selected transform // string $sl[] = `ls -sl`; if( size($sl) == 0 ) { error( (uiRes("m_pivotKeyUpdate.kPivotKeyUpdateErr")) ); } string $o = $sl[0]; // get the keys on the rotate pivot // float $pivotKeys[] = `keyframe -q -timeChange ($o + ".rotatePivotX")`; // for each key, update the rotatePivotTranslate to compensate for // the object's rotation // float $p; for( $p in $pivotKeys ) { currentTime $p; pivotKeyUpdateOneFrame(); } // restore current time // currentTime $t; } global proc pivotKeyUpdateOneFrame() // // Description: // // Updates the rotatePivotTranslate key // at the current frame to properly // compensate for the rotate pivot change // that happens at that frame. This will // prevent the object from jumping at this // frame. // // The procedure works by going to the // frame where the pivot is keyed, and // re-running the keyPivot() command // to generate a new compensating factor. // { // save current time // float $t = `currentTime -q`; // get current transform // string $sl[] = `ls -sl`; string $o = $sl[0]; // back up to the previous frame to get the rotatePivot // and rotatePivotTranslate values before the pivot // moved. // currentTime ($t-1); float $rpx = `getAttr ($o + ".rotatePivotX")`; float $rpy = `getAttr ($o + ".rotatePivotY")`; float $rpz = `getAttr ($o + ".rotatePivotZ")`; float $rptx = `getAttr ($o + ".rotatePivotTranslateX")`; float $rpty = `getAttr ($o + ".rotatePivotTranslateY")`; float $rptz = `getAttr ($o + ".rotatePivotTranslateZ")`; // advance back to the current frame // currentTime $t; // figure out where the pivot is supposed to move to // float $nrpx = `getAttr ($o + ".rotatePivotX")`; float $nrpy = `getAttr ($o + ".rotatePivotY")`; float $nrpz = `getAttr ($o + ".rotatePivotZ")`; // restore the state of the pivot/pivotTranslate // attributes before the key was set // setAttr ($o + ".rotatePivotX") $rpx; setAttr ($o + ".rotatePivotY") $rpy; setAttr ($o + ".rotatePivotZ") $rpz; setAttr ($o + ".rotatePivotTranslateX") $rptx; setAttr ($o + ".rotatePivotTranslateY") $rpty; setAttr ($o + ".rotatePivotTranslateZ") $rptz; // regenerate the pivot key - this will key the // rotatePivotTranslate attribute to the proper // value to compensate for the object's current // rotation. // float $sx = `getAttr ($o + ".scaleX")`; float $sy = `getAttr ($o + ".scaleY")`; float $sz = `getAttr ($o + ".scaleZ")`; pivotKey( ($nrpx/$sx), ($nrpy/$sy), ($nrpz/$sz) ); }