// =========================================================================== // 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. // =========================================================================== // // hikGlobalUtils.mel // // Description: // // Collection of useful global strings, variables and methods. // All global variables should start with "gHIK" and all // global methods should begin with "hik". // // UI-related global methods belong in the appropriate hik*UI.mel // file. // /////////////////////////////////////////////////////////////////////// // Global variables... /////////////////////////////////////////////////////////////////////// global int $gHIKDockableWindowWidth = 335; $gHIKDockableWindowWidth = `optionVar -q workspacesWidePanelInitialWidth`; global int $gHIKScrollBarWidth = 12; global string $gHIKCurrentCharacter = ""; global string $gHIKCurrentSource = ""; // TabHeight is used for setting the tabLayout's height when switching // between different tabs to keep the bottom aligned with the contents // skeleton and definition heights are constant // control and custom rig heights vary based on their width global int $gHIKSkeletonTabHeight = 540; if ( `about -uiLanguageIsLocalized` ) { $gHIKSkeletonTabHeight += 75; } global int $gHIKDefinitionTabHeight = 796; global float $gHIKRigAspectRatio = 1.0; // RigTabsAuxWidth is the difference between the width of the whole dock // and the figure widget. It takes into account the width of the layouts' // borders and 16 pixels for the potential vertical scrollbar global int $gHIKRigTabsAuxWidth = 39; global int $gHIKDockMinWidth = 282; // need it big enough so we don't get the horizontal scrollbar that does not scroll global int $gHIKSchematicWidgetMinWidth = 250; global int $gHIKSchematicWidgetMinHeight = 385; global int $gHIKDockSkeletonWidth = 279; global int $gHIKDockDefinitionWidth = 291; // FrameLayoutHeight is used for keeping the tabLayout bottom aligned // to the bottom of the contents which can expand and collapse // independently of the tab width // FrameLayoutHeight is constant // Used when resizing the control rig ui global int $gHIKControlRigFrameLayoutHeight = 125; global int $gHIKControlRigCollapseExpandHeightDiff = 68; global int $gHIKControlRigAuxHeight = 0; // Used when resizing the custom rig ui global int $gHIKCustomRigFrameLayoutHeight = 235; global int $gHIKCustomRigCollapseExpandHeightDiff = 173; global int $gHIKCustomRigAuxHeight = 0; /////////////////////////////////////////////////////////////////////// // Global strings... /////////////////////////////////////////////////////////////////////// { string $hikStrSkeleton = (uiRes("m_hikGlobalUtils.kSkeleton")); string $hikStrControlRig = (uiRes("m_hikGlobalUtils.kControlRig")); string $hikStrCustomRig = (uiRes("m_hikGlobalUtils.kCustomRig")); string $hikStrRenameCharacter = (uiRes("m_hikGlobalUtils.kRenameCharacter")); string $hikStrEditSkeleton = (uiRes("m_hikGlobalUtils.kEditSkeleton")); string $hikStrEditDefinition = (uiRes("m_hikGlobalUtils.kEditDefinition")); string $hikStrEditControls = (uiRes("m_hikGlobalUtils.kEditControls")); string $hikStrEditCustomRig = (uiRes("m_hikGlobalUtils.kEditCustomRig")); string $hikStrCreateSkeleton = (uiRes("m_hikGlobalUtils.kCreateSkeleton")); string $hikStrCreateControlRig = (uiRes("m_hikGlobalUtils.kCreateControlRig")); string $hikStrCreateCharacterDefinition = (uiRes("m_hikGlobalUtils.kCreateCharacterDefinition")); string $hikStrCreateCustomRigMapping = (uiRes("m_hikGlobalUtils.kCreateCustomRigMapping")); string $hikStrQuickRigTool = (uiRes("m_hikGlobalUtils.kQuickRigTool")); string $hikStrEditHIKProperties = (uiRes("m_hikGlobalUtils.kEditHIKProperties")); string $hikStrResetHIKProperties = (uiRes("m_hikGlobalUtils.kResetHIKProperties")); string $hikStrLoadCharacterDefinition = (uiRes("m_hikGlobalUtils.kLoadCharacterDefinition")); string $hikStrSaveCharacterDefinition = (uiRes("m_hikGlobalUtils.kSaveCharacterDefinition")); string $hikStrLoadUIConfig = (uiRes("m_hikGlobalUtils.kLoadUIConfiguration")); string $hikStrRigAlignSync = (uiRes("m_hikGlobalUtils.kRigAlignSync")); string $hikStrImportCustomMapping = (uiRes("m_hikGlobalUtils.kImportCustomRigMapping")); string $hikStrExportCustomMapping = (uiRes("m_hikGlobalUtils.kExportCustomRigMapping")); string $hikStrImportSamples = (uiRes("m_hikGlobalUtils.kImportSamples")); string $hikStrImportHIKExample = (uiRes("m_hikGlobalUtils.kImportHIKExample")); string $hikStrImportAnimExample = (uiRes("m_hikGlobalUtils.kImportAnimExample")); string $hikStrReset = (uiRes("m_hikGlobalUtils.kReset")); string $hikStrLiveConnection = (uiRes("m_hikGlobalUtils.kLiveConnection")); string $hikStrIK = (uiRes("m_hikGlobalUtils.kIK")); string $hikStrFK = (uiRes("m_hikGlobalUtils.kFK")); string $hikStrHIKDefinition = (uiRes("m_hikGlobalUtils.kHIKDefinition")); string $hikStrEditProperties = (uiRes("m_hikGlobalUtils.kEditProperties")); string $hikStrResetProperties = (uiRes("m_hikGlobalUtils.kResetProperties")); string $hikStrMirrorMatching = (uiRes("m_hikGlobalUtils.kMirrorMatching")); string $hikStrConfirugreMirrorMatching = (uiRes("m_hikGlobalUtils.kConfigureMirrorMatching")); string $hikStrRigLook = (uiRes("m_hikGlobalUtils.kRigLook")); string $hikStrWire = (uiRes("m_hikGlobalUtils.kWire")); string $hikStrStick = (uiRes("m_hikGlobalUtils.kStick")); string $hikStrBox = (uiRes("m_hikGlobalUtils.kBox")); string $hikStrStancePose = (uiRes("m_hikGlobalUtils.kStancePose")); string $hikStrRigAlign = (uiRes("m_hikGlobalUtils.kRigAlign")); string $hikStrImportMapping = (uiRes("m_hikGlobalUtils.kImportMapping")); string $hikStrExportMapping = (uiRes("m_hikGlobalUtils.kExportMapping")); string $hikStrBakeToCustomRig = (uiRes("m_hikGlobalUtils.kBakeToCustomRig")); string $hikStrBakeCustomRig = (uiRes("m_hikGlobalUtils.kBakeCustomRig")); string $hikStrBakeLiveToCustomRig = (uiRes("m_hikGlobalUtils.kBakeLiveToCustomRig")); string $hikStrControls = (uiRes("m_hikGlobalUtils.kControls")); string $hikStrCreate = (uiRes("m_hikGlobalUtils.kCreate")); string $hikStrDefine = (uiRes("m_hikGlobalUtils.kDefine")); string $hikStrDelete = (uiRes("m_hikGlobalUtils.kDelete")); string $hikStrDeleteControlRig = (uiRes("m_hikGlobalUtils.kDeleteControlRig")); string $hikStrDeleteCustomRig = (uiRes("m_hikGlobalUtils.kDeleteCustomRig")); string $hikStrDefinition = (uiRes("m_hikGlobalUtils.kDefinition")); string $hikStrLockDefinition = (uiRes("m_hikGlobalUtils.kLockDefinition")); string $hikStrRename = (uiRes("m_hikGlobalUtils.kRename")); string $hikStrMapBones = (uiRes("m_hikGlobalUtils.kLoadDefinition")); string $hikStrExtractMapTemplate = (uiRes("m_hikGlobalUtils.kSaveDefinition")); string $hikStrStance = (uiRes("m_hikGlobalUtils.kStance")); string $hikStrOK = (uiRes("m_hikGlobalUtils.kOK")); string $hiktStrCancel = (uiRes("m_hikGlobalUtils.kCancel")); string $hikStrUnknown = (uiRes("m_hikGlobalUtils.kUnknown")); string $hikStrNone = (uiRes("m_hikGlobalUtils.kNone")); string $hikStrMapTranslation = (uiRes("m_hikGlobalUtils.kMapTranslation")); string $hikStrMapRotation = (uiRes("m_hikGlobalUtils.kMapRotation")); string $hikStrBakeToSkeleton = (uiRes("m_hikGlobalUtils.kBakeToSkeleton")); string $hikStrBakeSkeleton = (uiRes("m_hikGlobalUtils.kBakeSkeleton")); string $hikStrBakeLiveToSkeleton = (uiRes("m_hikGlobalUtils.kBakeLiveToSkeleton")); string $hikStrBakeToControlRig = (uiRes("m_hikGlobalUtils.kBakeToControlRig")); string $hikStrBakeControlRig = (uiRes("m_hikGlobalUtils.kBakeControlRig")); string $hikStrBakeRigBodyPart = (uiRes("m_hikGlobalUtils.kBakeRigBodyPart")); } /////////////////////////////////////////////////////////////////////// // Option variables... /////////////////////////////////////////////////////////////////////// if( !`optionVar -exists hikSegmentScaleCompensateIsOff` ) { // Default is false optionVar -intValue hikSegmentScaleCompensateIsOff false; } /////////////////////////////////////////////////////////////////////// // Local methods... /////////////////////////////////////////////////////////////////////// proc string doCreateCharacterWithName( string $nameHint ) { string $character; if( $nameHint == "" ) { $character = `createNode "HIKCharacterNode"`; } else { $character = `createNode "HIKCharacterNode" -name $nameHint`; } string $propertyState = hikCreatePropertyState(); connectAttr ($propertyState+".message") ($character+".propertyState"); return $character; } proc string[] getStateToSk( string $character ) { string $list[]; if( $character != "" ) { string $list1[] = `listConnections -type HIKState2GlobalSK ($character+".OutputCharacterDefinition")`; string $list2[] = `listConnections -type HIKState2SK ($character+".OutputCharacterDefinition")`; $list = stringArrayCatenate( $list1, $list2 ); } return $list; } proc string getActiveSolver(string $character) // Description: // Will return the solver that is currently active for a character // This solver can be the the character solver itself // or a retargeter or a liveClient node // { string $state2Sks[] = getStateToSk( $character ); for( $state2Sk in $state2Sks ) { string $solvers[] = `listConnections -s 1 -d 0 ( $state2Sk+".InputCharacterState")`; if( size( $solvers ) > 0 ) return $solvers[0]; } return ""; } /////////////////////////////////////////////////////////////////////// // Global methods... /////////////////////////////////////////////////////////////////////// global proc string hikGetCurrentCharacter() { global string $gHIKCurrentCharacter; return $gHIKCurrentCharacter; } global proc hikSetCurrentCharacter(string $character) { global string $gHIKCurrentCharacter; $gHIKCurrentCharacter = ( hikIsNoneCharacter( $character) ) ? "" : $character; } global proc string[] hikGetSceneCharacters() { return `ls -type HIKCharacterNode`; } // This function does not change any of the names returned // global proc string[] hikGetRawRemoteCharacters( int $onlyLiveClients ) { string $remotes[]; // Do a number of checks to see if we have a live client string $characterStateClients[] = `ls -type HIKCharacterStateClient`; // Return if there are no connections clients if ( size( $characterStateClients ) < 1 ) return $remotes; // Still an empty list string $servers[]; if ( $onlyLiveClients ) { // Find the servers for the live clients for ( $client in $characterStateClients ) { if ( `getAttr ( $client + ".live" )` ) $servers[size($servers)] = `getAttr ( $client + ".serverName" )`; } if ( size($servers) < 1 ) return $remotes; // Still an empty list } else { // Find all servers for ( $client in $characterStateClients ) $servers[size($servers)] = `getAttr ( $client + ".serverName" )`; } // Get a list of all remote characters // for the server names we have collected for ( $server in $servers ) { string $serverList[] = `HIKGetRemoteCharacterList -server $server`; $remotes = stringArrayCatenate( $remotes, $serverList ); } return $remotes; } global proc string[] hikGetRemoteCharacters() { // Get the name of the active character in the scene string $character = hikGetCurrentCharacter(); string $remotes[] = hikGetRawRemoteCharacters( true /* onlyLiveClients */ ); // Form the prefix appended to the remote characters that are // valid sources for the active character string $prefix = ( "Constraint::" + $character ); // For each remote character that is a valid source for the // active character, strip the `Constraint::` prefix and add // a `(remote)` suffix. If the remote character is not a valid // source, remove it from the string array. int $i; for ( $i=0; $i - name of the source character { // If the character is not enabled, we're in "None" state if( !hikIsCharacterEnabled($character) ) return (uiRes("m_hikGlobalUtils.kNone")); // Not necessarily a HIK solver node. Returns node // that drives the bones. string $solver = getActiveSolver( $character ); if( $solver == "" ) return (uiRes("m_hikGlobalUtils.kUnknown")); string $solverType = `nodeType $solver`; if( $solverType == "HIKRetargeterNode" ) return hikGetRetargetCharacterInput($character); else if( $solverType == "HIKCharacterStateClient" ) return ($character + "(remote)"); // Unknown source if( $solverType != "HIKSolverNode" ) return (uiRes("m_hikGlobalUtils.kUnknown")); // solverType is HIKSolverNode... // We can have three possible inputs at this stage. // 1) Stance Input // 2) Rig Input // 3) Retargeting input // Are we in "Stance" input? if( `getAttr ($solver + ".InputStance")` ) return (uiRes("m_hikGlobalUtils.kStance")); // Not in stance, then assume a rig input. Try to differentiate between // rig input or rig input driven through a retargeter. // So check if any retargeting layer has a weight > .5 // Note: This will only be for legacy code. In future we'll have // a direct connection to the character node // TODO: can this be removed?? string $charactersLayers[] = hikGetRetargetCharacters( $character, 1 ); for( $i = 0; $i< size($charactersLayers);$i+=2 ) { string $layer = $charactersLayers[$i+1]; if( $layer!="" && (`getAttr ($layer+".weight")` > 0.5) ) { return $charactersLayers[$i]; } } // Assume rig input, otherwise... return (uiRes("m_hikGlobalUtils.kControlRig")); } global proc int hikIsNoneCharacter( string $lNewCharacter ) { if( $lNewCharacter == hikNoneString() ) return true; return false; } global proc string hikNoneString() { return ( uiRes( "m_hikGlobalUtils.kNone" ) ); } global proc int hikIsCharacterEnabled(string $pCharacter) { string $lGlobal2SkNode = hikGetStateToGlobalSk( $pCharacter, 0 ); if( $lGlobal2SkNode != "" ) { return RetargeterIsConnected( RetargeterGetName( $pCharacter ) ); } else { // No custom Rig, look if characterized skeleton is driven // If hips rotation is driven by the characterstate we can assume it is active string $nodeName = GetHIKNodeName(1); string $skNode[] = `listConnections -s 1 -d 0 ($pCharacter+"."+$nodeName)`; if( size($skNode) > 0 ) { string $state2sk[] = hikGetState2SKFromCharacter( $pCharacter ); if( size($state2sk)>0 ) { if( `isConnected ($state2sk[0]+"."+$nodeName+"Rx") ($skNode[0]+".rotateX")` ) { return true; } else { // There maybe a pairblend between the 2 nodes // If the state2sk is connected to a pair blend then assume constraint is active string $pairBlend[] = `listConnections -type "pairBlend" -s 0 -d 1 ($state2sk[0]+"."+$nodeName+"R")`; if( size( $pairBlend ) > 0 ) { return true; } /* This code should not be required because we connect the compound plug else { string $pairBlend[] = `listConnections -type "pairBlend" -s 0 -d 1 ($state2sk[0]+"."+$nodeName+"Rx")`; if( size( $pairBlend ) > 0 ) { return true; } } */ } } } return false; } } global proc int hikHasCustomRig(string $character) // Description: // Return 1 if this character has a custom rig // mapping // { return ( objExists( $character ) ) ? RetargeterExists( RetargeterGetName( $character ) ) : false ; } global proc int hikHasControlRig(string $character) // Description: // Return 1 if this character has a control rig // { return ( size(hikGetControlRig($character)) > 0); } global proc int hikHasDefinition(string $character) // Description: // Return 1 if this character has a skeleton definition. // This definition doesn't need to be valid, just needs to // exist. // { return ( $character != "" && objExists( $character ) ); } global proc int hikHasSkeletonGenerator(string $character) // Description: // Return 1 if this character's skeleton was created with // the skeleton generator tool (and thus can be unlocked // and edited again) { return (hikGetSkeletonGeneratorNode($character) != ""); } global proc int hikIsDefinitionLocked(string $character) // Description: // Return 1 if the skeleton definition is locked // { int $ret = hikHasDefinition($character); if ( $ret ) { string $lockPlugName = $character + ".InputCharacterizationLock"; $ret = `getAttr $lockPlugName`; } return $ret; } global proc int hikIsCharacterLiveActive( string $character ) // Description: // Return 1 if the character is live and active // { string $liveNode = hikGetLiveStateClient( $character, 0 ); return $liveNode != "" && `getAttr ( $liveNode + ".live" )` && hikIsCharacterInputTypeLive( $character) && hikIsCharacterEnabled( $character ); } // This proc execute the command asyncronously when the runTime specified, in secconds, is over. global proc hikExecuteDelayedCommand(int $runTime, string $command) { python("import maya.app.hik.timer;" +"maya.app.hik.timer.startTimer( " + $runTime + ", \"" + encodeString($command) + "\")"); } global proc string hikCreatePropertyState() { string $property2State = `createNode "HIKProperty2State" -name "HIKproperties#"`; // overwrite the default values the HIKProperty node inherits from the HIK3 library // If/when the library updates its default values, this call can be removed hikSetRollBonesDefaultsOnPropertyState($property2State); return $property2State; } global proc hikConnectPropState(string $pOutput, string $pInput) { string $Output = $pOutput + ".OutputPropertySetState"; string $Input = $pInput+ ".InputPropertySetState"; catchQuiet( `connectAttr -f $Output $Input` ); } global proc string hikCreateCharacterNoUpdateOfCurrent() { return doCreateCharacterWithName( "" ); } // Create a new Character -- but give it a name that we want // such as Character1. If the name is already taken, then // Maya will modify it to make it unique. global proc string hikCreateCharacter( string $nameHint ) { global string $gHIKCurrentCharacter; string $newCharacter = doCreateCharacterWithName( $nameHint ); $gHIKCurrentCharacter = $newCharacter; string $fmt = (uiRes("m_hikGlobalUtils.kCharacterCreated2")); string $messageCharacterCreated = `format -s $newCharacter $fmt`; print ($messageCharacterCreated); return $newCharacter; } global proc hikConnectAttribute(string $pNodeOut, string $pAttrOut, string $pNodeIn, string $pAttrIn) { if( $pNodeOut == "" || $pNodeIn == "" ) { return; } string $errorMessageAttributeNotFound = " Attribute Not Found: "; if(`attributeQuery -node $pNodeOut -exists $pAttrOut` ) { if(`attributeQuery -node $pNodeIn -exists $pAttrIn`) { string $in = $pNodeIn + "." + $pAttrIn; string $out = $pNodeOut + "." + $pAttrOut; string $existingConns[] = `listConnections -s 1 -d 0 $in`; if(`getAttr -lock $in` || size($existingConns) > 0) { string $errorMessageAttributeLockedOrConnected = " Attribute locked or connected: "; $errorMessageAttributeLockedOrConnected += $in; $errorMessageAttributeLockedOrConnected += "\n"; error($errorMessageAttributeLockedOrConnected); } else { connectAttr -f $out $in; } } else { string $message = $errorMessageAttributeNotFound + $pNodeIn + "." + $pAttrIn + "\n"; error($message); } } else { string $message = $errorMessageAttributeNotFound + $pNodeOut + "." + $pAttrOut + "\n"; error($message); } } global proc hikConnectAttributeInv(string $pNodeIn, string $pAttrIn, string $pNodeOut, string $pAttrOut) { hikConnectAttribute($pNodeOut, $pAttrOut, $pNodeIn, $pAttrIn); } global proc hikConnectArrayAttribute(string $pNodeOut, string $pAttrOut, int $pIndexOut, string $pNodeIn, string $pAttrIn, int $pIndexIn) { string $in = $pNodeIn + "." + $pAttrIn; string $out = $pNodeOut + "." + $pAttrOut; if ( $pIndexIn >= 0) $in = $in + "[" + $pIndexIn + "]"; if ( $pIndexOut >= 0) $out = $out + "[" + $pIndexOut + "]"; connectAttr -f $out $in; } global proc string hikGetNodeNameFromNode(string $node) { string $attr[] = `listAttr -string "ControlSet" $node`; if(size($attr) > 0) { string $conn[] = `listConnections -p on ($node + "." + $attr[0])`; if(size($conn) > 0) { string $plug[] = stringToStringArray($conn[0], "."); return $plug[1]; } } return ""; } // Get Retargeter Nodes from a Character global proc string[] hikGetRetargeterFromCharacter(string $pCharacter) { string $lRetargetAttr = $pCharacter + ".OutputCharacterDefinition"; return `listConnections -type HIKRetargeterNode $lRetargetAttr`; } // Get Solver Node from Character global proc string[] hikGetSolverFromCharacter(string $pCharacter) { string $lSolverAttr = $pCharacter + ".OutputCharacterDefinition"; return `listConnections -type HIKSolverNode $lSolverAttr`; } // // Undo related code - turn off undo and restore the // state. // Return value of hikTurnOffUndo() should be passed // to hikRestoreUndo(); // global proc int hikTurnOffUndo() { int $undoOn = `undoInfo -query -stateWithoutFlush`; if ($undoOn) undoInfo -stateWithoutFlush off; return $undoOn; } global proc hikRestoreUndo( int $undoOn ) { if ($undoOn) undoInfo -stateWithoutFlush on; } global proc string hikGetDefaultResourcesDir() { string $scriptPath = substitute( "Mel procedure found in: ", ( string )`whatIs "hikCreateCharacterControlsDockableWindow"`, ""); string $basename = `dirname $scriptPath`; string $resources = (`about -q -mac`) ? "Resources" : "resources"; return ($basename + "/../../" + $resources + "/CharacterControls/" ); }