From c885d47a5330432b15740c84e924aa6cbec1a677 Mon Sep 17 00:00:00 2001 From: Sean Donnelly <23455376+seando-adsk@users.noreply.github.com> Date: Tue, 24 Jan 2023 17:10:45 -0500 Subject: [PATCH 1/5] MAYA-127358 - Load my USD root file relative to scene file using 'Create Stage from File' MAYA-127353 - Load my USD root file relative to the scene file * Use the same python class "usdRootFileRelative" to add the controls to the stage load. --- plugin/adsk/scripts/AETemplateHelpers.py | 12 +++++++- .../scripts/mayaUsd_USDRootFileRelative.py | 9 ++++-- .../scripts/mayaUsd_createStageFromFile.mel | 28 +++++++++++++++---- .../mayaUsd_layerEditorFileDialogs.mel | 6 +++- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/plugin/adsk/scripts/AETemplateHelpers.py b/plugin/adsk/scripts/AETemplateHelpers.py index 8d9ddc4fe6..61186b01d7 100644 --- a/plugin/adsk/scripts/AETemplateHelpers.py +++ b/plugin/adsk/scripts/AETemplateHelpers.py @@ -125,7 +125,17 @@ def ProxyShapeFilePathChanged(filePathAttr, newFilePath=None): title = getMayaUsdString("kLoadUSDFile") okCaption = getMayaUsdString("kLoad") fileFilter = getUSDDialogFileFilters() - res = cmds.fileDialog2(caption=title, fileMode=1, ff=fileFilter, okc=okCaption) + + startDir = '' + if cmds.file(q=True, exists=True): + fullPath = cmds.file(q=True, loc=True) + startDir = os.path.dirname(fullPath) + + res = cmds.fileDialog2(caption=title, fileMode=1, ff=fileFilter, okc=okCaption, + optionsUICreate='mayaUsd_USDRootFileRelative_UICreate', + optionsUIInit='mayaUsd_USDRootFileRelative_UIInit', + optionsUICommit2='mayaUsd_USDRootFileRelative_UICommit', + startingDirectory=startDir) 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. diff --git a/plugin/adsk/scripts/mayaUsd_USDRootFileRelative.py b/plugin/adsk/scripts/mayaUsd_USDRootFileRelative.py index 4ff9793c05..9a200dc80a 100644 --- a/plugin/adsk/scripts/mayaUsd_USDRootFileRelative.py +++ b/plugin/adsk/scripts/mayaUsd_USDRootFileRelative.py @@ -10,9 +10,14 @@ class usdRootFileRelative(object): @classmethod def uiCreate(cls, parentLayout): + """ + Helper method to create the UI layout for the USD root file relative actions. + + Input parentLayout arg is expected to the a scroll layout into which controls + can be added. + """ pushOptionsUITemplate() cmds.setParent(parentLayout) - parent = cmds.scrollLayout(childResizable=True) optBoxForm = cmds.formLayout('optionsBoxForm') topFrame = cmds.frameLayout( @@ -49,7 +54,7 @@ def uiInit(cls, parentLayout, filterType): cmds.checkBox(cls.kMakePathRelativeCheckBox, edit=True, enable=haveSceneFile) @classmethod - def uiCommit(cls, parentLayout, selectedFile): + def uiCommit(cls, parentLayout, selectedFile=None): cmds.setParent(parentLayout) # Get the current checkbox state and save to optionVar. diff --git a/plugin/adsk/scripts/mayaUsd_createStageFromFile.mel b/plugin/adsk/scripts/mayaUsd_createStageFromFile.mel index befb26d14a..0f4e5d900a 100644 --- a/plugin/adsk/scripts/mayaUsd_createStageFromFile.mel +++ b/plugin/adsk/scripts/mayaUsd_createStageFromFile.mel @@ -64,10 +64,18 @@ proc string getLatestLoadStageFolder() // stageFromFile_UISetup // creates the options of the stageFromFile dialog -global proc string stageFromFile_UISetup(string $parent) { +global proc string stageFromFile_UISetup(string $parent) +{ + // First create the scroll layout here and then call the python + // helper to add the rest of the UI. setParent $parent; string $layout = `scrollLayout -childResizable true`; + // Add the USD root file relative section. + python("import mayaUsd_USDRootFileRelative as murel\nmurel.usdRootFileRelative.uiCreate('" + $layout + "')"); + + // Then add the stage from file specific section. + setParent $layout; $title = `getMayaUsdString("kUsdFileOptions")`; $frame = `frameLayout -label $title -collapsable false`; checkBoxGrp -l `getMayaUsdString("kLoadPayloads")` @@ -90,9 +98,13 @@ global proc string stageFromFile_UISetup(string $parent) { // stageFromFile_UIInit // init defaults values for the options of the stageFromFile dialog -global proc stageFromFile_UIInit(string $parent, string $filterType) { +global proc stageFromFile_UIInit(string $parent, string $filterType) +{ setOptionVars(false); + // Init the USD root file relative section. + python("import mayaUsd_USDRootFileRelative as murel\nmurel.usdRootFileRelative.uiInit('" + $parent + "', '" + $filterType + "')"); + string $ppath = `optionVar -q stageFromFile_primPath`; string $exppath = `optionVar -q stageFromFile_excludePrimPath`; int $loadp = `optionVar -q stageFromFile_loadPayloads`; @@ -103,9 +115,13 @@ global proc stageFromFile_UIInit(string $parent, string $filterType) { checkBoxGrp -e -value1 $loadp loadPayloadsCheckBox; } -global proc stageFromFile_UICommit(string $parent) { +global proc stageFromFile_UICommit(string $parent) +{ setParent $parent; + // Commit the USD root file relative section. + python("import mayaUsd_USDRootFileRelative as murel\nmurel.usdRootFileRelative.uiCommit('" + $parent + "')"); + // fetch values optionVar -stringValue stageFromFile_primPath (`textFieldGrp -q -text primPathField`); @@ -115,7 +131,8 @@ global proc stageFromFile_UICommit(string $parent) { (`checkBoxGrp -q -value1 loadPayloadsCheckBox`); } -proc string doCreateStage(string $fileName) { +proc string doCreateStage(string $fileName) +{ // actually load the file string $baseName = basenameEx($fileName); if( ! isValidObjectName($baseName) ) @@ -216,7 +233,8 @@ global proc mayaUsd_createStageFromFileOptions() showOptionBox(); } -global proc mayaUsd_createStageFromFile() { +global proc mayaUsd_createStageFromFile() +{ setOptionVars(false); $caption = getMayaUsdString("kCreateUsdStageFromFile"); diff --git a/plugin/adsk/scripts/mayaUsd_layerEditorFileDialogs.mel b/plugin/adsk/scripts/mayaUsd_layerEditorFileDialogs.mel index 1f110fff39..64eb13da7d 100644 --- a/plugin/adsk/scripts/mayaUsd_layerEditorFileDialogs.mel +++ b/plugin/adsk/scripts/mayaUsd_layerEditorFileDialogs.mel @@ -15,7 +15,11 @@ global proc mayaUsd_USDRootFileRelative_UICreate(string $parent) { - python("import mayaUsd_USDRootFileRelative as murel\nmurel.usdRootFileRelative.uiCreate('" + $parent + "')"); + // First create the scroll layout here and then call the python + // helper to add the rest of the UI. + setParent $parent; + string $layout = `scrollLayout -childResizable true`; + python("import mayaUsd_USDRootFileRelative as murel\nmurel.usdRootFileRelative.uiCreate('" + $layout + "')"); } global proc mayaUsd_USDRootFileRelative_UIInit(string $parent, string $filterType) From 012b4dd47d83733232099832a33a2b3295199d2a Mon Sep 17 00:00:00 2001 From: Ivan Vlasov Date: Wed, 25 Jan 2023 11:04:55 -0500 Subject: [PATCH 2/5] Feature implementation --- lib/mayaUsd/python/wrapUtil.cpp | 4 +++- plugin/adsk/scripts/AETemplateHelpers.py | 6 ++++++ plugin/adsk/scripts/mayaUsd_createStageFromFile.mel | 7 ++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/mayaUsd/python/wrapUtil.cpp b/lib/mayaUsd/python/wrapUtil.cpp index e6cf610ef0..ba5ec0496a 100644 --- a/lib/mayaUsd/python/wrapUtil.cpp +++ b/lib/mayaUsd/python/wrapUtil.cpp @@ -15,6 +15,7 @@ // #include #include +#include #include #include @@ -51,5 +52,6 @@ void wrapUtil() .def("IsAuthored", UsdMayaUtil::IsAuthored) .def("prettifyName", &UsdMayaUtil::prettifyName) .staticmethod("prettifyName") - .def("getDictionaryFromEncodedOptions", getDictionaryFromEncodedOptions); + .def("getDictionaryFromEncodedOptions", getDictionaryFromEncodedOptions) + .def("getPathRelativeToMayaSceneFile", &UsdMayaUtilFileSystem::getPathRelativeToMayaSceneFile); } diff --git a/plugin/adsk/scripts/AETemplateHelpers.py b/plugin/adsk/scripts/AETemplateHelpers.py index 61186b01d7..fd1e739f5d 100644 --- a/plugin/adsk/scripts/AETemplateHelpers.py +++ b/plugin/adsk/scripts/AETemplateHelpers.py @@ -2,6 +2,7 @@ import maya.cmds as cmds import ufe import mayaUsd.ufe +import mayaUsd.lib as mayaUsdLib from mayaUSDRegisterStrings import getMayaUsdString from mayaUsdUtils import getUSDDialogFileFilters @@ -60,6 +61,9 @@ def GetStageFromProxyShapeAttr(attr): return(stageName, proxyStage) +def RequireUsdPathsRelativeToMayaSceneFile(): + return cmds.optionVar(exists="mayaUsd_MakePathRelativeToSceneFile") and cmds.optionVar(query="mayaUsd_MakePathRelativeToSceneFile") + 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. @@ -140,6 +144,8 @@ def ProxyShapeFilePathChanged(filePathAttr, newFilePath=None): 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] + if RequireUsdPathsRelativeToMayaSceneFile(): + usdFileToLoad = mayaUsdLib.Util.getPathRelativeToMayaSceneFile(usdFileToLoad) cmds.setAttr(filePathAttr, usdFileToLoad, type='string') return True elif newFilePath is not None: diff --git a/plugin/adsk/scripts/mayaUsd_createStageFromFile.mel b/plugin/adsk/scripts/mayaUsd_createStageFromFile.mel index 0f4e5d900a..0856e8e7b0 100644 --- a/plugin/adsk/scripts/mayaUsd_createStageFromFile.mel +++ b/plugin/adsk/scripts/mayaUsd_createStageFromFile.mel @@ -142,8 +142,13 @@ proc string doCreateStage(string $fileName) string $exppath = `optionVar -q stageFromFile_excludePrimPath`; int $loadp = `optionVar -q stageFromFile_loadPayloads`; + string $fileNameToSave = $fileName; + if (`optionVar -exists mayaUsd_MakePathRelativeToSceneFile` && `optionVar -query mayaUsd_MakePathRelativeToSceneFile`) { + $fileNameToSave = `python("import mayaUsd.lib as mayaUsdLib; mayaUsdLib.Util.getPathRelativeToMayaSceneFile('" + $fileName + "')")`; + } + string $shapeNode = `createNode "mayaUsdProxyShape" -skipSelect -name ($baseName+"Shape")`; - setAttr -type "string" ($shapeNode+".filePath") $fileName; + setAttr -type "string" ($shapeNode+".filePath") $fileNameToSave; setAttr -type "string" ($shapeNode+".primPath") $ppath; setAttr -type "string" ($shapeNode+".excludePrimPaths") $exppath; setAttr ($shapeNode+".loadPayloads") $loadp; From 335363ebb0838d8221a20ffe41b96f255fc36673 Mon Sep 17 00:00:00 2001 From: Ivan Vlasov Date: Thu, 26 Jan 2023 08:32:05 -0500 Subject: [PATCH 3/5] Make sure to use the absolute path if Maya scene file doesn't exist yet --- lib/mayaUsd/utils/utilFileSystem.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/mayaUsd/utils/utilFileSystem.cpp b/lib/mayaUsd/utils/utilFileSystem.cpp index 32d9b0c67b..d3fae24177 100644 --- a/lib/mayaUsd/utils/utilFileSystem.cpp +++ b/lib/mayaUsd/utils/utilFileSystem.cpp @@ -121,6 +121,12 @@ std::string UsdMayaUtilFileSystem::getPathRelativeToMayaSceneFile(const std::str { ghc::filesystem::path absolutePath(fileName); ghc::filesystem::path basePath(getMayaSceneFileDir()); + + // If Maya scene file doesn't exist yet, use the absolute path + if (basePath.empty()) { + return fileName; + } + ghc::filesystem::path relativePath = absolutePath.lexically_relative(basePath); if (relativePath.empty()) { From edeb1f60e0479122c2bdb483f0e0574b6ce4b2d1 Mon Sep 17 00:00:00 2001 From: Ivan Vlasov Date: Thu, 26 Jan 2023 12:07:37 -0500 Subject: [PATCH 4/5] Minor improvements --- lib/mayaUsd/utils/utilFileSystem.cpp | 2 +- lib/mayaUsd/utils/utilFileSystem.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/mayaUsd/utils/utilFileSystem.cpp b/lib/mayaUsd/utils/utilFileSystem.cpp index d3fae24177..679ead02ae 100644 --- a/lib/mayaUsd/utils/utilFileSystem.cpp +++ b/lib/mayaUsd/utils/utilFileSystem.cpp @@ -130,7 +130,7 @@ std::string UsdMayaUtilFileSystem::getPathRelativeToMayaSceneFile(const std::str ghc::filesystem::path relativePath = absolutePath.lexically_relative(basePath); if (relativePath.empty()) { - TF_RUNTIME_ERROR( + TF_WARN( "File name (%s) cannot be resolved as relative to the Maya scene file, using the " "absolute path.", fileName.c_str()); diff --git a/lib/mayaUsd/utils/utilFileSystem.h b/lib/mayaUsd/utils/utilFileSystem.h index df66d5b79a..e0b5dea28f 100644 --- a/lib/mayaUsd/utils/utilFileSystem.h +++ b/lib/mayaUsd/utils/utilFileSystem.h @@ -49,7 +49,8 @@ std::string getMayaSceneFileDir(); MAYAUSD_CORE_PUBLIC std::string getMayaWorkspaceScenesDir(); -/*! \brief takes in an absolute file path and returns the path relative to maya scene file +/*! \brief takes in an absolute file path and returns the path relative to maya scene file. +When there is no scene file, the absolute (input) path will be returned. */ MAYAUSD_CORE_PUBLIC std::string getPathRelativeToMayaSceneFile(const std::string& fileName); From 41839408f62d4873ffb7d5743b27f8e244231791 Mon Sep 17 00:00:00 2001 From: Ivan Vlasov Date: Thu, 26 Jan 2023 12:18:44 -0500 Subject: [PATCH 5/5] clang-format --- lib/mayaUsd/python/wrapUtil.cpp | 4 +++- lib/mayaUsd/utils/utilFileSystem.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/mayaUsd/python/wrapUtil.cpp b/lib/mayaUsd/python/wrapUtil.cpp index ba5ec0496a..fe613cd937 100644 --- a/lib/mayaUsd/python/wrapUtil.cpp +++ b/lib/mayaUsd/python/wrapUtil.cpp @@ -53,5 +53,7 @@ void wrapUtil() .def("prettifyName", &UsdMayaUtil::prettifyName) .staticmethod("prettifyName") .def("getDictionaryFromEncodedOptions", getDictionaryFromEncodedOptions) - .def("getPathRelativeToMayaSceneFile", &UsdMayaUtilFileSystem::getPathRelativeToMayaSceneFile); + .def( + "getPathRelativeToMayaSceneFile", + &UsdMayaUtilFileSystem::getPathRelativeToMayaSceneFile); } diff --git a/lib/mayaUsd/utils/utilFileSystem.cpp b/lib/mayaUsd/utils/utilFileSystem.cpp index 679ead02ae..ba04f417bd 100644 --- a/lib/mayaUsd/utils/utilFileSystem.cpp +++ b/lib/mayaUsd/utils/utilFileSystem.cpp @@ -122,7 +122,7 @@ std::string UsdMayaUtilFileSystem::getPathRelativeToMayaSceneFile(const std::str ghc::filesystem::path absolutePath(fileName); ghc::filesystem::path basePath(getMayaSceneFileDir()); - // If Maya scene file doesn't exist yet, use the absolute path + // If Maya scene file doesn't exist yet, use the absolute path if (basePath.empty()) { return fileName; }