// =========================================================================== // 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. // =========================================================================== // // Procedure Name: // AEmotionPathTemplate // // Description Name; // Creates the attribute editor controls for the motionPath node // // Input Value: // nodeName // // Output Value: // None // // Global strings used to keep track of custom UI in // tear-off copies of the motionPath attribute editor. // These are cleared in resetAE.mel which gets called on // all file operations. // global string $gAEmotionPathWorldUpWidgets[]; // hold info plus widgets global string $gAEmotionPathFollowCBG[]; // follow checkBoxGrp // The main template proc called when the first instance // of the motionPath attribute editor is opened. // global proc AEmotionPathTemplate( string $nodeName ) { editorTemplate -beginScrollLayout; editorTemplate -beginLayout (uiRes("m_AEmotionPathTemplate.kMotionPathAttributes")) -collapse 0; editorTemplate -addControl "uValue"; // The fraction mode attribute value is presented in the // UI as "Parametric Length" which has the opposite // boolean value. Therefore, we need a custom control. // editorTemplate -callCustom "AEmotionPathFractionModeNew" "AEmotionPathFractionModeReplace" "fractionMode"; editorTemplate -callCustom "AEmotionPathFollowNew" "AEmotionPathFollowReplace" "follow"; editorTemplate -addControl "worldUpType" "AEmotionPathWorldUpControls"; editorTemplate -addControl "worldUpVector"; editorTemplate -callCustom "AEmotionPathWorldUpObjectNew" "AEmotionPathWorldUpObjectReplace" "worldUpMatrix"; editorTemplate -addControl "inverseUp"; editorTemplate -addControl "inverseFront"; editorTemplate -addControl "frontAxis"; editorTemplate -addControl "upAxis"; editorTemplate -addControl "frontTwist"; editorTemplate -addControl "upTwist"; editorTemplate -addControl "sideTwist"; editorTemplate -addSeparator; editorTemplate -addControl "bank" "AEmotionPathBankControls"; editorTemplate -addControl "bankScale"; editorTemplate -addControl "bankLimit"; editorTemplate -endLayout; // include/call base class/node attributes AEdependNodeTemplate $nodeName; editorTemplate -addExtraControls; editorTemplate -endScrollLayout; editorTemplate -suppress "normal"; editorTemplate -suppress "worldUpType"; editorTemplate -suppress "positionMarkerTime"; editorTemplate -suppress "orientationMarkerTime"; editorTemplate -suppress "rotateOrder"; editorTemplate -suppress "flowNode"; editorTemplate -suppress "oldFlowNode"; editorTemplate -suppress "geometryPath"; } // This proc gets called by the scriptJob which is watching the // follow attribute // global proc AEmotionPathFollowScriptJobProc(string $plug, string $followControl) { checkBoxGrp -e -v1 `getAttr $plug` $followControl; AEmotionPathFollowControlUpdate($plug,$followControl,1); } // The creation proc for the custom follow checkBoxGrp. // global proc AEmotionPathFollowNew( string $plug ) { global string $gAEmotionPathFollowCBG[]; // get the nodeName // string $buffer[]; tokenize($plug,".|",$buffer); string $nodeName = $buffer[0]; // data is stored in triples in $gAEmotionPathFollowCBG; // the first item is the nodename, the second is the parent layout // and the third is the control name // int $numMotionPathAEs = size($gAEmotionPathFollowCBG); $gAEmotionPathFollowCBG[$numMotionPathAEs] = $nodeName; $gAEmotionPathFollowCBG[$numMotionPathAEs+1] = `setParent -q`; // build the checkBoxGrp // setUITemplate -pst attributeEditorTemplate; string $followControl = `checkBoxGrp -ncb 1 -label "" -label1 (uiRes("m_AEmotionPathTemplate.kFollow")) AEmotionPathFollowCheckBoxGrp`; string $cc = "AEmotionPathFollowControlUpdate "+$plug+" "+$followControl+" 0"; checkBoxGrp -e -cc $cc $followControl; // store the control name in the global string array // so that we can keep track of it // $gAEmotionPathFollowCBG[$numMotionPathAEs+2] = $followControl; // set the original value // checkBoxGrp -e -v1 `getAttr $plug` $followControl; // build the callback mechanism // string $cmd = "AEmotionPathFollowScriptJobProc "+$plug+" "+$followControl; scriptJob -rp -p $followControl -ac $plug $cmd; } // A local proc used to find a control given current UI parent layout // proc string getCurrentFollowControl( string $nodeName ) { global string $gAEmotionPathFollowCBG[]; // look for the correct parent // string $curParent = `setParent -q`; int $index = -1; int $i; for ($i = 0; $i < size($gAEmotionPathFollowCBG); $i += 3 ) { if ( $curParent == $gAEmotionPathFollowCBG[$i+1] ) { $index = $i+2; break; } } string $cbg = "AEmotionPathFollowCheckBoxGrp"; if ($index != -1) { $cbg = $gAEmotionPathFollowCBG[$index]; $gAEmotionPathFollowCBG[$index-2] = $nodeName; } return $cbg; } // This proc is called when the user switches from one motionPath // to another so that we can reuse UI (which is faster than having // to delete and recreate it) // global proc AEmotionPathFollowReplace( string $plug ) { // get the nodeName // string $buffer[]; tokenize($plug,".|",$buffer); string $nodeName = $buffer[0]; // get the parent // string $followControl = getCurrentFollowControl( $nodeName ); // update the checkBoxGrp // string $cc = "AEmotionPathFollowControlUpdate "+$plug+" "+$followControl+" 0"; checkBoxGrp -e -v1 `getAttr $plug` -cc $cc $followControl; // update the callback mechanism // string $cmd = "AEmotionPathFollowScriptJobProc "+$plug+" "+$followControl; scriptJob -rp -p $followControl -ac $plug $cmd; } // This proc gets called when the user hits the follow checkBoxGrp, // or when the follow attribute has changed (i.e. the user typed // `pathAnimation -e -follow [true|false] motionPath1`). // This proc will dim/undim all related controls appropriately. // global proc AEmotionPathFollowControlUpdate(string $plug, string $followControl, int $fromScriptJob) { global string $gAEmotionPathNormalRBG[]; // get the nodeName from the plug // string $buffer[]; tokenize($plug,".",$buffer); string $nodeName = $buffer[0]; // get the current value of the checkBoxGrp // int $value = `checkBoxGrp -q -v1 $followControl`; // a pathAnimation command should only be issued if the // user hit the follow checkBoxGrp // if (!$fromScriptJob) pathAnimation -edit -follow $value $nodeName; // dim/undim controls for related attributes appropriately // if ($value == 1) { // Enable/disable the world up controls editorTemplate -dimControl $nodeName "worldUpType" false; AEmotionPathWorldUpControls( $nodeName ); editorTemplate -dimControl $nodeName "inverseUp" false; editorTemplate -dimControl $nodeName "inverseFront" false; editorTemplate -dimControl $nodeName "frontAxis" false; editorTemplate -dimControl $nodeName "upAxis" false; editorTemplate -dimControl $nodeName "frontTwist" false; editorTemplate -dimControl $nodeName "upTwist" false; editorTemplate -dimControl $nodeName "sideTwist" false; editorTemplate -dimControl $nodeName "bank" false; AEmotionPathBankControls $nodeName; } else { // Disable the world up controls editorTemplate -dimControl $nodeName "worldUpType" true; AEmotionPathWorldUpControls( $nodeName ); editorTemplate -dimControl $nodeName "inverseUp" true; editorTemplate -dimControl $nodeName "inverseFront" true; editorTemplate -dimControl $nodeName "frontAxis" true; editorTemplate -dimControl $nodeName "upAxis" true; editorTemplate -dimControl $nodeName "frontTwist" true; editorTemplate -dimControl $nodeName "upTwist" true; editorTemplate -dimControl $nodeName "sideTwist" true; editorTemplate -dimControl $nodeName "bank" true; editorTemplate -dimControl $nodeName "bankScale" true; editorTemplate -dimControl $nodeName "bankLimit" true; } } // This proc will dim/undim the bank controls as required // global proc AEmotionPathBankControls(string $nodeName) { $nodeAttr = $nodeName +".bank"; $value = `getAttr $nodeAttr`; if ($value == 1) { editorTemplate -dimControl $nodeName "bankScale" false; editorTemplate -dimControl $nodeName "bankLimit" false; } else { editorTemplate -dimControl $nodeName "bankScale" true; editorTemplate -dimControl $nodeName "bankLimit" true; } } proc setStateOfWorldUpObjectControls( string $nodeName, int $state ) { global string $gAEmotionPathWorldUpWidgets[]; // Update the world up object text field for all attribute // editors looking at this node int $i; for ($i = 0; $i < size($gAEmotionPathWorldUpWidgets); $i += 3 ) { if ( $nodeName == $gAEmotionPathWorldUpWidgets[$i] ) { string $worldUpObjectControl = $gAEmotionPathWorldUpWidgets[$i+2]; if ( `textFieldGrp -exists $worldUpObjectControl` ) { textFieldGrp -e -enable $state $worldUpObjectControl; } } } } // This proc will dim/undim the world up controls as required global proc AEmotionPathWorldUpControls(string $nodeName) { if ( `getAttr ($nodeName+".follow")` ) { $nodeAttr = $nodeName +".worldUpType"; int $value = `getAttr $nodeAttr`; switch ($value) { case 0: // Scene Up case 4: // Normal editorTemplate -dimControl $nodeName "worldUpVector" true; setStateOfWorldUpObjectControls( $nodeName, false ); break; case 1: // Object Up editorTemplate -dimControl $nodeName "worldUpVector" true; setStateOfWorldUpObjectControls( $nodeName, true ); break; case 2: // Object Rotation Up editorTemplate -dimControl $nodeName "worldUpVector" false; setStateOfWorldUpObjectControls( $nodeName, true ); break; case 3: // Vector editorTemplate -dimControl $nodeName "worldUpVector" false; setStateOfWorldUpObjectControls( $nodeName, false ); break; default: break; } } else { editorTemplate -dimControl $nodeName "worldUpVector" true; setStateOfWorldUpObjectControls( $nodeName, false ); } } // This proc gets called by the UI widget for the // worldUpMatrix attribute // global proc AEmotionPathWorldUpObjectControlProc(string $nodeName, string $widget) { // Get the current value of the widget string $value = `textFieldGrp -q -text $widget`; // setAttr just isn't sufficient for worldUpMatrix pathAnimation -edit -worldUpObject $value $nodeName; } // This proc gets called by the scriptJob which is watching the // worldUpMatrix attribute // global proc AEmotionPathWorldUpObjectScriptJobProc(string $nodeName, string $widget) { textFieldGrp -e -text `pathAnimation -q -worldUpObject $nodeName` $widget; } // Local proc shared by AEmotionPathWorldUpObjectNew() and AEmotionPathWorldUpObjectReplace() proc updateWorldUpObject( string $nodeName, string $plug, string $worldUpObjectControl ) { // Initialize/update the textFieldGrp string $cmd1 = "AEmotionPathWorldUpObjectControlProc "+$nodeName+" "+$worldUpObjectControl; textFieldGrp -e -text `pathAnimation -q -worldUpObject $nodeName` -cc $cmd1 $worldUpObjectControl; // Setup/update the scriptJob callback mechanism string $cmd2 = "AEmotionPathWorldUpObjectScriptJobProc "+$nodeName+" "+$worldUpObjectControl; scriptJob -rp -p $worldUpObjectControl -ac $plug $cmd2; } // The custom creation proc for the worldUpMatrix attribute // global proc AEmotionPathWorldUpObjectNew( string $plug ) { global string $gAEmotionPathWorldUpWidgets[]; // Get the node name string $buffer[]; tokenize($plug,".|",$buffer); string $nodeName = $buffer[0]; // Save the node name and the parent info in the global // string array int $numMotionPathAEs = size($gAEmotionPathWorldUpWidgets); $gAEmotionPathWorldUpWidgets[$numMotionPathAEs] = $nodeName; $gAEmotionPathWorldUpWidgets[$numMotionPathAEs+1] = `setParent -q`; // Create the textFieldGrp setUITemplate -pst attributeEditorTemplate; string $worldUpObjectControl = `textFieldGrp -label (uiRes("m_AEmotionPathTemplate.kWorldUpObject")) AEmotionPathWorldUpObjectField`; // Save the control for possible later reuse $gAEmotionPathWorldUpWidgets[$numMotionPathAEs+2] = $worldUpObjectControl; setUITemplate -ppt; updateWorldUpObject( $nodeName, $plug, $worldUpObjectControl ); } global proc AEmotionPathWorldUpObjectReplace( string $plug ) { global string $gAEmotionPathWorldUpWidgets[]; // Get the node name string $buffer[]; tokenize($plug,".|",$buffer); string $nodeName = $buffer[0]; // Reuse the existing control string $curParent = `setParent -q`; int $index = -1; int $i; for ( $i = 0; $i < size($gAEmotionPathWorldUpWidgets); $i += 3 ) { if ( $curParent == $gAEmotionPathWorldUpWidgets[$i+1] ) { $index = $i; break; } } string $worldUpObjectControl = "AEmotionPathWorldUpObjectField"; if ($index != -1) { $gAEmotionPathWorldUpWidgets[$index] = $nodeName; $worldUpObjectControl = $gAEmotionPathWorldUpWidgets[$index+2]; } updateWorldUpObject( $nodeName, $plug, $worldUpObjectControl ); } global proc AEmotionPathFractionModeNew( string $attrName ) // // Description: // Create a new checkBoxGrp for the attribute. // { checkBoxGrp -ncb 1 -label "" -label1 (uiRes("m_AEmotionPathTemplate.kParametricLength")) AEmotionPathFractionModeCheckBox; AEmotionPathFractionModeReplace( $attrName ); } global proc AEmotionPathFractionModeReplace( string $attrName ) // // Description: // Reconnect this control to the new attribute. // { // The value of the check box is the opposite of the // boolean-valued attribute. // int $attrValue = (! `getAttr $attrName`); checkBoxGrp -e -value1 $attrValue -changeCommand ( "setAttr \"" + $attrName + "\" (!#1)" ) AEmotionPathFractionModeCheckBox; scriptJob -replacePrevious -p AEmotionPathFractionModeCheckBox -attributeChange $attrName ( "AEmotionPathFractionModeChanged " + $attrName + " AEmotionPathFractionModeCheckBox" ); } global proc AEmotionPathFractionModeChanged( string $attrName, string $checkBoxGrp ) // // Description: // // { int $attrValue = (! `getAttr $attrName`); checkBoxGrp -e -v1 $attrValue AEmotionPathFractionModeCheckBox; }