// =========================================================================== // 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: AEcontainerMain // // Description Name; // Creates the attribute editor controls for the containerBase node // (the base class of nodes that are able to be containers) // // Input Value: // nodeName // // Output Value: // None // global string $gAttrEdInfos[]; global int $gNumAttrEds=0; proc string getField( string $attrEdInfo, int $childIndex ) // // Description: // Given the Attribute Editor info UI element, retrieve the child at the // given index, and return it. // // Inputs: // $attrEdInfo : Attribute Editor information // $childIndex : Child index // // Return Value: // Child // { string $children[] = `formLayout -q -ca $attrEdInfo`; int $numChildren = size( $children ); if( $childIndex >= $numChildren ){ error( (uiRes("m_AEcontainerMain.kGetFieldErr")) ); } return( $children[$childIndex] ); } proc setAttrEdIntField( string $attrEdInfo, int $childIndex, int $val ) // // Description: // Given the attrEd info UI element, retrieve the child at the given index, // and set it's int field value. // // Inputs: // $attrEdInfo : Attribute Editor information // $index : Child index // // Return Value: // Child label or "" // { string $intField = getField( $attrEdInfo, $childIndex ); if( !`intField -exists $intField` ){ error( uiRes( "m_AEcontainerMain.kGetFieldErr") ); } intField -e -v $val $intField; } proc int getAttrEdIntField( string $attrEdInfo, int $childIndex ) // // Description: // Given the attrEd info UI element, retrieve the child at the given index, // and return it's intField value. // // Inputs: // $attrEdInfo : Attribute Editor information // $index : Child index // // Return Value: // intField value or 0 // { string $intField = getField( $attrEdInfo, $childIndex ); if( !`intField -exists $intField` ){ error( uiRes( "m_AEcontainerMain.kGetFieldErr") ); } return(`intField -q -v $intField`); } global proc setAttrEdTextField( string $attrEdInfo, int $childIndex, string $val ) // // Description: // Given the attrEd info UI element, retrieve the child at the given index, // and set it's text label. // // Inputs: // $attrEdInfo : Attribute Editor information // $index : Child index // // Return Value: // Child label or "" // { string $text = getField( $attrEdInfo, $childIndex ); if( !`text -exists $text` ){ error( uiRes( "m_AEcontainerMain.kGetFieldErr") ); } text -e -label $val $text; } proc string getTextLabel( string $text ) // // Description: // Given a text field $text, return the value of its label. On linux, the // empty value is returned as " ", so check for that value and return "" // instead. // // Inputs: // $text : text field // // Return value: // label of text field, "" if none or " ". // { string $value = `text -q -label $text`; if( $value == " " ){ $value = ""; } return( $value ); } global proc string getAttrEdTextField( string $attrEdInfo, int $childIndex ) // // Description: // Given the attrEd info UI element, retrieve the child at the given index, // and return it's text label. Return "" if none. // // Inputs: // $attrEdInfo : Attribute Editor information // $index : Child index // // Return Value: // Child label or "" // { string $text = getField( $attrEdInfo, $childIndex ); if( !`text -exists $text` ){ error( uiRes( "m_AEcontainerMain.kGetFieldErr") ); } return( getTextLabel( $text ) ); } proc string getNodeName( string $attrEdInfo ) // // Description: // Given attrEd info, retrieve node name. // // Inputs: // $attrEdInfo : Attribute Editor information // // Return Value: // Node name. // { return( getAttrEdTextField( $attrEdInfo, 0 ) ); } proc setNodeName( string $attrEdInfo, string $nodeName ) // // Description: // Given attrEd info, set the value of the node name. // // Inputs: // $attrEdInfo : Attribute Editor information // $nodeName : Name of node // // Return Value: // None. // { setAttrEdTextField( $attrEdInfo, 0, $nodeName ); } proc int getViewMode( string $attrEdInfo ) // // Description: // Given attrEd info, get the view mode // // Inputs: // $attrEdInfo : Attribute Editor information // // Return Value: // View mode. // { return(getAttrEdIntField( $attrEdInfo, 1 ) ); } proc setViewMode( string $attrEdInfo, int $viewMode ) // // Description: // Given attrEd info, set the value of the node name. // // Inputs: // $attrEdInfo : Attribute Editor information // $viewMode : view mode // // Return Value: // None. // { setAttrEdIntField( $attrEdInfo, 1, $viewMode ); } proc string getTemplateName( string $attrEdInfo ) // // Description: // Given attrEd info, retrieve name of template. // // Inputs: // $attrEdInfo : Attribute Editor information // // Return Value: // Name of template. // { return( getAttrEdTextField( $attrEdInfo, 2 ) ); } proc setTemplateName( string $attrEdInfo, string $templateName ) // // Description: // Given attrEd info, set the value of the template name. // // Inputs: // $attrEdInfo : Attribute Editor information // $templateName : Name of template // // Return Value: // None. // { setAttrEdTextField( $attrEdInfo, 2, $templateName ); } proc string getViewName( string $attrEdInfo ) // // Description: // Given attrEd info, retrieve name of view. // // Inputs: // $attrEdInfo : Attribute Editor information // // Return Value: // Name of view. // { return( getAttrEdTextField( $attrEdInfo, 3 ) ); } proc setViewName( string $attrEdInfo, string $viewName ) // // Description: // Given attrEd info, set the value of the view name. // // Inputs: // $attrEdInfo : Attribute Editor information // $viewName : Name of view // // Return Value: // None. // { setAttrEdTextField( $attrEdInfo, 3, $viewName ); } proc string getBorderConnectionsLayout( string $attrEdInfo ) // // Description: // Given attrEd info, retrieve name of border connections layout. // // Inputs: // $attrEdInfo : Attribute Editor information // // Return Value: // Name of border connections layout. // { return( getAttrEdTextField( $attrEdInfo, 4 ) ); } proc setBorderConnectionsLayout( string $attrEdInfo, string $bcLayout ) // // Description: // Given attrEd info, set the value of the border connections layout. // // Inputs: // $attrEdInfo : Attribute Editor information // $bcLayout : Name of border connections layout // // Return Value: // None. // { setAttrEdTextField( $attrEdInfo, 4, $bcLayout ); } proc string getTemplateNameLayout( string $attrEdInfo ) // // Description: // Given attrEd info, retrieve name of template name layout. // // Inputs: // $attrEdInfo : Attribute Editor information // // Return Value: // Name of template name layout. // { return( getAttrEdTextField( $attrEdInfo, 6 ) ); } proc setTemplateNameLayout( string $attrEdInfo, string $tnLayout ) // // Description: // Given attrEd info, set the value of the template name layout. // // Inputs: // $attrEdInfo : Attribute Editor information // $tnLayout : Name of template name layout // // Return Value: // None. // { setAttrEdTextField( $attrEdInfo, 6, $tnLayout ); } proc string getViewNameLayout( string $attrEdInfo ) // // Description: // Given attrEd info, retrieve name of view name layout. // // Inputs: // $attrEdInfo : Attribute Editor information // // Return Value: // Name of view name layout. // { return( getAttrEdTextField( $attrEdInfo, 7 ) ); } proc setViewNameLayout( string $attrEdInfo, string $vnLayout ) // // Description: // Given attrEd info, set the value of the view name layout. // // Inputs: // $attrEdInfo : Attribute Editor information // $vnLayout : Name of view name layout // // Return Value: // None. // { setAttrEdTextField( $attrEdInfo, 7, $vnLayout ); } proc string getTemplatePathLayout( string $attrEdInfo ) // // Description: // Given attrEd info, retrieve name of template path layout. // // Inputs: // $attrEdInfo : Attribute Editor information // // Return Value: // Name of template path layout. // { return( getAttrEdTextField( $attrEdInfo, 8 ) ); } proc setTemplatePathLayout( string $attrEdInfo, string $tpLayout ) // // Description: // Given attrEd info, set the value of the template path layout. // // Inputs: // $attrEdInfo : Attribute Editor information // $tpLayout : Name of template path layout // // Return Value: // None. // { setAttrEdTextField( $attrEdInfo, 8, $tpLayout ); } proc debugPrint(string $msg) { print ($msg + "\n"); } proc int parentAttrIsPublished(string $plug, string $container) { // Gracefully handle unbound attrs if (size($plug) == 0) { return false; } int $isPublished = 0; // First quick check: Does it even have a parent? // string $currNode = plugNode($plug); string $currAttr = plugAttrNoIndex($plug); string $pAttr[] = `attributeQuery -listParent -node $currNode $currAttr`; if (size($pAttr)) { // Now since the attribute can be multi-levels deep with multis, we // need to form the parents name properly. // string $buff[]; tokenize($plug,".",$buff); int $foundParent = 0; string $parentName = ($currNode+"."); for ($ii = 1; $ii < size($buff)-1; $ii++) { string $buff2[]; tokenize($buff[$ii],"[",$buff2); $parentName += ($buff[$ii]); if ($buff2[0] == $pAttr[0]) { $foundParent = 1; } else { $parentName += "."; } } if (! $foundParent) { $parentName += $pAttr[0]; } if (`objExists $parentName`) { string $boundAttrs[] = `container -q -bindAttr $container`; $isPublished = stringArrayContains($parentName,$boundAttrs); } } return $isPublished; } global proc doNodePublish(string $publishName, string $container,int $publish) { string $sel[] = `ls -sl`; if ($publish && size($sel) == 0) { error((uiRes("m_AEcontainerMain.kMustSelectNodeToPublish"))); } if ($publish) { string $selNodeContainer = `container -q -findContainer { $sel[0] }`; if ($selNodeContainer != $container) { error((uiRes("m_AEcontainerMain.kNoPublishExternal"))); } string $pnames[] = `containerPublish -q -pn $container`; if (!stringArrayContains($publishName,$pnames)) { string $pcmd = ("containerPublish -publishNode \""+$publishName+"\" \"\" "+$container); evalEcho $pcmd; } string $bcmd = ("containerPublish -bindNode \""+$publishName+"\" \""); $bcmd += ($sel[0]+"\" "+$container); evalEcho $bcmd; } else { string $ubCmd = ("containerPublish -ubn \""+$publishName+"\" "+$container); evalEcho $ubCmd; string $upCmd = ("containerPublish -upn \""+$publishName+"\" "+$container); evalEcho $upCmd; } } global proc publishNodeNamePrompt(string $container) { string $proposedName = "name"; $uniqueProposedName = findUniqueAliasName($container,$proposedName,0); string $OK = (uiRes("m_AEcontainerMain.kOk")); string $cancel = (uiRes("m_AEcontainerMain.kCancel")); string $result = `promptDialog -title (uiRes("m_AEcontainerMain.kPublishNode")) -message (uiRes("m_AEcontainerMain.kSpecifyName")) -text $uniqueProposedName -button $OK -button $cancel -defaultButton $OK -cancelButton $cancel -dismissString $cancel`; if ($result == $OK) { string $publishName = `promptDialog -q`; doNodePublish($publishName,$container,1); } } // templateAvailable, templateValidate: // These routines checks if a template is available or not. // The return code indicates whether or not the template is available. // If the template is not already loaded, it will attempt to do so. // templateAvailable is as silent as possible, since it can be called // repeatedly and is more of a check than a validating routine. // templateValidate is similar but issues errors if the template // isn't there. proc int templateAvailable(string $template, string $templatePath) { int $status = 0; if (size($template) > 0) { $status = `containerTemplate -q -exists $template`; if (!$status) { $status = !catch(`containerTemplate -silent -load -fn $templatePath $template`); } } return $status; } proc int templateValidate(string $template, string $templatePath) { int $status = 0; if (size($template) > 0) { $status = `containerTemplate -q -exists $template`; if (!$status) { $status = !catch(`containerTemplate -load $template`); if (!$status) { string $fmt = (uiRes("m_AEcontainerMain.kTemplateNotValid")); string $msg = `format -stringArg $template $fmt`; error($msg); } } } return $status; } global proc AEcontainerViewNameNew( string $attrEdInfo , string $plug) // // Create a button listing the view name with a popup menu giving the // choices // { setUITemplate -pst attributeEditorTemplate; string $layout = `rowLayout -nc 3`; setViewNameLayout( $attrEdInfo, $layout ); text -al "right" -l (uiRes("m_AEcontainerMain.kViewName")); string $viewName = `getAttr $plug`; if ($viewName == "") { button -label (uiRes("m_AEcontainerMain.kNone")) aeViewButton; } else { button -label $viewName aeViewButton; } popupMenu -button 1 aeViewPopupMenu; } global proc AEcontainerViewNameReplace( string $attrEdInfo , string $plug) // // Fill in the view popup menu with the available views // { string $layout = getViewNameLayout( $attrEdInfo ); string $aeViewButton = ($layout + "|aeViewButton"); string $aeViewPopupMenu = ($aeViewButton + "|aeViewPopupMenu"); if (!`popupMenu -exists $aeViewPopupMenu`) { return; } string $viewName = `getAttr $plug`; string $container = plugNode($plug); string $template = `getAttr ($container+".templateName")`; string $templatePath = `getAttr ($container+".templatePath")`; string $viewList[]; if (templateAvailable($template, $templatePath)) { $viewList = `containerTemplate -q -viewList $template`; } // delete previous menu items // popupMenu -e -deleteAllItems $aeViewPopupMenu; setParent -m $aeViewPopupMenu; // create the "None" menu item // string $redrawCmd = "AEcontainerViewNameCB " + $attrEdInfo + " " + $plug; string $setAttrCmd = ("setAttr -type \"string\" "+$container+".viewName \"\""); string $label = uiRes("m_AEcontainerMain.kNone"); string $buttonCmd = "button -e -label \""+ $label + "\" " + $aeViewButton; menuItem -label (uiRes("m_AEcontainerMain.kNone")) -command ($setAttrCmd+";"+$buttonCmd+";"+$redrawCmd); // add menu items for the available views // int $selectView = -1; for ($ii = 0; $ii < size($viewList); $ii++) { string $currView = ("\""+$viewList[$ii]+"\""); $setAttrCmd = ("setAttr -type \"string\" "+$container+".viewName "+$currView); $buttonCmd = "button -e -label "+$currView+" " + $aeViewButton; menuItem -label ($viewList[$ii]) -c ($setAttrCmd+";"+$buttonCmd+";"+$redrawCmd); if ($viewName == $viewList[$ii]) { $selectView = $ii; } } // change the button title to the view name // if ($selectView >= 0) { button -e -label $viewList[$selectView] $aeViewButton; } else { button -e -label (uiRes("m_AEcontainerMain.kNone")) $aeViewButton; } setParent ..; } global proc containerPublishedNew( string $attrEdInfo , string $attrName) { string $layout = `columnLayout -adj true containerMemberLayout`; setBorderConnectionsLayout( $attrEdInfo, $layout ); setParent ..; containerPublishedCommon( $attrEdInfo, "", $layout, $attrName ); } global proc containerPublishedReplace( string $attrEdInfo , string $attrName) { string $layout = getBorderConnectionsLayout( $attrEdInfo ); containerPublishedCommon( $attrEdInfo, "", $layout, $attrName ); } // Determines if published attribute section requires a rebuild or not, and // if we need to update the Asset Editor(s). // proc int publishedAttrRebuildRequired( string $attrEdInfo, string $nodeName, int $primary ) // // Description: // Determing if the attribute editor and/or some of the asset editor(s) // need to be updated. See Return Value for the possible return values. // // Inputs: // $nodeName : node being edited when callback triggered // $primary : if true, this is the primary trigger; if false, secondary // // Return Value: // true iff editor with data $attrEdInfo should be refreshed. // { int $refreshReqd = 0; // Get current view attribute values // We only do the refresh if something has changed int $viewMode = `getAttr ($nodeName + ".viewMode")`; string $templateName = `getAttr ($nodeName + ".templateName")`; string $viewName = `getAttr ($nodeName + ".viewName")`; string $attrEdNodeName = getNodeName( $attrEdInfo ); if( $nodeName != $attrEdNodeName ){ // Refresh if this is the primary call, else we're not interested in // this container node, so don't // $refreshReqd = $primary; } else { // This call was triggered either as the primary update, or as a // secondary update, for an editor that is editing the same node as // the primary. // // Refresh always if viewmode changes; similarly, if template changes, // refresh always since that could mean the autopublishing of some // new, unbound attributes. // int $attrEdViewMode = getViewMode( $attrEdInfo ); string $attrEdTemplateName = getTemplateName( $attrEdInfo ); string $attrEdViewName = getViewName( $attrEdInfo ); // Refresh on view name change only when // using template view mode // if ( ($attrEdTemplateName != $templateName) || ($attrEdViewMode != $viewMode) || ( ( $attrEdViewName != $viewName) && ( $viewMode == 1 ) ) ) { $refreshReqd = 1; } } return $refreshReqd; } // Used for AE only: saves published attribute view // information for determining if rebuild required or not. proc publishedAttrRebuildReset( string $attrEdInfo, string $nodeName) { int $viewMode = `getAttr ($nodeName + ".viewMode")`; string $templateName = `getAttr ($nodeName + ".templateName")`; string $viewName = `getAttr ($nodeName + ".viewName")`; setNodeName( $attrEdInfo, $nodeName ); setViewMode( $attrEdInfo, $viewMode ); setTemplateName( $attrEdInfo, $templateName ); setViewName( $attrEdInfo, $viewName ); } proc int attrIsMsg( string $attr ) // // If the given attribute is of type message, return true // { string $filtered[] = `listAttr -hasData $attr`; return( size($filtered) == 0 ); } proc int isTripleAttr(string $attr) { if( attrIsMsg( $attr ) ){ return 0; } string $attrType = `getAttr -type $attr`; if ($attrType == "float3" || $attrType == "double3") { return 1; } return 0; } // // Add a UI control for an attribute that is not published // on the container. // A placeholder entry is created that shows only // the label and is disabled (dimmed). // proc addUnPublishedAttrControl(string $label) { setUITemplate -pst attributeEditorTemplate; string $createdControl = `rowLayout -nc 3`; text -al "right" -l $label -enable 0 nameTxt; separator sep; setUITemplate -ppt; setParent ..; } // Add a UI control for a published attribute that can't be // displayed completely in the AE. // // What we do is dependent on how the attribute is connected: // * connected as an input: disabled text box and button // that traverses to the input node // * connected as an output: disabled text box and button // that traverses to the first output node // * unconnected: separator and button indicating it is not connected // * unbound attributes: only a separator // // Arguments: // $attr = published attribute or "" for unbound attributes // $label = published name to serve as label for the control // proc addUnDisplayableAttrControl(string $attr, string $label, string $annotation) { setUITemplate -pst attributeEditorTemplate; string $createdControl = `rowLayout -nc 3`; text -al "right" -l $label -annotation $annotation -enable 1 nameTxt; string $image; string $node; string $inConns[], $outConns[]; if ($attr != "") { $inConns = `listConnections -s 1 -d 0 -p 1 $attr`; $outConns = `listConnections -s 0 -d 1 -p 1 $attr`; } if (size($inConns) > 0) { textField -en 0 -text $inConns[0]; $image = "inArrow.png"; string $connNodes[] = `listConnections -s 1 -d 0 $attr`; $node = $connNodes[0]; } else if (size($outConns) > 0) { string $connNodes[] = `listConnections -s 0 -d 1 $attr`; for ($ii = 0; $ii < size($connNodes); $ii++) { // if the only connection is that it is published, don't // show that // if (nodeType($connNodes[$ii]) != "container" && nodeType($connNodes[$ii]) != "hyperLayout") { textField -en 0 -text $outConns[$ii]; $image = "outArrow.png"; $node = $connNodes[$ii]; break; } } } if (size($node) == 0) { $image = "navButtonUnconnected.png"; separator; } if ("" != $attr) { string $button = `symbolButton -image $image`; if (size($node) > 0) { symbolButton -e -c ("showEditor "+$node) $button; } } setUITemplate -ppt; setParent ..; } // Callback from AEcontainerFilenameAttrBrowser (or // AEcontainerDirnameAttrBrowser) to update the attribute's // value global proc int AEcontainerFilenameAttrCB( string $fileAttribute, string $filename, string $fileType ) { setAttr $fileAttribute -type "string" $filename; string $currentDir = `workspace -q -dir`; retainWorkingDirectory ($currentDir); return true; } // This launches a generic filename browser to assign // a value to a published attribute that is used as a filename global proc AEcontainerFilenameAttrBrowser( string $cmd ) { // Don't ask for a specific type of file, let the browser // display all the extensions it knows about. We don't know // what type of filename the user needs on a published attr. fileBrowser ($cmd, (uiRes("m_AEcontainerMain.kOpen")), "", 0); } // This launches a directory name browser to assign // a value to a published attribute that is used as a // directory name global proc AEcontainerDirnameAttrBrowser( string $cmd ) { // Prompt for a directory name fileBrowser ($cmd, (uiRes("m_AEcontainerMain.kOpen1")), "", 4); } // This determines whether a published attribute is used as // a filename. proc int attrIsUsedAsFilename(string $plugName) { if (size(`listAttr -usedAsFilename $plugName`) > 0) { return 1; } return 0; } // This determines whether a published attribute is used as // a directory name. proc int attrIsUsedAsDirname(string $plugName) { // See bug 306145 re: generic handling of this logic if (attrIsUsedAsFilename($plugName)) { if ((`nodeType $plugName` == "cacheFile") && (plugAttr($plugName) == "cachePath")) { return 1; } } return 0; } // Add a UI control for a published attribute that is used // as a filename. This also includes special handling for those // that expect directory name. // // Arguments: // $attr = published attribute // $label = published name to serve as label for the control // $annotation = annotation // proc addFilenameAttrControl(string $plugName, string $label, string $annotation) { setUITemplate -pst attributeEditorTemplate; $createdControl = `rowLayout -nc 3 -annotation $annotation`; text -label $label -annotation $annotation; textField -annotation $annotation fileNameField ; symbolButton -image "navButtonBrowse.png" -annotation $annotation browser; connectControl -fileName fileNameField $plugName; string $command = "AEcontainerFilenameAttrCB " + " "+$plugName; // If this is actually expecting a directory name, use a // different browser. See also bug 306145. if (attrIsUsedAsDirname($plugName)) { button -e -c ("AEcontainerDirnameAttrBrowser \"" + $command + "\"" ) browser; } else { button -e -c ("AEcontainerFilenameAttrBrowser \"" + $command + "\"" ) browser; } setParent ..; setUITemplate -ppt; } proc addPublishedAttrControl(string $attr, string $label, string $annotation) // // Add a UI control for the attribute with the specified label. // If the attribute is a double or float, make a slider. // If the attribute is an enum, make an option box. // If the attribute is a boolean, make a check box. // { if( size($attr) == 0 ){ // Unbound name, no type info // addUnDisplayableAttrControl($attr, $label, $annotation); return; } string $publishee = `connectionInfo -getExactSource $attr`; // In case an unbound plug was passed into this routine // handle it as undisplayable. if ($publishee == "") { // Unbound name, no type info // addUnDisplayableAttrControl($attr, $label, $annotation); return; } string $node = plugNode($publishee); string $endAttr = plugAttrNoIndex($publishee); // If a node with a swatch has a .message attribute published, display the // swatch now, with the appropriate label. // if( $endAttr == "message" ){ if( hasSwatch( $node ) ){ if( !`exists AEswatchDisplayNew` ){ eval("source \"AEswatchDisplay.mel\""); } columnLayout; AEswatchDisplayNew( $node, $publishee ); if( `text -exists swatchLabel` ){ text -e -label $label swatchLabel; } setParent ..; return; } } if (`attributeQuery -hidden -node $node $endAttr`) { return; } // If the attribute is a compound, try displaying it at the parent // level. If that fails, then display each child separately. // string $children[] = `attributeQuery -listChildren -node $node $endAttr`; if (size($children) > 0) { if (`attrControlGrp -q -handlesAttribute $attr`) { attrControlGrp -attribute $attr -label $label -annotation $annotation; } else if( (`objectType -isa "ramp" $node`) && ((`plugAttr $publishee`) == "colorEntryList" ) ){ // We have the color entry list for a ramp node, so show that type // of ramp // if( !`exists AEmakeRampInteractiveNew` ){ eval("source \"AErampTemplate.mel\""); } AEmakeRampInteractiveNew( ($node + ".colorEntry1"), ($node + ".colorEntry2"), ($node + ".colorEntry3"), ($node + ".colorEntry4"), ($node + ".colorEntry5") ); } else if ( ($publishee == ($node + "." + $endAttr) ) && (size(`listAttr -ramp $publishee`) > 0) ) { // Only show the ramp if the multi parent is published // string $label = `attributeName -nice $attr`; frameLayout -label $label -borderVisible true -collapsable true -labelVisible true -collapse false; if( !`exists AEmakeRampControlInteractiveNew` ){ eval("source \"AEaddRampControl.mel\""); } AEmakeRampControlInteractiveNew($publishee); // Pop column layout created by above call, and frame layout // setParent ..; setParent ..; } else { for ($child in $children) { string $childAttr = ($publishee+"."+$child); if (! `objExists $childAttr`) { continue; } if (`attributeQuery -multi -node $node $child`) { continue; } else { // Don't propogate annotation addPublishedAttrControl($childAttr,$label+"_"+$child, ""); } } } return; } string $attrShortNames[] = `listAttr -shortNames $attr`; string $attrShortName = ($node+"."+$attrShortNames[0]); // Set slider min and max for each attribute // Each attribute defaults to a range of [-25, 25] float $min = -25.0; float $max = 25.0; string $pNode = plugNode($publishee); string $pAttr = plugAttrNoIndex($publishee); if (`attributeQuery -node $pNode -softMinExists $pAttr`) { float $smin[] = `attributeQuery -node $pNode -softMin $pAttr`; $min = $smin[0]; } if (`attributeQuery -node $pNode -softMaxExists $pAttr`) { float $smax[] = `attributeQuery -node $pNode -softMax $pAttr`; $max = $smax[0]; } if ( "" != `match "\\.t[xyz]$" $attrShortName` ) { // Translate attributes (.tx, .ty, .tz) should have a range of // [-100, 100] $min = -100.0; $max = 100.0; } else if ( "" != `match "\\.r[xyz]$" $attrShortName` ) { // Rotate attributes (.rx, .ry, .rz) should have a range of // [-360, 360] $min = -360.0; $max = 360.0; } else if ( "" != `match "\\.s[xyz]$" $attrShortName` ) { // Scale attributes (.sx, .sy, .sz) should have a range of // [-10, 10] $min = -10.0; $max = 10.0; } string $attrType; if( !attrIsMsg( $attr ) ){ $attrType = `getAttr -type $attr`; } switch ( $attrType ) { case "double": case "float": case "long": case "long long int": case "byte": case "short": case "doubleAngle": case "doubleLinear": case "floatAngle": case "floatLinear": case "time": // attrFieldSliderGrp sliders won't show up unless a min and max // for the control is specified. Use `minfloat` and `maxfloat` to enusre // the user is not limited manually entering a value into the // field. attrFieldSliderGrp -enable 1 -min `minfloat` -max `maxfloat` -sliderMinValue $min -sliderMaxValue $max -label $label -annotation $annotation -attribute $attr; break; case "bool": $checkBox = `checkBoxGrp -label $label -annotation $annotation -l1 ""`; connectControl -index 2 $checkBox $attr; break; case "enum": attrEnumOptionMenuGrp -label $label -annotation $annotation -attribute $attr; break; case "string": if (attrIsUsedAsFilename($attr)) { addFilenameAttrControl($attr, $label, $annotation); } else { attrControlGrp -label $label -attribute $attr -annotation $annotation; } break; default: addUnDisplayableAttrControl($attr, $label, $annotation); break; } } // Format an annotation string to use with published attrs proc string formatItemAnnotation(string $assetInfo, int $isGroup, string $label, string $attrType, string $desc) { string $annotString; string $fmt; // The information we display depends on what is available and // which UI it is for (asset editor or AE). // TODO: could add more info if/when we could support multiple lines // in the annotations. // Asset Editor: if (size($assetInfo) > 0) { if ($isGroup) // Group fields leave empty { return $annotString; // empty } // Use type information when available. // Otherwise we only show the label. if (size($attrType) > 0) { $fmt = (uiRes("m_AEcontainerMain.kAttrAnnotAsEdLong")); $annotString = `format -stringArg $attrType -stringArg $label $fmt`; } else { $fmt = (uiRes("m_AEcontainerMain.kAttrAnnotAsEdShort")); $annotString = `format -stringArg $label $fmt`; } } // Attribute Editor: else { // Attribute Editor, use description when available, otherwise nothing if (size($desc) > 0) { $annotString = $desc; } } return $annotString; } proc createPublishedNodeRowAssetEditor( string $assetInfo, string $mainFrame, string $label, string $nodes[]) // // Description: // Helper function for doViewLayout to create a row in the // asset editor for a published node. // { int $i = 0; int $len = size($nodes); if( $len > 0 ) { int $collapsed = ($len > 10); frameLayout -label $label -borderVisible false -collapsable true -labelVisible true -collapse $collapsed; columnLayout -adj true; for( $i = 0; $i < $len; $i=$i+2) { string $publishedName = $nodes[$i]; string $actualNode = $nodes[$i+1]; string $row = `rowLayout -numberOfColumns 4 -cw 1 18 -cw 2 140 -cw 3 36 -ad4 4`; iconTextCheckBox -w 18 -h 18 -cc ("selectionCmd " + $assetInfo + " 1 0 0 " + $row ) -annotation (uiRes("m_AEcontainerMain.kSelectionAnnot")) selectionButton; text -align "left" -font "obliqueLabelFont" -w 140 -rs false -label $publishedName; // Invisible place holder, since bind/unbind is unapplicable yet. // symbolButton -w 18 -h 18 -vis false -m false bindUnbindButton; text -align "left" -font "obliqueLabelFont" -label $actualNode; int $isSelected = isLeftWinSelection( $assetInfo, $actualNode ); if( $isSelected && $collapsed ){ // Don't collapse this frame // frameLayout -e -collapse false $mainFrame; } selectionCmd( $assetInfo, 0, $isSelected, 0, $row ); setParent ..; } setParent ..; // pop column layout setParent ..; // pop frame layout } } global proc addAttrEdRowLayout( string $frameLayout, string $colLayout, int $isPublished, string $attr, int $viewMode, string $container, string $label, string $annot ) // Add a row layout for the Attribute Editor, either when we're initially // building it, or when we're expanding a frame. // { string $oldParent = `setParent -q`; if( $oldParent != $colLayout ){ setParent $colLayout; } // Ensure we use AE Template setUITemplate -pst attributeEditorTemplate; // Handle display for published attributes if ($isPublished) { // Check whether the parent attribute is also // published. If so we skip this attribute since // we do not want the control to appear twice. // string $plug = `connectionInfo -getExactSource $attr`; if (($viewMode == 1) || !parentAttrIsPublished($plug,$container)) { addPublishedAttrControl($plug, $label, $annot); } } else { // Handle display for unpublished attributes addUnPublishedAttrControl($label); } // Restore template setUITemplate -ppt; if( $frameLayout != "" ){ // Remove the pre-expand command // frameLayout -e -preExpandCommand "" $frameLayout; } if( $oldParent != $colLayout ){ setParent $oldParent; } } global proc addRowLayout( string $assetInfo, string $frameLayout, string $columnLayout, int $isFromTemplate, string $selectionAnnot, string $itemName, string $itemAnnot, string $publishee, int $preExpandCmd ) // Add a row layout for the Asset Editor, either when we're initially building // the RHS, or when we're expanding a frame. // { string $parent; if( $preExpandCmd ){ // We'll need to restore the parent // $parent = `setParent -q`; } string $editedContainer = getEditedContainer( $assetInfo ); string $row = `rowLayout -parent $columnLayout -numberOfColumns 4 -cw 1 18 -cw 2 140 -cw 3 36 -ad4 4`; iconTextCheckBox -parent $row -w 18 -h 18 -cc ("selectionCmd " + $assetInfo + " 1 0 " + $isFromTemplate + " " + $row ) -annotation $selectionAnnot; text -parent $row -align "left" -w 140 -rs false -label $itemName -annotation $itemAnnot; symbolButton -parent $row -w 18 -h 18 -c ("bindUnbindCmd " + $assetInfo + " 1 0 " + $isFromTemplate + " " + $row ); text -parent $row -align "left" -font "obliqueLabelFont" -label $publishee; string $leftSel = $publishee; if( $leftSel == "" ){ $leftSel = ($editedContainer + "." + $itemName); } int $isSelected = isLeftWinSelection( $assetInfo, $leftSel ); bindUnbindCmd( $assetInfo, 0, $isSelected, $isFromTemplate, $row ); selectionCmd( $assetInfo, 0, $isSelected, $isFromTemplate, $row ); if( $preExpandCmd ){ // Reset the preExpand command for the frame layout, restore parent // frameLayout -e -preExpandCommand "" $frameLayout; setParent $parent; } else { // Pop up one level // setParent ..; } } proc doViewLayout( string $attrEdInfo, string $assetInfo, string $container, string $oldGroups[], string $oldStates[]) // // Description: // Create the controls for an published attribute view. // The view contains both attributes and group controls. // // If you modify this method, you should also modify processFrame and // containerPublishedUpdate. // TODO: Refactor containerPublishedUpdate & doViewLayout to make this // easier to maintain. We're skipping it for now, pending how we decide // to handle iteration of templates. // // Inputs: // $attrEdInfo - Attribute Editor information \Exactly one of these is // $assetInfo - Asset Editor information /non-empty // $container - Container for this layout // $oldGroups - Names of old groups, if this container is being refreshed // $oldStates - Collapsed state of old groups // { // Get view info for container and do the layout int $oldGroupIndex = 0; int $numOldGroups = size($oldGroups); string $viewLabel; string $viewAnnotation; string $itemName[]; int $itemIsGroup[]; string $itemLabel[]; int $itemLevel[]; int $itemNumChildren[]; string $itemDesc[]; string $itemAttrType[]; string $itemAnnotation[]; string $frameLayouts[]; string $colLayouts[]; string $preExpandCmds[]; int $expandNow[]; int $numGroups = 0; string $groups[]; // Request all required view info in one shot, then sort it out // $numKeys needs to be kept in sync with this list int $numKeys = 7; string $keywords = "itemName:itemLabel:itemIsGroup:itemLevel:itemNumChildren:itemAttrType:itemDescription"; string $viewItems[] = `containerView -itemList -itemInfo $keywords -query $container`; // Set view label $viewLabel = `containerView -query -viewLabel $container`; // Set view annotation to be the view description. // Note: annotation is for AE only, left empty for asset editor if ($assetInfo == "") { $viewAnnotation = `containerView -query -viewDescription $container`; } int $viewMode = `getAttr ($container + ".viewMode")`; int $flatCap = 0; int $forcedGroupCount = 0; if( $viewMode == 0 ){ // In flat mode, it can take a really long time to build the editor if // there is a huge number of published attributes (bug #307251). We can // drastically reduce this time by partitioning the attributes into // groups, and only creating the UI contents of the group on demand // (i.e., create the frame for the group in a collapsed state, and // create the contents of the frame only when the user expands it). // // We'll let the first 40 attributes be listed without grouping, but // after that, we'll create a group when we reach a pre-specified cap. // The default is 12, which is also the minimum for a non-zero value // (to avoid creating a worse problem by having too many small // groups). If the cap is non-zero, we force the creation of groups // after every $flatCap items; if the cap is zero, we use one // (potentially giant) flat list. The optionVar "containerFlatViewCap" // can be used to override the default value. // $flatCap = 12; if( `optionVar -exists containerFlatViewCap`){ int $userCap = `optionVar -q containerFlatViewCap`; if( ($userCap != 0) && ($userCap < $flatCap) ){ string $capWrn = (uiRes("m_AEcontainerMain.kCapTooSmallWarning")); warning(`format -s $userCap $capWrn`); } else { $flatCap = $userCap; } } } int $flatCount = 0; string $capFmt = (uiRes("m_AEcontainerMain.kFlatCapGroup")); int $numItems = size($viewItems)/$numKeys; int $i=0; for ($itemIndex=0; $itemIndex<$numItems; $itemIndex++) { if( $flatCap > 0 ){ if( ($flatCount >= $flatCap) && ($itemIndex>=40) ){ // Only introduce the first group after the first 40 items // $forcedGroupCount++; $flatCount = 0; // Introduce a forced group // $itemName[$i] = `format -stringArg $forcedGroupCount $capFmt`; $itemLabel[$i] = $itemName[$i]; $itemIsGroup[$i] = 1; $itemLevel[$i] = 0; if( $numItems - $itemIndex > $flatCap ){ $itemNumChildren[$i] = $flatCap; } else { $itemNumChildren[$i] = $numItems - $itemIndex; } $itemAttrType[$i] = ""; $itemDesc[$i] = ""; $itemAnnotation[$i] = $itemName[$i]; $i++; } $flatCount++; } int $index = $itemIndex*$numKeys; $itemName[$i] = $viewItems[$index]; $itemLabel[$i] = $viewItems[$index+1]; $itemIsGroup[$i] = $viewItems[$index+2]; if( $forcedGroupCount > 0 ){ $itemLevel[$i] = 1; } else { $itemLevel[$i] = $viewItems[$index+3]; } $itemNumChildren[$i] = $viewItems[$index+4]; $itemAttrType[$i] = $viewItems[$index+5]; $itemDesc[$i] = $viewItems[$index+6]; // Format the annotation string for this item $itemAnnotation[$i] = formatItemAnnotation($assetInfo, $itemIsGroup[$i], $itemLabel[$i], $itemAttrType[$i], $itemDesc[$i]); $i++; } // For the asset editor, if the view mode is "Use Template", we will show // non-template published names in a separate frame called "Others". // int $doTemplate = true; string $templateName = `getAttr ($container + ".templateName")`; int $doOthers = (($assetInfo != "") && ($viewMode == 1 ) && ($templateName != "")); string $templateNames[]; string $editedContainer; if( $assetInfo != "" ){ if( !`exists getEditedContainer` ){ eval("source \"assetWindow.mel\""); } $editedContainer = getEditedContainer( $assetInfo ); // On linux, we need to manually set the columnLayout width to the // width of the scrollLayout, otherwise the columnLayout gets some // strange fixed value. // string $rightColumnLayout = `setParent -q`; setParent ..; string $rightScrollLayout = `setParent -q`; setParent $rightColumnLayout; int $width = `scrollLayout -q -saw $rightScrollLayout`; columnLayout -e -cw $width $rightColumnLayout; columnLayout -e -w $width $rightColumnLayout; // Need the template names // $templateNames = getTemplateNames( $assetInfo ); } // Create a formLayout whose children will be text fields (see // containerPublishedCommon). The first text field is the name of the // container, and the following text fields point to the frames for // the groups for this container. We'll use this information to // restore the collapsed state of each frame, if possible, if we rebuild // this layout for the exact same container. // string $collapsedDataForm = `formLayout -m true -vis false `; setParent ..; while( $doOthers || $doTemplate ){ if( !$doTemplate ){ $doOthers = false; $viewLabel = (uiRes("m_AEcontainerMain.kOthers")); // In template mode, published names that aren't part of the // template don't show up in the item list, so add them here. // string $publishedNames[] = `container -q -publishName $container`; int $numPublishedNames = size($publishedNames); int $numOthers = 0; clear $itemName; clear $itemLabel; clear $itemIsGroup; clear $itemLevel; clear $itemNumChildren; int $index = 0; while( $index < $numPublishedNames ){ if( !stringArrayContains( $publishedNames[$index], $templateNames ) ){ $itemName[$numOthers] = $publishedNames[$index]; $itemLabel[$numOthers] = $publishedNames[$index]; $itemIsGroup[$numOthers] = 0; $itemLevel[$numOthers] = 1; $itemNumChildren[$numOthers] = 0; $itemAttrType[$numOthers] = ""; $itemDesc[$numOthers] = ""; // TODO: make this attributeNiceName $itemAnnotation[$numOthers] = $itemLabel[$numOthers]; $numOthers++; } $index++; } if( $numOthers == 0 ){ // Nothing to add, so no section // break; } } string $attrs[]; int $isPublished[]; string $publishees[]; clear $attrs; clear $isPublished; // Loop through each attribute in the list to determine if it is // published or not. Build up lists of information that will // be used below to create the controls. Group items are skipped. for ( $i = 0; $i < size($itemName); $i++ ) { // Save info for this attribute into next table position int $index = size($attrs); $attrs[$index] = ""; $isPublished[$index] = 0; // Check if this attribute is published or not. // If so set the full attribute name. if ((!$itemIsGroup[$i]) && (`attributeQuery -exists -node $container $itemName[$i]`)) { $attrs[$index] = ($container+"."+$itemName[$i]); $isPublished[$index] = 1; } if( $assetInfo != "" ){ // Asset Editor Only: // // We need the internal node+attr for the published attribute, // if any. // if( $isPublished[$index] ){ string $plug = `connectionInfo -ges $attrs[$index]`; $publishees[$index] = $plug; } else { $publishees[$index] = ""; } } } // Now build the controls for the groups and attributes // string $mainFrame; $count = size($attrs); if ($count > 0) { string $selectionAnnot = (uiRes("m_AEcontainerMain.kSelectDeselectAnnot")); // Create the frame in a collapsed state to avoid slow downs while // we build subframes, and expand it once we're done. // $mainFrame = `frameLayout -label $viewLabel -annotation $viewAnnotation -borderVisible false -collapsable true -labelVisible ($assetInfo != "") -collapse 1`; string $mainColLayout = `columnLayout -adj true `; int $prevLevel = 0; int $grpCnt = 0; int $currFrameLevel=-1; for ( $i = 0; $i < $count; $i++ ) { // Handle decrease in grouping depth int $currLevel = $itemLevel[$i]; while ($currLevel < $prevLevel) { // Pop column layout // Pop frame layout setParent ..; setParent ..; // Decrement level $prevLevel--; // Assign pre-expand command, if any // if( $preExpandCmds[$prevLevel] != "" ){ if( $expandNow[$prevLevel] ){ frameLayout -e -collapse 0 $frameLayouts[$prevLevel]; eval($preExpandCmds[$prevLevel]); } else { frameLayout -e -preExpandCommand $preExpandCmds[$prevLevel] $frameLayouts[$prevLevel]; } $preExpandCmds[$prevLevel] = ""; } } $prevLevel = $currLevel; // Determine collapsed state // (TODO: this logic may need to be tweaked) int $collapsed = (($grpCnt > 3) || ($itemNumChildren[$i] > 10)); // Handle new group item if ($itemIsGroup[$i]) { // This is the most recent frame to which we want to // add rows // $currFrameLevel = $currLevel; // Ensure we use AE Template if ($assetInfo == "") setUITemplate -pst attributeEditorTemplate; // If this published attribute is on the container itself // (so a dynamic attr on the container), don't display the // label since it will be the same as the container label. // int $hideLabel = ($itemLabel[$i] == $container); if( $hideLabel ) { $collapsed = 0; } if( $oldGroupIndex < $numOldGroups ){ string $currGroup = $itemLabel[$i]; if( stringArrayContains( $currGroup, $oldGroups ) ){ while( $oldGroups[$oldGroupIndex] != $itemLabel[$i] ){ // Assume this old group is no longer valid, // and skip it // $oldGroupIndex++; if( $oldGroupIndex >= $numOldGroups ){ // No more old groups, bail // break; } } if( $oldGroupIndex < $numOldGroups ){ $collapsed = $oldStates[$oldGroupIndex]; $oldGroups[$oldGroupIndex] = ""; $oldGroupIndex++; } } // else, a new group, so no collapse info } // New framelayout string $frame = `frameLayout -label $itemLabel[$i] -annotation $itemAnnotation[$i] -borderVisible false -collapsable (!$hideLabel) -labelVisible (!$hideLabel) -collapse $collapsed`; if( !$hideLabel ){ $groups[$numGroups] = $frame; $numGroups++; } // New columnlayout string $colLayout = `columnLayout`; // Save current frame & column layouts; if this frame is // not to be expanded, start building a pre-expand command // $frameLayouts[$currFrameLevel] = $frame; $colLayouts[$currFrameLevel] = $colLayout; $expandNow[$currFrameLevel] = false; if( $collapsed ){ $preExpandCmds[$currFrameLevel] = ";"; } else { $preExpandCmds[$currFrameLevel] = ""; } if( $assetInfo != "" ){ columnLayout -e -adj true $colLayout; } $grpCnt++; // Restore UI template if ($assetInfo == "") setUITemplate -ppt; } // Handle display for published attributes else if( $assetInfo != "" ){ // Asset Editor Only: // // Display a row with a selection button (may or may not be // visible, depending on the state of the LHS pane selection), // the published attribute's name, the internal node + attr of // the published attribute, and the bind/unbind button. // int $isFromTemplate = stringArrayContains( $itemName[$i], $templateNames ); if( ($currFrameLevel<0) || ($preExpandCmds[$currFrameLevel] == "") ){ // Not collapsed, add immediately // addRowLayout( $assetInfo, ($currFrameLevel<0)?$mainFrame: $frameLayouts[$currFrameLevel], ($currFrameLevel<0)?$mainColLayout: $colLayouts[$currFrameLevel], $isFromTemplate, $selectionAnnot, $itemName[$i], $itemAnnotation[$i], $publishees[$i], 0); } else { if( !$expandNow[$i] ){ string $leftSel = $publishees[$i]; if( $leftSel == "" ){ $leftSel = ($editedContainer + "." + $itemName[$i]); } int $isSelected = isLeftWinSelection( $assetInfo, $leftSel ); if( $isSelected ){ $expandNow[$currFrameLevel] = true; } } // Collapsed, add on demand // $preExpandCmds[$currFrameLevel] = $preExpandCmds[$currFrameLevel] + ("addRowLayout( \"" + $assetInfo + "\", \"" + $frameLayouts[$currFrameLevel] + "\", \"" + $colLayouts[$currFrameLevel] + "\", " + $isFromTemplate + ", \"" + $selectionAnnot + "\", \"" + $itemName[$i] + "\", \"" + $itemAnnotation[$i] + "\", \"" + $publishees[$i] + "\", 1 );"); } } else { // Attribute Editor Only: // if( ($currFrameLevel<0) || ($preExpandCmds[$currFrameLevel] == "") ){ // Not collapsed, add immediately // addAttrEdRowLayout( "", ($currFrameLevel<0)?$mainColLayout: $colLayouts[$currFrameLevel], $isPublished[$i], $attrs[$i], $viewMode, $container, $itemLabel[$i], $itemAnnotation[$i] ); } else { // Collapsed, add on demand // $preExpandCmds[$currFrameLevel] = $preExpandCmds[$currFrameLevel] + ("addAttrEdRowLayout( \"" + $frameLayouts[$currFrameLevel] + "\", \"" + $colLayouts[$currFrameLevel] + "\", " + $isPublished[$i] + ", \"" + $attrs[$i] + "\", " + $viewMode + ", \"" + $container + "\", \"" + $itemLabel[$i] + "\", \"" + $itemAnnotation[$i] + "\" );"); } } } // Pop UI for the last item... // setParent ..; // pop column layout setParent ..; // pop frame layout // Assign pre-expand command, if any // if( $preExpandCmds[0] != "" ){ if( $expandNow[0] ){ frameLayout -e -collapse 0 $frameLayouts[0]; eval($preExpandCmds[0]); } else { frameLayout -e -preExpandCommand $preExpandCmds[0] $frameLayouts[0]; } $preExpandCmds[0] = ""; } if( $assetInfo == "" ){ // Reset rebuild info for Attribute Editor only // publishedAttrRebuildReset($attrEdInfo, $container); } // Make sure the parent is reset when we're done frameLayout -e -collapse 0 $mainFrame; setParent $mainFrame; setParent ..; } $doTemplate = false; } // Asset Editor Only: Display published nodes... // if( $assetInfo != "" && (nodeType($container) == "container") ) { string $rootNode = `container -q -publishAsRoot $container`; string $parents[] = `container -q -pap $container`; string $children[] = `container -q -pac $container`; string $nodes[] = `containerPublish -q -bn $container`; string $rootArray[] = {}; if( $rootNode != "" ) $rootArray[0] = $rootNode; if( size($rootArray) > 0 || size($parents) > 0 || size($children) > 0 ) { string $publishedNodesFrame = `frameLayout -label (uiRes("m_AEcontainerMain.kPublishedNodes")) -borderVisible false -collapsable true -labelVisible true -collapse 0`; columnLayout -adj true; createPublishedNodeRowAssetEditor( $assetInfo, $publishedNodesFrame, (uiRes("m_AEcontainerMain.kSelTransformNoColon")), $rootArray); createPublishedNodeRowAssetEditor( $assetInfo, $publishedNodesFrame, (uiRes("m_AEcontainerMain.kParentAnchors")), $parents); createPublishedNodeRowAssetEditor( $assetInfo, $publishedNodesFrame, (uiRes("m_AEcontainerMain.kChildAnchors")), $children); createPublishedNodeRowAssetEditor( $assetInfo, $publishedNodesFrame, (uiRes("m_AEcontainerMain.kPublishedNodesNoColon")), $nodes); // Make sure the parent is reset when we're done setParent $publishedNodesFrame; setParent ..; } } // Now save the name of the container, and the frame layouts corresponding // to groups. // string $oldParent = `setParent -q`; text -p $collapsedDataForm -m false -l $container; // Sometimes $viewLabel gets overridden (e.g., if $doOthers is true in the // main loop above), but we only care about this value // $viewLabel = `containerView -query -viewLabel $container`; text -p $collapsedDataForm -m false -l $viewLabel; $i = 0; while( $i < $numGroups ){ text -p $collapsedDataForm -m false -l $groups[$i]; $i++; } setParent $oldParent; } // Template-driven layout of published attributes (group by node) // // Procedure Name: // containerPublishedCommon // // Description: // Replace the contents of the container attributes section // // Input Arguments: // $assetInfo - Asset Editor information // $layoutName - the name of the layout // $nodeOrAttrName - the name of the node or node.attribute passed in // // Return Value: // None. // global proc containerPublishedCommon( string $attrEdInfo, string $assetInfo, string $layoutName, string $nodeOrAttrName ) { // Determine container node from nodename or nodename.attr passed // into this routine. $container = plugNode($nodeOrAttrName); // Delete the controls that are there now // string $children[] = `layout -query -childArray $layoutName`; string $cmd = "deleteUI "; for ( $child in $children ) { $cmd += $child; $cmd += " "; } string $oldStates[]; string $oldGroups[]; // If there are no children don't call "deleteUI" if ( `size $children` > 0 ) { // First child is a formLayout whose children are text fields (see // doViewLayout). The first text field is the name of the old // container, the second text field is the old view label, and the // following text fields point to the frames for // the old groups for the old container. We'll use this information to // restore the collapsed state of each frame, if possible. // string $texts[] = `layout -q -childArray $children[0]`; int $numOldGroups = size($texts); string $viewLabel; $viewLabel = `containerView -query -viewLabel $container`; if( ($numOldGroups > 1) && (`text -q -label $texts[0]` == $container) && (`text -q -label $texts[1]` == $viewLabel) ){ // Same container, same view, grab frame collapse info // int $groupIndex = 2; int $i = 0; while( $groupIndex < $numOldGroups ){ string $frameLayout = `text -q -label $texts[$groupIndex]`; $oldGroups[$i] = `frameLayout -q -label $frameLayout`; $oldStates[$i] = `frameLayout -q -collapse $frameLayout`; $i++; $groupIndex++; } } // Only call evalDeferred once so the attrFieldSliderGrps don't get // deleted one by one. eval( $cmd ); } setParent $layoutName; doViewLayout($attrEdInfo, $assetInfo, $container, $oldGroups, $oldStates); } // Template name file browser handling global proc AEtemplateFileBrowser( string $attrName ) { // select the container so that AssignTemplate knows which container // to act on (could alternatively use a global var) // string $nodeName = plugNode($attrName); select -add $nodeName; AssignTemplate; } proc doErrorDialog(string $msg) { string $ok = (uiRes("m_AEcontainerMain.kConfirmOkay")); confirmDialog -message $msg -button $ok -defaultButton $ok; error($msg); } // Refresh the template filename field to reflect the filename of // the template loaded proc templateFileNameUpdate(string $attrEdInfo, string $nodeOrAttrName) { // Get the template name from the attribute $nodeName = plugNode($nodeOrAttrName); string $templateName = `getAttr ($nodeName + ".templateName")`; string $templatePath = `getAttr ($nodeName + ".templatePath")`; // Set the annotation on the template file browser button to // show the filename the template is loaded from (if possible) string $annotText; if (templateAvailable($templateName, $templatePath)) { $annotText = `containerTemplate -q -fileName $templateName`; } else if (size($templateName) > 0) { string $fmt = (uiRes("m_AEcontainerMain.kTemplateNotFound")); $annotText = `format -stringArg $templateName $fmt`; } // Symbol button may not exist yet string $layout = getTemplatePathLayout( $attrEdInfo ); string $templatePathBrowser = ($layout + "|templatePathBrowser"); if (`symbolButton -exists $templatePathBrowser`) { symbolButton -e -annotation $annotText $templatePathBrowser; } } proc AEpublishTemplateNames( string $node, string $templateName ) // // Description: // Given node, and its valid template name, publish template names // that are missing from the node. // // Inputs: // $node : container node with valid template // $templateName : Name of template assigned to container // // Return Value: // None. // { if ( !`exists "publishMissingNames"` ) { eval("source \"containerAssignTemplate.mel\""); } publishMissingNames( $node, `containerTemplate -q -al $templateName` ); } global proc AEtemplateNameNew( string $attrEdInfo,string $attrName) { setUITemplate -pst attributeEditorTemplate; columnLayout -adj true; string $layout = `rowLayout -nc 3 templateNameLayout`; text -label (uiRes("m_AEcontainerMain.kTemplateName")) templateNameText; textField templateNameField; symbolButton -image "refresh.png" -annotation (uiRes("m_AEcontainerMain.kReload")) templateReloadButton; setParent ..; setTemplateNameLayout( $attrEdInfo, $layout ); setParent ..; setUITemplate -ppt; AEtemplateNameReplace( $attrEdInfo , $attrName); } global proc AEtemplateNameReplace( string $attrEdInfo,string $attrName) { string $layout = getTemplateNameLayout( $attrEdInfo ); string $templateName = `getAttr $attrName`; string $nodeName = plugNode($attrName); string $templateNameField = ($layout + "|templateNameField"); connectControl -fileName $templateNameField $attrName; // Set up callback on template name text field string $command = "AEeditTemplateNameCB " + $attrEdInfo + " " + $attrName; textField -e -cc $command $templateNameField; scriptJob -replacePrevious -parent $templateNameField -attributeChange $attrName ($command); // Set up callback and command on template reload button string $templateReloadButton = ($layout + "|templateReloadButton"); $command = "AEreloadTemplateCB " + $attrEdInfo + " " + $attrName; symbolButton -e -c $command $templateReloadButton; AEcontainerRedrawOnViewChange($attrEdInfo, $nodeName, 1 ); } // Callback when template name (text) field changes global proc AEeditTemplateNameCB(string $attrEdInfo, string $plug) { $nodeName = plugNode($plug); string $templateName = `getAttr ($nodeName + ".templateName")`; // Clear the file path attribute. It will be reset if the template // is valid, or it will remain clear if the template is invalid. setAttr ($nodeName + ".templatePath") -type "string" ""; // Validate template name alone. if (size($templateName) == 0) { // Field was cleared, clear the templatePath as well setAttr ($nodeName + ".templatePath") -type "string" ""; } else if (templateValidate($templateName, "")) { AEpublishTemplateNames( $nodeName, $templateName ); // Template is valid, update the path attribute string $newFileName = `containerTemplate -q -fn $templateName`; setAttr ($nodeName + ".templatePath") -type "string" $newFileName; } evalDeferred("AEcontainerRedrawOnViewChange \"" + $attrEdInfo + "\" \"" + $nodeName + "\" 1"); } global proc AEcontainerReloadButtonEnable( string $attrEdInfo, string $attrName) { string $layout = getTemplateNameLayout( $attrEdInfo ); string $templateReloadButton = ($layout + "|templateReloadButton"); // Disable template reload when we don't have a template // Symbol button may not exist yet if (`symbolButton -exists $templateReloadButton`) { $nodeName = plugNode($attrName); string $templateName = `getAttr ($nodeName + ".templateName")`; int $enabled = (size($templateName) > 0); symbolButton -edit -enable $enabled $templateReloadButton; } } global proc AEcontainerViewModeEnable(string $attrName) { $nodeName = plugNode($attrName); int $dimmed = false; // Dim if not template view mode int $viewMode = `getAttr ($nodeName + ".viewMode")`; if ($viewMode != 1) { $dimmed = true; } // Dim if template not available else { string $templateName = `getAttr ($nodeName + ".templateName")`; string $templatePath = `getAttr ($nodeName + ".templatePath")`; if (!templateAvailable($templateName, $templatePath)) { $dimmed = true; } } editorTemplate -dimControl $nodeName "viewName" $dimmed; } // Callback when template reload selected global proc AEreloadTemplateCB( string $attrEdInfo, string $plug) { $nodeName = plugNode($plug); string $templateName = `getAttr ($nodeName + ".templateName")`; string $templatePath = `getAttr ($nodeName + ".templatePath")`; evalDeferred("AEcontainerRedrawOnViewChange \"" + $attrEdInfo + "\" \"" + $nodeName + "\" 1"); if ($templateName != "") { containerTemplate -load -force -fn $templatePath $templateName; } } global proc AEtemplatePathNew( string $attrEdInfo,string $attrName) { setUITemplate -pst attributeEditorTemplate; columnLayout -adj true; string $layout = `rowLayout -nc 3 templatePathLayout`; setTemplatePathLayout( $attrEdInfo, $layout ); text -label (uiRes("m_AEcontainerMain.kTemplatePath")) templatePathText; textField templatePathField; symbolButton -image "navButtonBrowse.png" templatePathBrowser; setParent ..; setParent ..; setUITemplate -ppt; AEtemplatePathReplace( $attrEdInfo, $attrName ); } global proc AEtemplatePathReplace( string $attrEdInfo,string $attrName) { string $templatePath = `getAttr $attrName`; string $nodeName = plugNode($attrName); string $layout = getTemplatePathLayout( $attrEdInfo ); string $templatePathField = ($layout + "|templatePathField"); connectControl -fileName $templatePathField $attrName; // Set up callback on template name text field $command = "AEeditTemplateNameCB " + $attrEdInfo + " " + $attrName; textField -e -cc $command $templatePathField; // Set up callback and command on template browser button string $templatePathBrowser = ($layout + "|templatePathBrowser"); symbolButton -e -c ("AEtemplateFileBrowser " + $attrName ) $templatePathBrowser; AEcontainerRedrawOnViewChange($attrEdInfo, $nodeName, 1 ); } // Callback when viewMode changes global proc AEcontainerViewModeCB( string $attrEdInfo, string $nodeName) { AEcontainerRedrawOnViewChange($attrEdInfo, $nodeName, 1 ); } // Callback when viewName changes global proc AEcontainerViewNameCB( string $attrEdInfo, string $nodeName) { evalDeferred("AEcontainerRedrawOnViewChange \"" + $attrEdInfo + "\" \"" + $nodeName + "\" 1"); } // This is the main routine to redraw portions of this // AE that need to react to a view-related attribute change. // The published attributes will be drawn with the view // and all affected controls will be updated. // The routines called here should not do any more // setAttrs - they should only redraw the controls to // reflect the current state of the container view settings. global proc AEcontainerRedrawOnViewChange( string $attrEdInfo, string $plug, int $primary) // $assetInfo - Asset Editor information; If this method is // triggered by an asset editor, don't try to refresh // the asset editor that triggered it. If empty, // refresh all Asset Editors. // $primary - If true, this is the primary redraw call // { string $nodeName = plugNode($plug); // Update published attributes section: // Determine if a refresh is required // (i.e. if the node or view settings have changed since // the last time the published attrs were redrawn). // This is required since this callback gets called // each time the AE is rebuilt or refreshed, this avoids // multiple refreshes on the same "event". if( publishedAttrRebuildRequired( $attrEdInfo, $nodeName, $primary ) ){ containerPublishedReplace( $attrEdInfo , $nodeName); if( $primary ){ // Refresh other Attribute Editor(s), and Asset Editor(s) // if( !`exists refreshAssetWindows` ){ eval("source \"assetWindow.mel\""); } refreshAssetWindows( "", $nodeName ); AEcontainerRedrawAll( $attrEdInfo, $nodeName ); } } // Update view selector AEcontainerViewNameReplace( $attrEdInfo, $nodeName+".viewName"); // Update template browser control templateFileNameUpdate( $attrEdInfo, $nodeName); AEcontainerViewModeEnable($plug); AEcontainerReloadButtonEnable( $attrEdInfo, $plug); } global proc AEcontainerRedrawAll( string $triggerInfo, string $plug ) // // This rountine is called from the Attribute and Asset Editor to update all // relevant Attribute Editors // { global string $gAttrEdInfos[]; global int $gNumAttrEds; int $iAttrEdInfos = 0; int $stillValid = 0; while( $iAttrEdInfos < $gNumAttrEds ){ string $attrEdInfo = $gAttrEdInfos[$iAttrEdInfos]; if( `formLayout -exists $attrEdInfo` ){ if( $triggerInfo != $attrEdInfo ){ AEcontainerRedrawOnViewChange( $attrEdInfo, $plug, 0 ); } if( $stillValid < $iAttrEdInfos ){ // We found at least one dead Attribute Editor, so we need to // shift values over in the array to eliminate the dead one(s). // $gAttrEdInfos[$stillValid] = $attrEdInfo; } $stillValid++; } // else invalid editor; we don't increment the $stillValid count $iAttrEdInfos++; } if( $stillValid < $gNumAttrEds ){ // Truncate the array // $gNumAttrEds = $stillValid; } } global proc blackBoxCB( string $nodeName ) // // Description: // Callback for black box checkbox. Whenever blackBox is set to true, // isCollapsed is forced to true, and disabled. // // Inputs: // $nodeName : container node's name // // Return Value: // None. // { int $isBlackBox = `getAttr ($nodeName + ".blackBox")`; if( $isBlackBox ){ string $isCollapsedAttr = $nodeName + ".isCollapsed"; if( !`getAttr $isCollapsedAttr` ){ setAttr $isCollapsedAttr true; } } editorTemplate -dimControl $nodeName "isCollapsed" $isBlackBox; } global proc uiTreatmentCB( string $nodeName ) { int $uiTreatment = `getAttr ($nodeName + ".uiTreatment")`; if ($uiTreatment == 1000) { editorTemplate -dimControl $nodeName "customTreatment" 0; } else { editorTemplate -dimControl $nodeName "customTreatment" 1; } } global proc isCollapsedCB( string $nodeName ) // // Description: // Callback for isCollapsed checkbox. Whenever blackBox is set to true, // make sure isCollapsed is forced to true. // // Inputs: // $nodeName : container node's name // // Return Value: // None. // { if( `getAttr ($nodeName + ".blackBox")` ){ // don't allow setting isCollapsed to false // int $isCollapsed = `getAttr ($nodeName + ".isCollapsed")`; if( !$isCollapsed ){ setAttr ($nodeName + ".isCollapsed") true; } } } proc int processFrame( string $assetInfo, string $frameName, string $editedContainer, string $templateNames[]) // // Description: // Process the current frame // // If you modify this method, you should also modify doViewLayout. // TODO: Refactor containerPublishedUpdate & doViewLayout to make this // easier to maintain. We're skipping it for now, pending how we decide // to handle iteration of templates. // // Inputs: // $frameName : frame layout name // $editedContainer: name of currently edited container // $templateNames : published names that come from the active template, // if any // // Return Value: // true iff frame processing was normal // { int $status = false; string $children[] = `layout -q -ca $frameName`; if( size($children) == 1 ){ string $columnName = $frameName+"|"+$children[0]; if( `columnLayout -exists $columnName`){ // Now go through the column layout's children // clear $children; $children = `layout -q -ca $columnName`; int $numChildren = size($children); int $index = 0; $status = true; while( $index < $numChildren ){ string $layoutName = $columnName + "|" + $children[$index]; if( `rowLayout -exists $layoutName` ){ // Process a row // string $rowChildren[] = `rowLayout -q -ca $layoutName`; if( size($rowChildren) != 4 ){ $status = false; break; } string $itcbName = $layoutName + "|" + $rowChildren[0]; if( `iconTextCheckBox -exists $itcbName` ){ string $internText = ($layoutName + "|" + $rowChildren[3]); string $internPlug = `text -q -label $internText`; string $publicText = ($layoutName + "|" + $rowChildren[1]); string $publicName = `text -q -label $publicText`; string $leftSel = $internPlug; if( $internPlug == "" ){ $leftSel = ($editedContainer + "." + $publicName); } int $isSelected = isLeftWinSelection( $assetInfo, $leftSel ); int $isFromTemplate = stringArrayContains( $publicName, $templateNames ); string $bindBtn = $layoutName + "|" + $rowChildren[2]; if( `symbolButton -exists $bindBtn` ){ if( `symbolButton -q -m $bindBtn` ){ bindUnbindCmd( $assetInfo, 0, $isSelected, $isFromTemplate, $layoutName ); } } selectionCmd( $assetInfo, 0, $isSelected, $isFromTemplate, $layoutName ); } } else if( `frameLayout -exists $layoutName` ){ // Process a new frame // if( !processFrame( $assetInfo, $layoutName, $editedContainer, $templateNames ) ){ $status = false; break; } } else { $status = false; break; } $index++; } } } return( $status ); } global proc containerPublishedUpdate( string $assetInfo, string $layoutName, string $templateNames[]) // // Description: // Update the right window without rebuilding it entirely. This is only // applicable to the Asset Editor. // // If you modify this method, you should also modify doViewLayout. // TODO: Refactor containerPublishedUpdate & doViewLayout to make this // easier to maintain. We're skipping it for now, pending how we decide // to handle iteration of templates. // // Inputs: // $assetInfo - Asset Editor information // $layoutName - the name of the layout // { string $editedContainer = getEditedContainer( $assetInfo ); int $status = false; if( `columnLayout -exists $layoutName` ){ string $children[] = `layout -q -ca $layoutName`; int $numFrames = size($children)-1; // We should have at least the template frame, possibly the // "Others" frame, and the "Published Nodes" frame. // If not, bail. // if( ($numFrames >= 1) && ($numFrames <= 3) ){ // First child is the collapsedDataForm, so skip it // int $frameIndex = 1; $status = true; while( $frameIndex < $numFrames ){ string $frameName = $layoutName+"|"+$children[$frameIndex]; if( !`frameLayout -exists $frameName`){ $status = false; break; } if( !processFrame( $assetInfo, $frameName, $editedContainer, $templateNames ) ){ $status = false; break; } $frameIndex++; } } } if( !$status ){ // If we get here, we failed, so rebuild all. // rebuildRightWin( $assetInfo ); } } global proc string AEcontainerMain( string $nodeName ) { // We'll create an extra form to store data relevant only to this // particular Attr Ed representation (e.g., the main window, a copied tab) // The data form has managed set to true, and visibility to false, other // wise the subsequent scroll layout won't display in a copy tab. // // $dataForm will have the following children: // T=Text, I=Integer // 0 - $nodeName T // 1 - view mode (initially -1) I // 2 - template name (initially "") T // 3 - template view name (initially "") T // 4 - borderConnections layout (initially "") T // 5 - published nodes layout (initially "") T // 6 - template name layout (initially "") T // 7 - view name layout (initially "") T // 8 - template path layout (initially "") T string $dataForm = `formLayout -m true -vis false`;//dataForm[ text -p $dataForm -m false -l $nodeName; intField -p $dataForm -m false -v -1; text -p $dataForm -m false -l ""; text -p $dataForm -m false -l ""; text -p $dataForm -m false -l ""; text -p $dataForm -m false -l ""; text -p $dataForm -m false -l ""; text -p $dataForm -m false -l ""; text -p $dataForm -m false -l ""; setParent ..; //]end-dataForm // Keep track of all data forms, so we can update AE & tabs, as need be // global string $gAttrEdInfos[]; global int $gNumAttrEds; if( !stringArrayContains( $dataForm, $gAttrEdInfos ) ){ // We don't want duplicate entries; this could happen if an Attribute // Editor is deleted, and a new one created before we check if the // deleted one is still valid. By coincidence, the two could have the // same name, and we'd end up with two entries with the same name. // $gAttrEdInfos[$gNumAttrEds] = $dataForm; $gNumAttrEds++; } editorTemplate -beginLayout (uiRes("m_AEcontainerMain.kPublishedAttributes")) -collapse 0; editorTemplate -callCustom ("containerPublishedNew \""+$dataForm+"\"") ("containerPublishedReplace \""+$dataForm+"\"") "borderConnections"; editorTemplate -endLayout; editorTemplate -beginLayout (uiRes("m_AEcontainerMain.kAssetAttributes")) -collapse 1; editorTemplate -addControl "blackBox" "blackBoxCB"; editorTemplate -addControl "iconName"; editorTemplate -beginLayout (uiRes("m_AEcontainerMain.kTemplates")) -collapse 0; editorTemplate -addControl "viewMode" ("AEcontainerViewModeCB " + $dataForm ); editorTemplate -callCustom ("AEtemplateNameNew \""+$dataForm+"\"") ("AEtemplateNameReplace \""+$dataForm+"\"") templateName; editorTemplate -callCustom ("AEtemplatePathNew \""+$dataForm+"\"") ("AEtemplatePathReplace \""+$dataForm+"\"") templatePath; editorTemplate -callCustom ("AEcontainerViewNameNew \""+$dataForm+"\"") ("AEcontainerViewNameReplace \""+$dataForm+"\"") "viewName"; editorTemplate -endLayout; editorTemplate -label (uiRes("m_AEcontainerMain.kOwner")) -addControl "creator"; editorTemplate -addControl "creationDate"; editorTemplate -addControl "isCollapsed" "isCollapsedCB"; editorTemplate -beginLayout (uiRes("m_AEcontainerMain.kContextProperties")) -collapse 0; editorTemplate -addControl "rmbCommand"; editorTemplate -label (uiRes("m_AEcontainerMain.kUiTreatment")) -addControl "uiTreatment" "uiTreatmentCB"; editorTemplate -addControl "customTreatment"; editorTemplate -label (uiRes("m_AEcontainerMain.kType")) -addControl "containerType"; editorTemplate -endLayout; editorTemplate -endLayout; editorTemplate -suppress "hyperLayout"; editorTemplate -suppress "templateVersion"; return $dataForm; }