def cacheDialog(dagPath, pulledMayaRefPrim, _): '''Display dialog to cache the argument pulled Maya reference prim to USD.''' global _mayaRefDagPath global _pulledMayaRefPrim _mayaRefDagPath = dagPath _pulledMayaRefPrim = pulledMayaRefPrim ok = getMayaUsdLibString('kCacheMayaRefCache') fileFilter = getMayaUsdLibString( "kAllUsdFiles" ) + " (*.usd *.usda *.usdc *.usdz);;*.usd;;*.usda;;*.usdc;;*.usdz" # As per Maya projectViewer.mel code structure, the UI creation # (optionsUICreate) creates the main UI framework, and UI initialization # (optionsUIInit) puts up the export options. files = cmds.fileDialog2( returnFilter=1, fileMode=0, caption=getMayaUsdLibString('kCaptionCacheToUsd'), fileFilter=fileFilter, dialogStyle=2, okCaption=ok, # The callbacks below must be MEL procedures, as per fileDialog2 # requirements. They call their corresponding Python functions. optionsUICreate="mayaUsdCacheMayaReference_cacheCreateUi", optionsUIInit="mayaUsdCacheMayaReference_cacheInitUi", optionsUITitle="", optionsUICommit2="mayaUsdCacheMayaReference_cacheCommitUi", startingDirectory=cmds.workspace(query=True, directory=True))
def createMayaReferenceMenuItem(dagPath, precedingItem): '''Create a merge to USD menuItem for Maya references. If the Maya object at dagPath is a transform corresponding to a Maya reference, create a menuItem for it. ''' # The dagPath must have the pull information that brings us to the USD # prim. If this prim is of type Maya reference, create a specific menu # item for it, otherwise return an empty string for the chain of # responsibility. # The dagPath may come in as a shortest unique name. Expand it to full # name; ls -l would be an alternate implementation. sn = om.MSelectionList() sn.add(dagPath) fullDagPath = sn.getDagPath(0).fullPathName() mayaItem = ufe.Hierarchy.createItem(ufe.PathString.path(fullDagPath)) pathMapper = ufe.PathMappingHandler.pathMappingHandler(mayaItem) pulledPath = pathMapper.fromHost(mayaItem.path()) prim = mayaUsd.ufe.ufePathToPrim(ufe.PathString.string(pulledPath)) # If the pulled prim isn't a MayaReference, not our responsibility. if prim.GetTypeName() != 'MayaReference': return '' cmd = partial(mayaUsdCacheMayaReference.cacheDialog, fullDagPath, prim) cacheLabel = getMayaUsdLibString('kMenuCacheToUsd') return cmds.menuItem(label=cacheLabel, insertAfter=precedingItem, image="cache_to_USD.png", command=cmd)
def variantNameChanged(selectedItem): # If the "Create New" item is selected, we show the text input # to the right of the optionMenu. For existing variant names # the field is hidden. createNew = getMayaUsdLibString('kMayaRefCreateNew') cmds.textField('variantNameText', edit=True, visible=(selectedItem == createNew))
def fileOptionsTabPage(tabLayout): mayaRefUtils.pushOptionsUITemplate() cmds.setParent(tabLayout) # See fileOptions.mel:fileOptionsTabPage() comments. Contrary to that # code, we are not keeping 'optionsBoxForm' as a global MEL variable. We # assume that we don't need to reference this directly to hide UI # temporarily. optBoxForm = cmds.formLayout('optionsBoxForm') topFrame = cmds.frameLayout('optionsBoxFrame', collapsable=False, labelVisible=False, marginWidth=10, borderVisible=False) cmds.formLayout(optBoxForm, edit=True, af=[(topFrame, 'left', 0), (topFrame, 'top', 0), (topFrame, 'right', 0), (topFrame, 'bottom', 0)]) topForm = cmds.columnLayout('actionOptionsForm', rowSpacing=5) cmds.setParent(topForm) cmds.frameLayout(label=getMayaUsdLibString("kMayaRefDescription")) cmds.columnLayout(adjustableColumn=True) cmds.text(align="left", label="TBD") cmds.setParent(topForm) cmds.frameLayout(label=getMayaUsdLibString("kCacheMayaRefOptions")) # USD file option controls will be parented under this layout. # resultCallback not called on "post", is therefore an empty string. fileOptionsScroll = cmds.columnLayout('fileOptionsScroll') mel.eval( 'mayaUsdTranslatorExport("fileOptionsScroll", "post=all;!animation-data", "' + getCacheOptions() + '", "")') cacheFileUsdHierarchyOptions(topForm) cmds.setUITemplate(popTemplate=True)
def createDefaultMenuItem(dagPath, precedingItem): # This is the final callable in the chain of responsibility, so it must # always return a menu item. cmd = 'maya.mel.eval("mayaUsdMenu_pushBackToUSD ' + dagPath + '")' mergeLabel = getMayaUsdLibString('kMenuMergeMayaEdits') returnedItem = cmds.menuItem(label=mergeLabel, insertAfter=precedingItem, image="merge_to_USD.png", command=cmd) cmd = 'maya.mel.eval("mayaUsdMenu_pushBackToUSDOptions ' + dagPath + '")' cmds.menuItem(insertAfter=returnedItem, optionBox=True, command=cmd) return returnedItem
def createMenuItem(dagPath, precedingItem): '''Create a merge to USD menuItem for Maya object at dagPath. The menuItem will be placed in the menu after precedingItem, which must be a menuItem string name. ''' for creator in _menuItemCreators: created = creator(dagPath, precedingItem) if created: return created # The following means that default menu item creation failed. errorMsg = getMayaUsdLibString('kErrorMergeToUsdMenuItem') cmds.error(errorMsg)
def cacheCommitUi(parent, selectedFile): # Read data to set up cache. # The following call will set _cacheOptions. Initial settings not accessed # on "query", is therefore an empty string. mel.eval( 'mayaUsdTranslatorExport("fileOptionsScroll", "query", "", "mayaUsdCacheMayaReference_setCacheOptions")' ) # Regardless of UI, animation is always on. cacheOptionsText = re.sub(r'animation=.', 'animation=1', getCacheOptions()) userArgs = mayaUsd.lib.Util.getDictionaryFromEncodedOptions( cacheOptionsText) primName = cmds.textFieldGrp('primNameText', query=True, text=True) defineInVariant = cmds.radioButtonGrp('variantRadioBtn', query=True, select=True) userArgs['rn_layer'] = selectedFile userArgs['rn_primName'] = primName userArgs['rn_defineInVariant'] = defineInVariant userArgs['rn_payloadOrReference'] = cmds.optionMenuGrp( 'compositionArcTypeMenu', query=True, value=True) userArgs['rn_listEditType'] = cmds.optionMenu('listEditedAsMenu', query=True, value=True) if defineInVariant: userArgs['rn_variantSetName'] = cmds.optionMenu('variantSetMenu', query=True, value=True) variantName = cmds.optionMenu('variantNameMenu', query=True, value=True) if variantName == 'Create New': variantName = cmds.textField('variantNameText', query=True, text=True) userArgs['rn_variantName'] = variantName # Call push. if not mayaUsd.lib.PrimUpdaterManager.mergeToUsd(_mayaRefDagPath, userArgs): errorMsgFormat = getMayaUsdLibString('kErrorCacheToUsdFailed') errorMsg = cmds.format(errorMsgFormat, stringArg=(_mayaRefDagPath)) cmds.error(errorMsg)
def variantSetNameChanged(selectedItem): # Update the Variant Name option menu from the input Variant Set. mayaRefPrimParent = _pulledMayaRefPrim.GetParent() cmds.optionMenu('variantNameMenu', edit=True, deleteAllItems=True) variantNames = mayaRefPrimParent.GetVariantSet( selectedItem).GetVariantNames() cmds.menuItem(getMayaUsdLibString('kMayaRefCreateNew'), parent='variantNameMenu') for vName in variantNames: cmds.menuItem(label=vName, parent='variantNameMenu') # Select 'Create New' by default and set the text field to default value. cmds.optionMenu('variantNameMenu', edit=True, select=1) cmds.textField('variantNameText', edit=True, visible=True, text=kDefaultCacheVariantName)
def ProxyShapeFilePathChanged(filePathAttr, newFilePath=None): # Function called from the MayaUsd Proxy Shape template when the file path # text field of the file path attibute custom control is modified or interacted with. # # Arguments: # - filePathAttr: string representing the file path attribute. # - newFilePath : If None, the user clicked the file browser button. # - In this case a file dialog will be opened to allow user to pick USD file. # Otherwise when a string, the user entered a filename directly in the field. # - In this case simply try and load the file. # # Return Value: # - True: The input file path attribute was updated with a new value. # - False: No update to file path attribute was done. # debugMessage('ProxyShapeFilePathChanged(%s, %s)' % (filePathAttr, newFilePath)) try: stageName, proxyStage = GetStageFromProxyShapeAttr(filePathAttr) # Does the filepath attribute contain a valid file? currFilePath = cmds.getAttr(filePathAttr) dirtyStack = False openFileDialog = False if currFilePath: # We have a current file path, so check if any layer in the layerstack is dirty? dirtyStack = IsProxyShapeLayerStackDirty(proxyStage) if not dirtyStack: openFileDialog = True else: # No current file path, so do we just have an empty stage or was something added to # this anon layer? rootLayer = proxyStage.GetRootLayer() if rootLayer and not rootLayer.empty: dirtyStack = True elif newFilePath is None: debugMessage(' Empty stage, opening file dialog...') openFileDialog = True # If we have a dirty layer stack, display dialog to confirm new loading. if dirtyStack: kTitleFormat = getMayaUsdString("kDiscardStageEditsTitle") kMsgFormat = getMayaUsdString("kDiscardStageEditsLoadMsg") kYes = getMayaUsdString("kButtonYes") kNo = getMayaUsdString("kButtonNo") kTitle = cmds.format(kTitleFormat, stringArg=stageName) # Our title is a little long, and the confirmDialog command is not making the # dialog wide enough to show it all. So by telling the message string to not # word-wrap, the dialog is forced wider. kMsg = "<p style='white-space:pre'>" + cmds.format(kMsgFormat, stringArg=stageName) res = cmds.confirmDialog(title=kTitle, message=kMsg, messageAlign='left', button=[kYes, kNo], defaultButton=kYes, cancelButton=kNo, dismissString=kNo, icon='warning') if res == kYes: debugMessage(' User confirmed load action, opening file dialog...') openFileDialog = True else: # User said NO to update, so don't proceed any farther. return False if openFileDialog and newFilePath is None: # Pop the file open dialog for user to load new usd file. title = getMayaUsdString("kLoadUSDFile") okCaption = getMayaUsdString("kLoad") fileFilter = getMayaUsdLibString("kAllUsdFiles") + ' (*.usd *.usda *.usdc *.usdz );;*.usd;;*.usda;;*.usdc;;*.usdz'; res = cmds.fileDialog2(caption=title, fileMode=1, ff=fileFilter, okc=okCaption) if res and len(res) == 1: debugMessage(' User picked USD file, setting file path attribute') # Simply set the file path attribute. The proxy shape will load the file. usdFileToLoad = res[0] cmds.setAttr(filePathAttr, usdFileToLoad, type='string') return True elif newFilePath is not None: # Instead of opening a file dialog to get the USD file, simply # use the one provided as input. # Note: it is important to check "not None" since the new file path can be # an empty string. debugMessage(' New file to load provided, setting filepath="%s"' % newFilePath) cmds.setAttr(filePathAttr, newFilePath, type='string') return True except Exception as e: debugMessage('ProxyShapeFilePathChanged() - Error: %s' % str(e)) pass return False
def cacheFileUsdHierarchyOptions(topForm): '''Create controls to insert Maya reference USD cache into USD hierarchy.''' cmds.setParent(topForm) cmds.frameLayout(label=getMayaUsdLibString("kCacheMayaRefUsdHierarchy")) widgetColumn = cmds.columnLayout() rl = mel.eval('createRowLayoutforMayaReference("' + widgetColumn + '", "cacheFilePreviewRow", 2)') with mayaRefUtils.SetParentContext(rl): cmds.iconTextStaticLabel(st="iconAndTextHorizontal", i1="info.png", l=getMayaUsdLibString('kCacheFileWillAppear')) cmds.textField(text=str(_pulledMayaRefPrim.GetParent().GetPath()), editable=False) with mayaRefUtils.SetParentContext(cmds.rowLayout(numberOfColumns=2)): cmds.optionMenuGrp( 'compositionArcTypeMenu', label=getMayaUsdLibString('kOptionAsCompositionArc'), cc=compositionArcChanged) cmds.menuItem(label=getMayaUsdLibString('kMenuPayload')) cmds.menuItem(label=getMayaUsdLibString('kMenuReference')) cmds.optionMenu('listEditedAsMenu', label=getMayaUsdLibString('kOptionListEditedAs'), cc=listEditChanged) cmds.menuItem(label=getMayaUsdLibString('kMenuAppend')) cmds.menuItem(label=getMayaUsdLibString('kMenuPrepend')) variantRb = cmds.radioButtonGrp('variantRadioBtn', nrb=1, label=getMayaUsdLibString('kTextDefineIn'), l1=getMayaUsdLibString('kTextVariant')) rl = mel.eval('createRowLayoutforMayaReference("' + widgetColumn + '", "usdCacheVariantSetRow", 3)') with mayaRefUtils.SetParentContext(rl): cmds.text(label=getMayaUsdLibString('kMayaRefVariantSetName')) cmds.optionMenu('variantSetMenu', cc=variantSetNameChanged) cmds.textField(visible=False) rl = mel.eval('createRowLayoutforMayaReference("' + widgetColumn + '", "usdCacheVariantNameRow", 3)') with mayaRefUtils.SetParentContext(rl): cmds.text(label=getMayaUsdLibString('kMayaRefVariantName')) cmds.optionMenu('variantNameMenu', cc=variantNameChanged) cmds.textField('variantNameText', cc=variantNameTextChanged) newChildRb = cmds.radioButtonGrp( 'newChildPrimRadioBtn', nrb=1, label='', scl=variantRb, l1=getMayaUsdLibString('kButtonNewChildPrim')) cmds.textFieldGrp('primNameText', label=getMayaUsdLibString('kMayaRefPrimName'), cc=primNameTextChanged) cmds.radioButtonGrp(variantRb, edit=True, select=1)
def createMayaReferencePrim( ufePathStr, mayaReferencePath, mayaNamespace, mayaReferencePrimName=mayaRefUtils.defaultMayaReferencePrimName(), groupPrim=None, variantSet=None, mayaAutoEdit=kDefaultEditAsMayaData): '''Create a Maya reference prim and optional group prim parented to the argument path. Optionally create a variant set and name and placed the edits inside that variant. Naming of Maya Reference prim is supported, otherwise default name is used. The group prim is optional. The variant set and name are optional Parameters: ----------- ufePathStr : str : Ufe PathString of parent prim to add Maya Reference mayaReferencePath : str : File path of Maya Reference (for attribute) mayaNamespace : str : Namespace (for attribute) mayaReferencePrimName : str [optional] : Name for the Maya Reference prim groupPrim : tuple(str,str,str) [optional] : The Group prim Name, Type & Kind to create Note: the name is optional and will be auto-computed if empty or not provided. Note: Type and Kind are both mandatory, but Kind is allowed to be empty string. variantSet : tuple(str,str) [optional] : The Variant Set Name and Variant Name to create Return: ------- The Usd prim of the newly created Maya Reference or an invalid prim if there is an error. ''' # Make sure the prim name is valid and doesn't already exist. parentPrim = mayaUsd.ufe.ufePathToPrim(ufePathStr) # There are special conditions when we are given the ProxyShape gateway node. ufePath = ufe.PathString.path(ufePathStr) isGateway = (ufePath.nbSegments() == 1) # Were we given a Group prim to create? groupPrimName = None groupPrimType = None groupPrimKind = None if groupPrim: if (len(groupPrim) == 2): groupPrimType, groupPrimKind = groupPrim elif (len(groupPrim) == 3): groupPrimName, groupPrimType, groupPrimKind = groupPrim # Make sure the input Group prim name doesn't exist already # and validate the input name. # Note: it is allowed to be input as empty in which case a default is used. if groupPrimName: checkGroupPrimName = mayaUsd.ufe.uniqueChildName( parentPrim, groupPrimName) if checkGroupPrimName != groupPrimName: errorMsgFormat = getMayaUsdLibString( 'kErrorGroupPrimExists') errorMsg = cmds.format(errorMsgFormat, stringArg=(groupPrimName, ufePathStr)) om.MGlobal.displayError(errorMsg) return Usd.Prim() groupPrimName = Tf.MakeValidIdentifier(checkGroupPrimName) # If the group prim was either not provided or empty we use a default name. if not groupPrimName: groupPrimName = getDefaultGroupPrimName(parentPrim, mayaNamespace) # When the input is a gateway we cannot have in variant unless group is also given. if isGateway and variantSet and not groupPrimName: errorMsg = getMayaUsdLibString('kErrorCannotAddToProxyShape') om.MGlobal.displayError(errorMsg) return Usd.Prim() # Make sure the input Maya Reference prim name doesn't exist already # and validate the input name. # Note: if we are given a group prim to create, then we know that the # Maya Reference prim name will be unique since it will be the # only child (of the newly created group prim). checkName = mayaUsd.ufe.uniqueChildName( parentPrim, mayaReferencePrimName) if groupPrim is None else mayaReferencePrimName if checkName != mayaReferencePrimName: errorMsgFormat = getMayaUsdLibString('kErrorMayaRefPrimExists') errorMsg = cmds.format(errorMsgFormat, stringArg=(mayaReferencePrimName, ufePathStr)) om.MGlobal.displayError(errorMsg) return Usd.Prim() validatedPrimName = Tf.MakeValidIdentifier(checkName) # Extract the USD path segment from the UFE path and append the Maya # reference prim to it. parentPath = str(ufePath.segments[1]) if ufePath.nbSegments() > 1 else '' stage = mayaUsd.ufe.getStage(ufePathStr) # Optionally insert a Group prim as a parent of the Maya reference prim. groupPrim = None if groupPrimName: groupPath = Sdf.AssetPath(parentPath + '/' + groupPrimName) try: groupPrim = stage.DefinePrim(groupPath.path, groupPrimType) except (Tf.ErrorException): groupPrim = Usd.Prim() if not groupPrim.IsValid(): errorMsgFormat = getMayaUsdLibString('kErrorCreatingGroupPrim') errorMsg = cmds.format(errorMsgFormat, stringArg=(ufePathStr)) om.MGlobal.displayError(errorMsg) return Usd.Prim() if groupPrimKind: model = Usd.ModelAPI(groupPrim) model.SetKind(groupPrimKind) if groupPrim: primPath = Sdf.AssetPath(groupPrim.GetPath().pathString + '/' + validatedPrimName) else: primPath = Sdf.AssetPath(parentPath + '/' + validatedPrimName) # Were we given a Variant Set to create? variantSetName = None variantName = None if variantSet and (len(variantSet) == 2): variantSetName, variantName = variantSet if variantSetName and variantName: validatedVariantSetName = Tf.MakeValidIdentifier(variantSetName) validatedVariantName = Tf.MakeValidIdentifier(variantName) # If we created a group prim add the variant set there, otherwise add it # to the prim that corresponds to the input ufe path. variantPrim = groupPrim if groupPrim else mayaUsd.ufe.ufePathToPrim( ufePathStr) vset = variantPrim.GetVariantSet(validatedVariantSetName) vset.AddVariant(validatedVariantName) vset.SetVariantSelection(validatedVariantName) with vset.GetVariantEditContext(): # Now all of our subsequent edits will go "inside" the # 'variantName' variant of 'variantSetName'. prim = createPrimAndAttributes(stage, primPath, mayaReferencePath, mayaNamespace, mayaAutoEdit) else: prim = createPrimAndAttributes(stage, primPath, mayaReferencePath, mayaNamespace, mayaAutoEdit) if prim is None or not prim.IsValid(): errorMsgFormat = getMayaUsdLibString('kErrorCreatingMayaRefPrim') errorMsg = cmds.format(errorMsgFormat, stringArg=(ufePathStr)) om.MGlobal.displayError(errorMsg) return Usd.Prim() return prim