// =========================================================================== // 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. // =========================================================================== // // // Creation Date: Nov. 96 // // Description: // This script creates a window that can be used to // set the keyable status of attributes on active objects. // // Input Arguments: // None. // // Return Value: // None. // // global proc PSupdateKeyableUI ( string $parent, string $selectedItem ) // // Setup the two lists of attributes - those that // are keyable, and those that aren't, so the user // can flip them from one side to the other. // { setParent $parent; int $KEYABLE_List_Limit, $NONKEYABLE_List_Limit; string $KEYABLE_List[], $NONKEYABLE_List[], $DISP_NONKEYABLE_List[]; if ($selectedItem == "") return; $KEYABLE_List = `listAttr -k -s -v -r -w -c -m $selectedItem`; $DISP_NONKEYABLE_List = `listAttr -cb -s -v -r -w -c -m $selectedItem`; string $NONKEYABLE_ListInit[] = `listAttr -s -v -r -w -c -m $selectedItem`; $NONKEYABLE_List = stringArrayRemove($DISP_NONKEYABLE_List, $NONKEYABLE_ListInit); $KEYABLE_List_Limit = size( $KEYABLE_List ); $DISP_NONKEYABLE_List_Limit = size( $DISP_NONKEYABLE_List ); $NONKEYABLE_List_Limit = size( $NONKEYABLE_List ); if( !`exists lockingKeyableWnd_uiNames` ) { source lockingKeyableWnd; } // The $KEYABLE_List, $NONKEYABLE_List, and // $DISP_NONKEYABLE_List are lists of long names. Now // that we support Channel Names in "long", "short", or // "nice" mode, we might need to convert the displayed // attributes from long names to whatever our current // display mode is. We therefore fill in the // ${KEY,NONKEY,DISP_NONKEY}ABLE_UI_List arrays based on // the display mode. // $KEYABLE_List = sort($KEYABLE_List); $KEYABLE_UI_List = lockingKeyableWnd_uiNames( $KEYABLE_List, $selectedItem ); $NONKEYABLE_List = sort($NONKEYABLE_List); $NONKEYABLE_UI_List = lockingKeyableWnd_uiNames( $NONKEYABLE_List, $selectedItem ); $DISP_NONKEYABLE_List = sort($DISP_NONKEYABLE_List); $DISP_NONKEYABLE_UI_List = lockingKeyableWnd_uiNames( $DISP_NONKEYABLE_List, $selectedItem ); // Since listAttr is going to return the full attribute names // we need, strip off any component parts of $selectedItem // by tokenizing based on the "." character. // string $node, $buffer[]; tokenize( $selectedItem, ".", $buffer ); if( size( $buffer ) > 0 ) { $node = $buffer[0]; } else { $node = $selectedItem; } // First clear, then refill the keyable and non-keyable scroll lists // Each pane in the tabLayout has two scroll lists to manage: the // first (ex: KEYABLE_List) contains the attr name as determined by // the current display mode (optionVar "CCchannelNames"), and the // second (ex: KEYABLE_LONG_List) contains the long name of what's // being displayed, to guarantee that we can issue the appropriate // MEL command to change the state on the attr. // textScrollList -e -m 0 KEYABLE_List; textScrollList -e -m 0 KEYABLE_LONG_List; textScrollList -e -m 0 NONKEYABLE_List; textScrollList -e -m 0 NONKEYABLE_LONG_List; textScrollList -e -m 0 DISP_NONKEYABLE_List; textScrollList -e -m 0 DISP_NONKEYABLE_LONG_List; textScrollList -e -ra KEYABLE_List; textScrollList -e -ra KEYABLE_LONG_List; textScrollList -e -ra NONKEYABLE_List; textScrollList -e -ra NONKEYABLE_LONG_List; textScrollList -e -ra DISP_NONKEYABLE_List; textScrollList -e -ra DISP_NONKEYABLE_LONG_List; int $i; for ( $i=0; $i < $KEYABLE_List_Limit; $i++ ) { textScrollList -e -a $KEYABLE_UI_List[$i] KEYABLE_List; textScrollList -e -a $KEYABLE_List[$i] KEYABLE_LONG_List; } for ( $i=0; $i < $NONKEYABLE_List_Limit; $i++ ) { int $isKeyable; string $attrName = ( $node + "." + $NONKEYABLE_List[$i] ); if( !catch( $isKeyable = `getAttr -k $attrName` ) &&( $isKeyable == 0 ) ) { textScrollList -e -a $NONKEYABLE_UI_List[$i] NONKEYABLE_List; textScrollList -e -a $NONKEYABLE_List[$i] NONKEYABLE_LONG_List; } } for ( $i=0; $i < $DISP_NONKEYABLE_List_Limit; $i++ ) { int $isKeyable; string $attrName = ( $node + "." + $DISP_NONKEYABLE_List[$i] ); if( !catch( $isKeyable = `getAttr -k $attrName` ) &&( $isKeyable == 0 ) ) { textScrollList -e -a $DISP_NONKEYABLE_UI_List[$i] DISP_NONKEYABLE_List; textScrollList -e -a $DISP_NONKEYABLE_List[$i] DISP_NONKEYABLE_LONG_List; } } textScrollList -e -m 1 KEYABLE_List; textScrollList -e -m 1 NONKEYABLE_List; textScrollList -e -m 1 DISP_NONKEYABLE_List; // Hook up the buttons to the right object // button -e -c ( "PS_moveToNonKeyable " + $parent + " " + $selectedItem ) NONKEYABLE_Button; button -e -c ( "PS_moveToKeyable " + $parent + " " + $selectedItem ) KEYABLE_Button; // Dim the lock and unlock buttons. They will be undimmed when // the user clicks on either list // disable KEYABLE_Button; disable NONKEYABLE_Button; } global proc PS_selectItemsInCenterList( string $selectedAttrs[] ) // // When moving to the center list, keep the items selected in case the user // wants to move them over again // { // Select in the (hidden) NONKEYABLE_LONG_List first // for( $selAttr in $selectedAttrs) { textScrollList -e -selectItem $selAttr NONKEYABLE_LONG_List; button -e -en 1 KEYABLE_Button; button -e -en 1 NONKEYABLE_Button; } // Then update the UI list based on what's selected in the LONG list // int $which[] = `textScrollList -q -selectIndexedItem NONKEYABLE_LONG_List`; for( $w in $which ) { textScrollList -e -selectIndexedItem $w NONKEYABLE_List; } } global proc PS_moveToKeyable ( string $parent, string $selectedItem ) // // Move items selected in the non-keyable list // to the keyable list... // { setParent $parent; string $selectedAttrs[]; int $selectedAttrsSize; int $selectedIndices[]; string $flagString = "setAttr -k on"; $selectedIndices = `textScrollList -q -sii NONKEYABLE_List`; $selectedAttrsSize = size( $selectedIndices ); string $longNames[] = `textScrollList -q -ai NONKEYABLE_LONG_List`; int $moveToCenterList = 0; if ($selectedAttrsSize == 0) { $selectedIndices = `textScrollList -q -sii DISP_NONKEYABLE_List`; $selectedAttrsSize = size( $selectedIndices ); $longNames = `textScrollList -q -ai DISP_NONKEYABLE_LONG_List`; $flagString = "setAttr -cb off"; $moveToCenterList = 1; } // Subtract one since the indices were filled up from 1-based // textScrollList -q -sii but $longNames requires 0-based // acess... // for( $index in $selectedIndices ) { $selectedAttrs[size($selectedAttrs)] = $longNames[$index-1]; } // Since listAttr is going to return the full attribute names // we need, strip off any component parts of $selectedItem // by tokenizing based on the "." character. // string $node, $buffer[]; tokenize( $selectedItem, ".", $buffer ); if( size( $buffer ) > 0 ) { $node = $buffer[0]; } else { $node = $selectedItem; } // see if the ALL option is engaged // int $changeAll = `checkBox -q -v CC_KEYALL_Box`; if ( $changeAll ){ // get the node type of the current node // string $baseType = `nodeType $selectedItem`; // get a list of all selected nodes // string $allNodes[] = `selectedNodes`; // for each node that matches type, set the keyability // of each attribute in the non-keyable list // int $limit = `size($allNodes)`; string $thisNode; int $index; for ( $index=0; $index<$limit; $index++ ){ $thisNode = $allNodes[$index]; if ( `nodeType $thisNode` == $baseType ){ int $i; string $cmd; for ( $i=0; $i<$selectedAttrsSize; $i++ ){ $cmd = ($flagString + " " + $thisNode + "." + $selectedAttrs[$i]); evalEcho $cmd; } } } } else { // only change the selected node int $i; for( $i=0; $i < $selectedAttrsSize; $i++ ) { $cmd = ($flagString + " " + $node + "." + $selectedAttrs[$i]); evalEcho $cmd; } } // Update the window // PSupdateKeyableUI $parent $selectedItem; if ($moveToCenterList) { PS_selectItemsInCenterList($selectedAttrs); } } global proc PS_moveToNonKeyable ( string $parent, string $selectedItem ) // // Move items selected in the keyable list // to the non-keyable list... // { setParent $parent; string $selectedAttrs[]; int $selectedAttrsSize; int $selectedIndices[]; string $flagString = "setAttr -k off"; $selectedIndices = `textScrollList -q -sii KEYABLE_List`; $selectedAttrsSize = size( $selectedIndices ); string $longNames[] = `textScrollList -q -ai KEYABLE_LONG_List`; int $moveToCenterList = 1; if ($selectedAttrsSize == 0) { $selectedIndices = `textScrollList -q -sii NONKEYABLE_List`; $selectedAttrsSize = size( $selectedIndices ); $longNames = `textScrollList -q -ai NONKEYABLE_LONG_List` ; $flagString = "setAttr -cb true"; $moveToCenterList = 0; } // Subtract one since the indices were filled up from 1-based // textScrollList -q -sii but $longNames requires 0-based // acess... // for( $index in $selectedIndices ) { $selectedAttrs[size($selectedAttrs)] = $longNames[$index-1]; } // Since listAttr is going to return the full attribute names // we need, strip off any component parts of $selectedItem // by tokenizing based on the "." character. // string $node, $buffer[]; tokenize( $selectedItem, ".", $buffer ); if( size( $buffer ) > 0 ) { $node = $buffer[0]; } else { $node = $selectedItem; } // see if the ALL option is engaged // int $changeAll = `checkBox -q -v CC_KEYALL_Box`; if ( $changeAll ){ // get the node type of the current node // string $baseType = `nodeType $selectedItem`; // get a list of all selected nodes // string $allNodes[] = `selectedNodes`; // for each node that matches type, set the keyability // of each attribute in the non-keyable list // int $limit = `size($allNodes)`; string $thisNode; int $index; for ( $index=0; $index<$limit; $index++ ){ $thisNode = $allNodes[$index]; if ( `nodeType $thisNode` == $baseType ){ int $i; for ( $i=0; $i<$selectedAttrsSize; $i++ ){ $cmd = ($flagString + " " + $thisNode + "." + $selectedAttrs[$i]); evalEcho $cmd; } } } } else { // only change the selected node int $i; for( $i=0; $i < $selectedAttrsSize; $i++ ) { $cmd = ($flagString + " " + $node + "." + $selectedAttrs[$i]); evalEcho $cmd; } } // Update the window // PSupdateKeyableUI $parent $selectedItem; if ($moveToCenterList) { PS_selectItemsInCenterList($selectedAttrs); } } global proc PScreateKeyableUI( string $parent, string $node ) // // Sets up a UI that shows all the DAG and // Shape nodes in the system, so that the // user can set the keyable attributes for // them. // { setParent $parent; string $myContainer = `formLayout containerForm`; text -label (uiRes("m_PScreateKeyableUI.kKeyable")) KEYABLE_Text; // Label the non-keyable area // text -label (uiRes("m_PScreateKeyableUI.kNonKeyableHidden")) NONKEYABLE_Text; // Label the displayable non-keyable area // text -label (uiRes("m_PScreateKeyableUI.kNonKeyableDisplayed")) DISP_NONKEYABLE_Text; // Create the Move to non-keyable button // string $nkButton = `button -label (uiRes("m_PScreateKeyableUI.kMoveRight")) -c ( "PS_moveToNonKeyable " + $parent + " " + $node ) -h 26 NONKEYABLE_Button`; // Create the Move to keyable button // string $kButton = `button -label (uiRes("m_PScreateKeyableUI.kMoveLeft")) -c ( "PS_moveToKeyable " + $parent + " " + $node ) -h 26 KEYABLE_Button`; // Create the cancel/close button // button -label (uiRes("m_PScreateKeyableUI.kClose")) -h 26 -c "deleteUI LockingKeyable" CLOSE_Button; // Create the ALL checkbox // if ( !`optionVar -exists CCkeyAllSame` ){ optionVar -intValue CCkeyAllSame 1; } checkBox -label (uiRes("m_PScreateKeyableUI.kChangeAllObjects")) -v `optionVar -q CCkeyAllSame` -cc "optionVar -intValue CCkeyAllSame #1" CC_KEYALL_Box; // Create the keyable scroll list // textScrollList -ams 1 -h 150 -sc ("disable KEYABLE_Button; disable -v false " + $nkButton + ";textScrollList -e -da NONKEYABLE_List; textScrollList -e -da DISP_NONKEYABLE_List" ) KEYABLE_List; // Create the non-keyable scroll list // textScrollList -ams 1 -h 150 -sc ("button -e -en 1 KEYABLE_Button; button -e -en 1 NONKEYABLE_Button; textScrollList -e -da KEYABLE_List; textScrollList -e -da DISP_NONKEYABLE_List" ) NONKEYABLE_List; // Create the displayed non-keyable scroll list // textScrollList -ams 1 -h 150 -sc ("disable NONKEYABLE_Button; disable -v false " + $kButton + ";textScrollList -e -da NONKEYABLE_List;textScrollList -e -da KEYABLE_List" ) DISP_NONKEYABLE_List; // When we're displaying Nice attr names, we can't just // query the textScrollList for its selected entries to // get an attr's long name to execute its state-changing // MEL command. So, no matter what we're actually displaying, // these three {KEY,NONKEY,DISP_NONKEY}ABLE_LONG_List // textScrollLists hold on to the long names required for // the MEL commands. They're always kept in sync whenever // their corresponding display-name textScrollLists are // modified, and it was easier implementing things this way // than passing a bunch of arrays around and modifying proc // signatures and such. These widgets are never made visible // and really are for convenience only. // textScrollList -ams 1 -visible 0 KEYABLE_LONG_List; textScrollList -ams 1 -visible 0 NONKEYABLE_LONG_List; textScrollList -ams 1 -visible 0 DISP_NONKEYABLE_LONG_List; separator -hr true KEYABLE_Sep; // Edit the form attachments // formLayout -edit -af KEYABLE_Text top 10 -af KEYABLE_Text left 10 -ap KEYABLE_Text right 10 33 -an KEYABLE_Text bottom -af NONKEYABLE_Text top 10 -ap NONKEYABLE_Text left 10 33 -ap NONKEYABLE_Text right 10 66 -an NONKEYABLE_Text bottom -af DISP_NONKEYABLE_Text top 10 -ap DISP_NONKEYABLE_Text left 10 66 -af DISP_NONKEYABLE_Text right 10 -an DISP_NONKEYABLE_Text bottom -af KEYABLE_List top 30 -af KEYABLE_List left 10 -ap KEYABLE_List right 0 33 -ac KEYABLE_List bottom 10 KEYABLE_Sep -af NONKEYABLE_List top 30 -ap NONKEYABLE_List left 0 33 -ap NONKEYABLE_List right 0 66 -ac NONKEYABLE_List bottom 10 KEYABLE_Sep -af DISP_NONKEYABLE_List top 30 -ap DISP_NONKEYABLE_List left 0 66 -af DISP_NONKEYABLE_List right 10 -ac DISP_NONKEYABLE_List bottom 10 KEYABLE_Sep -an KEYABLE_Sep top -af KEYABLE_Sep left 0 -af KEYABLE_Sep right 0 -af KEYABLE_Sep bottom 60 -an CC_KEYALL_Box top -af CC_KEYALL_Box left 15 -af CC_KEYALL_Box bottom 30 -an CC_KEYALL_Box right -ac CLOSE_Button top 2 CC_KEYALL_Box -ap CLOSE_Button right 2 66 -ap CLOSE_Button left 2 33 -af CLOSE_Button bottom 5 -ac NONKEYABLE_Button top 2 CC_KEYALL_Box -ap NONKEYABLE_Button right 2 33 -af NONKEYABLE_Button left 5 -af NONKEYABLE_Button bottom 5 -ac KEYABLE_Button top 2 CC_KEYALL_Box -ap KEYABLE_Button left 2 66 -af KEYABLE_Button right 5 -af KEYABLE_Button bottom 5 $myContainer; // Fill the scroll lists // with the selected object's attributes // PSupdateKeyableUI $parent $node; showWindow; }