// =========================================================================== // 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. // =========================================================================== // // Description: // Compound publish workflow in nodeEditor panel // //////////////////////////////////////////////////// /// LOCAL FUNCTIONS //////////////////////////////////////////////////// proc string[] getCurrentCompoundDescription() { string $ned = ( `getCurrentNodeEditor`); if ("" == $ned) error (uiRes("m_nodeEditorPublish.kInvalidNodeEditor")); string $container = `nodeEditor -q -vd $ned`; if ("" == $container) error (uiRes("m_nodeEditorPublish.kInvalidContainer")); string $compound = `nodeEditor -q -vc $ned`; if ("" == $compound) error (uiRes("m_nodeEditorPublish.kInvalidCompound")); return { $container, $compound }; } proc string[] getSelectedNodeDescription(string $node) { if ("" == $node) error (uiRes("m_nodeEditorPublish.kInvalidNode")); string $compDesc[] = `getCurrentCompoundDescription`; string $compoundName = $compDesc[1]; if (!endsWith($compoundName, ".")) { $compoundName = $compoundName + "."; } return { $compDesc[0], $compoundName + $node }; } proc string buildCompoundCmd(string $compDesc[], string $action) { string $container = $compDesc[0]; string $compound = $compDesc[1]; string $cmd = "vnnCompound \"" + $container + "\" \"" + $compound + "\" " + $action; return $cmd; } proc string buildNodeCmd(string $nodeDesc[], string $action) { string $container = $nodeDesc[0]; string $node = $nodeDesc[1]; string $cmd = "vnnNode \"" + $container + "\" \"" + $node + "\" " + $action; return $cmd; } proc string getCompoundMetadata(string $compDesc[], string $metadataKey) { string $action = "-queryMetaData \"" + $metadataKey + "\""; string $cmd = buildCompoundCmd($compDesc, $action); string $values[] = eval($cmd); if(size($values) > 0) return $values[0]; return ""; } proc setCompoundMetadata(string $compDesc[], string $metadataKey, string $metadataValue) { string $action = "-setMetaData \"" + $metadataKey + "\" \"" + $metadataValue + "\""; string $cmd = buildCompoundCmd($compDesc, $action); eval($cmd); } // Split string // Note that leading, consecutive, or trailing separators give empty strings, // unlike the MEL tokenize() function which strips them proc string[] publishCompound_splitString(string $text, string $separator) { string $result[]; string $pattern = $separator + ".*"; string $matchingText; int $separatorLen = size($separator); int $n = 0; while ( size( $matchingText = `match $pattern $text` ) ) { int $matchingTextLen = size( $matchingText ); int $matchingTextPos = size( $text ) - $matchingTextLen; if( $matchingTextPos > 1 ) { $result[ $n++ ] = substring( $text, 1, $matchingTextPos ); } else { $result[ $n++ ] = ""; } $text = substring( $matchingText, $separatorLen+1, $matchingTextLen); } $result[ $n ] = $text; return $result; } // Joint an array of string to a string that can be used as an array declaration : // { "str1", "str2" } proc string arrayToString(string $values[]) { string $result; for ( $value in $values ) { if(size($result) > 0) { $result += ", "; } $result += "\"" + $value + "\""; } return ("{" + $result + "}"); } //////////////////////////////////////////////////// /// GLOBAL FUNCTIONS //////////////////////////////////////////////////// global proc publishCompound_fillNamespaceSelection(string $currentNamespace) { string $ned = ( `getCurrentNodeEditor`); if ("" == $ned) return; string $runTime = `nodeEditor -q -vnnRuntime $ned`; string $allNamespacesCmd = "vnn -libraries \"" + $runTime + "\""; string $allNamespaces[]; catchQuiet($allNamespaces = eval($allNamespacesCmd)); // Fill with existing namespaces int $namespaceCount = size( $allNamespaces ); int $namespaceIdx = 0; for ( $namespaceIdx = 0; $namespaceIdx < $namespaceCount; ++$namespaceIdx ) { string $namespace = $allNamespaces[$namespaceIdx]; menuItem -label $namespace -parent "namespaceSelectionList"; } menuItem -divider true -dividerLabel "---" -enable false -parent "namespaceSelectionList"; menuItem -label (uiRes("m_nodeEditorPublish.kNamespaceNew")) -parent "namespaceSelectionList"; // Select current namespace if( catchQuiet(`optionMenu -edit -value $currentNamespace "namespaceSelectionList"`) ) { // Not found: select New... and set custom value int $newNamespaceItem = `optionMenu -q -numberOfItems "namespaceSelectionList"`; optionMenu -edit -select $newNamespaceItem "namespaceSelectionList"; textField -edit -text $currentNamespace -enable true "customNamespace"; } else { // Found: make the custom value read-only textField -edit -enable false "customNamespace"; } } global proc publishCompound_fillNodedefSelection(string $currentNamespace, string $currentNodedef) { string $ned = ( `getCurrentNodeEditor`); if ("" == $ned) return; string $runTime = `nodeEditor -q -vnnRuntime $ned`; string $allNodeDefsCmd = "vnn -nodes \"" + $runTime + "\" \"" + $currentNamespace + "\""; string $allNodedefs[]; catchQuiet($allNodeDefs = eval($allNodeDefsCmd)); int $nodedefCount = size( $allNodedefs ); int $nodedefIdx = 0; for ( $nodedefIdx = 0; $nodedefIdx < $nodedefCount; ++$nodedefIdx ) { string $nodedef = $allNodedefs[$nodedefIdx]; menuItem -label $nodedef -parent "nodedefSelectionList"; } menuItem -divider true -dividerLabel "---" -enable false -parent "nodedefSelectionList"; menuItem -label (uiRes("m_nodeEditorPublish.kNodedefNew")) -parent "nodedefSelectionList"; // Select current nodedef if( catchQuiet(`optionMenu -edit -value $currentNodedef "nodedefSelectionList"`) ) { // Not found: select New... and set custom value int $newNodedefItem = `optionMenu -q -numberOfItems "nodedefSelectionList"`; optionMenu -edit -select $newNodedefItem "nodedefSelectionList"; textField -edit -text $currentNodedef -enable true "customNodedef"; } else { // Found: make the custom value read-only textField -edit -enable false "customNodedef"; } } global proc string publishCompound_getSelectedNamespace() { string $selectedNamespace = `optionMenu -q -value "namespaceSelectionList"`; if(`textField -q -enable "customNamespace"`) { $selectedNamespace = `textField -q -text "customNamespace"`; } return $selectedNamespace; } global proc string publishCompound_getSelectedNodedef() { string $selectedNodedef = `optionMenu -q -value "nodedefSelectionList"`; if(`textField -q -enable "customNodedef"`) { $selectedNodedef = `textField -q -text "customNodedef"`; } return $selectedNodedef; } global proc publishCompound_namespaceSelectionChanged(string $parent) { setParent $parent; int $selectedItem = `optionMenu -q -select "namespaceSelectionList"`; int $nbItems = `optionMenu -q -numberOfItems "namespaceSelectionList"`; int $setCustomNamespaceEnable = ($selectedItem == $nbItems); // == New... textField -edit -enable $setCustomNamespaceEnable "customNamespace"; string $selectedNamespace = publishCompound_getSelectedNamespace(); string $selectedNodedef = publishCompound_getSelectedNodedef(); if( `optionMenu -q -numberOfItems "nodedefSelectionList"` > 0) { deleteUI -menuItem `optionMenu -q -itemListLong "nodedefSelectionList"`; } publishCompound_fillNodedefSelection($selectedNamespace, $selectedNodedef); } global proc publishCompound_nodedefSelectionChanged(string $parent) { setParent $parent; int $selectedItem = `optionMenu -q -select "nodedefSelectionList"`; int $nbItems = `optionMenu -q -numberOfItems "nodedefSelectionList"`; int $setCustomNodedefEnable = ($selectedItem == $nbItems); // == New... textField -edit -enable $setCustomNodedefEnable "customNodedef"; } global proc publishCompound_buildOverloadOptionsUI(string $compDesc[], string $parent) { string $action = "-queryTypeName"; string $cmd = buildNodeCmd($compDesc, $action); string $typeName = eval($cmd); // Type name is "runtime,namespace,nodeDef" string $typeNameValues[] = publishCompound_splitString($typeName, ","); string $currentNamespace = $typeNameValues[1]; string $currentNodedef = $typeNameValues[2]; setParent $parent; int $labelWidth = 100; int $minFieldWidth = 100; frameLayout -label (uiRes("m_nodeEditorPublish.kOverloadOptions")) -marginHeight 5 -collapsable false -borderVisible false; rowLayout -numberOfColumns 2 -columnWidth2 $labelWidth $minFieldWidth -adjustableColumn 2; text -label (uiRes("m_nodeEditorPublish.kNamespace")) -width $labelWidth -align "right"; string $namespaceSelectionChangedCmd = "publishCompound_namespaceSelectionChanged \"" + $parent + "\""; optionMenu -changeCommand $namespaceSelectionChangedCmd "namespaceSelectionList"; setParent ..; rowLayout -numberOfColumns 2 -columnWidth2 $labelWidth $minFieldWidth -adjustableColumn 2; text -label "" -width $labelWidth; textField -enable false "customNamespace"; setParent ..; rowLayout -numberOfColumns 2 -columnWidth2 $labelWidth $minFieldWidth -adjustableColumn 2; text -label (uiRes("m_nodeEditorPublish.kNodedef")) -width $labelWidth -align "right"; string $nodedefSelectionChangedCmd = "publishCompound_nodedefSelectionChanged \"" + $parent + "\""; optionMenu -changeCommand $nodedefSelectionChangedCmd "nodedefSelectionList"; setParent ..; rowLayout -numberOfColumns 2 -columnWidth2 $labelWidth $minFieldWidth -adjustableColumn 2; text -label "" -width $labelWidth; textField -enable false "customNodedef"; setParent ..; publishCompound_fillNamespaceSelection($currentNamespace); publishCompound_fillNodedefSelection($currentNamespace, $currentNodedef); publishCompound_namespaceSelectionChanged($parent); publishCompound_nodedefSelectionChanged($parent); } global proc publishCompound_buildPublishOptionsUI(string $compDesc[], string $parent) { string $action = "-queryIsReferenced"; string $cmd = buildCompoundCmd($compDesc, $action); int $isReferenced = `eval($cmd)`; setParent $parent; frameLayout -label (uiRes("m_nodeEditorPublish.kOptions")) -marginHeight 5 -collapsable false -borderVisible false; columnLayout -adjustableColumn true; text -label (uiRes("m_nodeEditorPublish.kGeneralOptions")) -font "boldLabelFont" -align "left"; separator -height 5 -style "none" -noBackground true; checkBox -label (uiRes("m_nodeEditorPublish.kFlattenCompound")) "flattenCompound"; checkBox -label (uiRes("m_nodeEditorPublish.kReferenceOnPublish")) -enable ($isReferenced == 0) "referenceOnPublish"; separator -height 10 -style "none" -noBackground true; text -label (uiRes("m_nodeEditorPublish.kPublishOptions")) -font "boldLabelFont" -align "left"; separator -height 5 -style "none" -noBackground true; checkBox -label (uiRes("m_nodeEditorPublish.kIgnoreErrosOnPublish")) "ignoreErrors"; optionMenu -label (uiRes("m_nodeEditorPublish.kLogLevel")) -width 120 "logLevel"; menuItem -label (uiRes("m_nodeEditorPublish.kDebug")); checkBox -label (uiRes("m_nodeEditorPublish.kOutputPublishLogFile")) -value true "logPublish"; int $labelWidth = 110; int $minFieldWidth = 100; rowLayout -numberOfColumns 2 -columnWidth2 $labelWidth $minFieldWidth -adjustableColumn 2; text -label (uiRes("m_nodeEditorPublish.kPrePublishMEL")); textField "prePublishCallback"; setParent ..; rowLayout -numberOfColumns 2 -columnWidth2 $labelWidth $minFieldWidth -adjustableColumn 2; text -label (uiRes("m_nodeEditorPublish.kPostPublishMEL")); textField "postPublishCallback"; } global proc publishCompound_optionsUICreate(string $compDesc[], string $parent) { // Activate the default UI template so that the layout of this // option box is consistent with the layout of the rest of the // application. // setUITemplate -pushTemplate DefaultTemplate; setParent $parent; string $optionLayout = `columnLayout -adjustableColumn true`; publishCompound_buildOverloadOptionsUI($compDesc, $optionLayout); publishCompound_buildPublishOptionsUI($compDesc, $optionLayout); // Deactivate the default UI template // setUITemplate -popTemplate; } global proc publishCompound_optionsUICommit2(string $compDesc[], string $parent, string $file) { setParent $parent; string $selectedNamespace = publishCompound_getSelectedNamespace(); string $selectedNodedef = publishCompound_getSelectedNodedef(); int $referenceOnPublish = 0; if(`checkBox -q -enable "referenceOnPublish"`) { $referenceOnPublish = `checkBox -q -value "referenceOnPublish"`; } int $ignoreErrors = `checkBox -q -value "ignoreErrors"`; int $logLevel = `optionMenu -q -select "logLevel"`; int $logPublish = `checkBox -q -value "logPublish"`; int $flattenCompound = `checkBox -q -value "flattenCompound"`; if( $flattenCompound != 0) { // TODO explode compounds inside ??? } // Metadatas string $publishedBy = `getenv USER`; string $publishDate = `date -format "YYYYMMDD_hhmmss"`; string $publishVersion = getCompoundMetadata($compDesc, "publishVersion"); // Increase version number int $publishVersionNumber = 0; if ($publishVersion != "") $publishVersionNumber = $publishVersion; $publishVersionNumber += 1; $publishVersion = string($publishVersionNumber); // Add some left padding while(size($publishVersion) < 3) { $publishVersion = "0" + $publishVersion; } setCompoundMetadata($compDesc, "publishedBy", $publishedBy); setCompoundMetadata($compDesc, "publishDate", $publishDate); setCompoundMetadata($compDesc, "publishVersion", $publishVersion); string $logFile = ""; if( $logPublish != 0 ) { string $logFolder = `internalVar -userTmpDir`; $logFile = $logFolder + $selectedNamespace + "_" + $selectedNodedef + "_" + $publishDate + "_log.txt"; } // Call pre-callback string $prePublishCallback = `textField -q -text "prePublishCallback"`; if( $prePublishCallback != "") { $prePublishCallback = `substitute "$container" $prePublishCallback $compDesc[0]`; $prePublishCallback = `substitute "$compound" $prePublishCallback $compDesc[1]`; $prePublishCallback = `substitute "$file" $prePublishCallback $file`; catch(eval($prePublishCallback)); } // TODO logFile, logLevel and ignoreErrors // Do the publish string $action = "-publish \"" + $file + "\" \"" + $selectedNamespace + "\" \"" + $selectedNodedef + "\" " + $referenceOnPublish; string $cmd = buildCompoundCmd($compDesc, $action); int $result = `eval($cmd)`; if( $result == 0 ) { string $msg = (uiRes("m_nodeEditorPublish.kFailedToPublish")); $msg = `format -s $file $msg`; warning $msg; return; } // Call post-callback string $postPublishCallback = `textField -q -text "postPublishCallback"`; if( $postPublishCallback != "") { $postPublishCallback = `substitute "$container" $postPublishCallback $compDesc[0]`; $postPublishCallback = `substitute "$compound" $postPublishCallback $compDesc[1]`; $postPublishCallback = `substitute "$file" $postPublishCallback $file`; catch(eval($postPublishCallback)); } } global proc nodeEdEditCompound(string $node) { string $ned = ( `getCurrentNodeEditor`); if ("" == $ned) return; nodeEditor -edit -openContainerView $node false $ned; } global proc nodeEdPublishCompound_impl(string $compDesc[]) { // Save a compound (local or referenced) to a file, // - if the compound is currently referenced // it may be moved to another namespace, // and is saved to a json file. // - if the compound is currently local: // - referenceOnPublish is true : the compound is moved inside a namespace and saved, // - referenceOnPublish is false : a copy compound is created in a namespace and saved, // the current local compound remain unchanged. string $startingDirectory = ""; string $bifrostRoot = `getenv BIFROST_LOCATION`; if( $bifrostRoot == "" ) { string $mayaRoot = `getenv MAYA_LOCATION`; if( $mayaRoot != "" ) { if( `about -mac` ) { $mayaRoot += "/../.."; } $bifrostRoot += $mayaRoot + "/plug-ins/bifrost"; } } if( $bifrostRoot != "" ) { $startingDirectory = $bifrostRoot + "/graphlib"; } else { $startingDirectory = `internalVar -userAppDir`; } string $fileFilter = "JSON (*.json);;"; string $optionsUICreate = "publishCompound_optionsUICreate( " + arrayToString($compDesc) + " )"; string $optionsUICommit2 = "publishCompound_optionsUICommit2( " + arrayToString($compDesc) + " )"; fileDialog2 -fileMode 0 -fileFilter $fileFilter -okCaption (uiRes("m_nodeEditorPublish.kPublish")) -caption (uiRes("m_nodeEditorPublish.kPublishCompound")) -dialogStyle 2 -startingDirectory $startingDirectory -optionsUICreate $optionsUICreate -optionsUICommit2 $optionsUICommit2; } global proc nodeEdPublishCompound(string $node) { string $compDesc[] = `getCurrentCompoundDescription`; nodeEdPublishCompound_impl $compDesc; } global proc nodeEdPublishCurrentCompound() { string $compDesc[] = `getCurrentCompoundDescription`; nodeEdPublishCompound_impl $compDesc; } global proc nodeEdImportCompound(string $node) { // Create a new copy of a referenced compound, // the uri of the local copy will be the same as the source compound. // Requisite : the compound must be currently referenced. string $compDesc[] = `getSelectedNodeDescription $node`; string $action = "-setIsReferenced false"; string $cmd = buildCompoundCmd($compDesc, $action); eval($cmd); } global proc nodeEdRevertCompound(string $node) { // Go back to the original referenced compound. // Requisite : the compound must have been imported before. string $compDesc[] = `getSelectedNodeDescription $node`; string $action = "-setIsReferenced true"; string $cmd = buildCompoundCmd($compDesc, $action); eval($cmd); } global proc nodeEdDeleteCompound(string $node) { print "nodeEdDeleteCompound : not implemented yet\n"; } global proc int nodeEdIsReferenced(string $node) { // A referenced compound is a compound defined inside a namespace // and has a valid uri path. string $compDesc[] = `getSelectedNodeDescription $node`; string $action = "-queryIsReferenced"; string $cmd = buildCompoundCmd($compDesc, $action); return eval($cmd); } global proc int nodeEdCanBeReverted(string $node) { // A compound can be reverted if has been imported: // converted from a referenced to a local compound int $isReferenced = `nodeEdIsReferenced $node`; if ( $isReferenced ) return 0; string $compDesc[] = `getSelectedNodeDescription $node`; string $action = "-queryIsImported"; string $cmd = buildCompoundCmd($compDesc, $action); return eval($cmd); }