Skip to content

Commit

Permalink
Merge pull request #3236 from Autodesk/bailp/EMSUSD-256/relative-maya…
Browse files Browse the repository at this point in the history
…-ref

EMSUSD-256 allow Maya ref to be relative to the layer.
  • Loading branch information
seando-adsk authored Jul 31, 2023
2 parents 13273b3 + 2ba2e71 commit 7a4d6c0
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 44 deletions.
25 changes: 19 additions & 6 deletions lib/mayaUsd/resources/scripts/mayaUsdAddMayaReference.mel
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ proc fileOptionsTabPage(string $tabLayout)
string $topForm = `columnLayout -rowSpacing 5 actionOptionsForm`;

setParent $topForm;
frameLayout -label `getMayaUsdLibString("kMayaRefDescription")` -height 170 -mw $gOptionBoxTemplateDescriptionMarginWidth;
frameLayout -label `getMayaUsdLibString("kMayaRefDescription")` -height 170 -mw $gOptionBoxTemplateDescriptionMarginWidth -collapsable 0;
columnLayout;
text -align "left" -wordWrap true -height 80 -label `getMayaUsdLibString("kMayaRefAddToUSDDescription1")`;
text -align "left" -wordWrap true -height 50 -label `getMayaUsdLibString("kMayaRefAddToUSDDescription2")`;
Expand All @@ -101,6 +101,8 @@ proc fileOptionsTabPage(string $tabLayout)
frameLayout -label `getMayaUsdLibString("kMayaRefUsdOptions")`;
string $widgetColumn = `columnLayout usdOptionsLayout`;

python("import mayaUsd_USDRootFileRelative as murel\nmurel.usdMayaRefRelativeToEditTargetLayer.uiCreateFields()");

textFieldGrp
-label `getMayaUsdLibString("kMayaRefMayaRefPrimName")`
-cc "usdMayaRef_changePrimNameText \"#1\""
Expand Down Expand Up @@ -592,8 +594,10 @@ proc usdMayaRef_setupDefineInVariant()
}

// Adapted from fileOptions.mel:fileOptionsSetup().
proc fileOptionsSetup(string $parent, int $forceFactorySettings, string $chosenFileType)
proc fileOptionsSetup(string $parent, int $forceFactorySettings, string $filterType)
{
python("import mayaUsd_USDRootFileRelative as murel\nmurel.usdMayaRefRelativeToEditTargetLayer.uiInit(r'''" + $parent + "''', r'''" + $filterType + "''')");

global string $gUsdMayaReferenceUfePath;

string $action = "Reference";
Expand Down Expand Up @@ -670,8 +674,8 @@ proc fileOptionsSetup(string $parent, int $forceFactorySettings, string $chosenF

fo_changeReferenceNamespaceOption( $action );

string $fileType = ("" == $chosenFileType) ?
`optionVar -q defaultFileReferenceType` : $chosenFileType;
string $fileType = ("" == $filterType) ?
`optionVar -q defaultFileReferenceType` : $filterType;

int $userPrefix = 0;
string $usePrefixOptionVar = "referenceOptionsUseRenamePrefix";
Expand Down Expand Up @@ -775,6 +779,8 @@ global proc addMayaReferenceToUsdUiCb(string $parent, string $selectedFile)
{
setParent $parent;

python("import mayaUsd_USDRootFileRelative as murel\nmurel.usdMayaRefRelativeToEditTargetLayer.uiCommit(r'''" + $parent + "''', r'''" + $selectedFile + "''')");

string $action = "Reference";

global string $gFileOptionsString;
Expand Down Expand Up @@ -1060,10 +1066,17 @@ global proc string addMayaReferenceToUsd(string $ufePath)

int $autoEditAsMayaData = `optionVar -query usdMayaReferenceEditAsMayaDat`;

// No need to actually create the Maya reference node: pulling on the
string $filePath = $file[0];
int $requireRelative = (`optionVar -exists mayaUsd_MakePathRelativeToEditTargetLayer` && `optionVar -query mayaUsd_MakePathRelativeToEditTargetLayer`);
if ($requireRelative) {
string $relativeTo = `python("import mayaUsd_USDRootFileRelative as murel; murel.usdFileRelative.getRelativeFilePathRoot()")`;
$filePath = `python("import mayaUsd.lib as mayaUsdLib; mayaUsdLib.Util.getPathRelativeToDirectory(r'''" + $filePath + "''', r'''" + $relativeTo + "''')")`;
}
$filePath = fromNativePath($filePath);

// No need to actually create the Maya reference node: edit-as-Maya on the
// Maya reference prim will create the Maya reference node.
// Create the Maya reference prim under its parent.
string $filePath = fromNativePath($file[0]);
string $ns = computeNamespace($filePath);
string $pyCmdArgs = `format -s $ufePath -s $filePath -s $ns -s $gUsdMayaReferencePrimName "'^1s', '^2s', '^3s', '^4s'"`;
if ($useGroup)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ global proc mayaUsdLibRegisterStrings()
register("kMayaRefCacheToUSDDescription2", "<p><b>Note:</b> When authoring the exported USD cache back into a current USD hierarchy, an edit will be made on the targeted layer. The cache file will be added as a USD reference, defined either in a variant or prim.</p>");
register("kMayaRefAddToUSDDescription1", "<p>Add a Maya reference to a USD prim to enable working with original Maya data in your USD scene. Select a Maya scene file to add as a reference. Once a Maya reference file is added, a Maya transform node will appear in the Outliner at your selected prim, containing your newly added Maya reference. Use this dialog to build out the scope of your Maya reference.</p>");
register("kMayaRefAddToUSDDescription2", "<p><b>Tip:</b> Define your Maya Reference in a USD variant. This will enable your prim to have 2 variants you can switch between in the Outliner; the Maya reference and its USD cache.</p>");
register("kMayaRefUsdOptions", "USD Options");
register("kMayaRefUsdOptions", "Author Maya Reference File to USD");
register("kMayaRefMayaRefPrimName", "Maya Reference Prim Name:");
register("kMayaRefGroup", "Group");
register("kMayaRefPrimName", "Prim Name:");
Expand Down
7 changes: 6 additions & 1 deletion lib/mayaUsd/ufe/MayaUsdContextOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ const std::string getTargetLayerFilePath(const UsdPrim& prim)

bool _prepareUSDReferenceTargetLayer(const UsdPrim& prim)
{
return UsdMayaUtilFileSystem::prepareLayerSaveUILayer(getCurrentTargetLayer(prim), false);
static const bool useSceneFileForRoot = false;
return UsdMayaUtilFileSystem::prepareLayerSaveUILayer(
getCurrentTargetLayer(prim), useSceneFileForRoot);
}

// Ask SDF for all supported extensions:
Expand Down Expand Up @@ -616,6 +618,9 @@ Ufe::UndoableCommand::Ptr MayaUsdContextOps::doOpCmd(const ItemPath& itemPath)
WaitCursor wait;
MGlobal::executeCommand(script, /* display = */ true, /* undoable = */ true);
} else if (itemPath[0] == kAddMayaReferenceItem) {
if (!_prepareUSDReferenceTargetLayer(prim()))
return nullptr;

MString script;
script.format("addMayaReferenceToUsd \"^1s\"", Ufe::PathString::string(path()).c_str());
MString result = MGlobal::executeCommandStringResult(
Expand Down
88 changes: 52 additions & 36 deletions plugin/adsk/scripts/mayaUsd_USDRootFileRelative.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,63 +65,63 @@ def getRelativeFilePathRoot():
return _relativeToFilePath

@classmethod
def uiCreate(cls, parentLayout, relativeToWhat):
def uiCreate(cls, parentLayout):
"""
Helper method to create the UI layout for the file relative actions.
Input parentLayout arg is expected to be a scroll layout into which controls
can be added.
Input relativeToWhat tells what the file is relative to. See the class docs.
"""
mayaRefUtils.pushOptionsUITemplate()
cmds.setParent(parentLayout)

topForm = cmds.columnLayout('actionOptionsForm', rowSpacing=5)

kRelativePathOptionsStr = getMayaUsdString("kRelativePathOptions")
kMakePathRelativeStr = getMayaUsdString("kMakePathRelativeTo" + relativeToWhat)
kMakePathRelativeAnnStr = getMayaUsdString("kMakePathRelativeTo" + relativeToWhat + "Ann")
kUnresolvedPathStr = getMayaUsdString("kUnresolvedPath")
kUnresolvedPathAnnStr = getMayaUsdString("kUnresolvedPathAnn")

optBoxMarginWidth = mel.eval('global int $gOptionBoxTemplateDescriptionMarginWidth; $gOptionBoxTemplateDescriptionMarginWidth += 0')
cmds.setParent(topForm)
cmds.frameLayout(label=kRelativePathOptionsStr, collapsable=False)
widgetColumn = cmds.columnLayout()

cls.uiCreateFields()

return topForm

@classmethod
def uiCreateFields(cls):
"""
Helper method to create the UI fields for the file relative actions.
"""
kMakePathRelativeStr = getMayaUsdString("kMakePathRelativeTo" + cls.kRelativeToWhat)
kMakePathRelativeAnnStr = getMayaUsdString("kMakePathRelativeTo" + cls.kRelativeToWhat + "Ann")
kUnresolvedPathStr = getMayaUsdString("kUnresolvedPath")
kUnresolvedPathAnnStr = getMayaUsdString("kUnresolvedPathAnn")

cmds.checkBox(cls.kMakePathRelativeCheckBox, label=kMakePathRelativeStr, ann=kMakePathRelativeAnnStr)

cmds.checkBox(cls.kMakePathRelativeCheckBox, edit=True, changeCommand=cls.onMakePathRelativeChanged)
cmds.textFieldGrp(cls.kUnresolvedPathTextField, label=kUnresolvedPathStr, ann=kUnresolvedPathAnnStr, editable=False)
cls._haveRelativePathFields = True

return topForm

@classmethod
def uiInit(cls, parentLayout, canBeRelative, relativeToWhat):
def uiInit(cls, parentLayout):
"""
Helper method to initialize the UI layout for the file relative actions.
Input parentLayout arg is expected to be a scroll layout into which controls
can be added.
Input canBeRelative tells if the file can be made relative at all. If false,
the relative path UI is shown but disabled.
Input relativeToWhat tells what the file is relative to. See the class docs.
"""
cmds.setParent(parentLayout)

# Initialize the class variables.
cls._fileDialog = None
cls._acceptButton = None
cls._canBeRelative = canBeRelative
cls._ensureUsdExtension = True
cls._haveRelativePathFields = cmds.textFieldGrp(cls.kUnresolvedPathTextField, exists=True)

# Get the current checkbox value from optionVar (if any) and update checkbox.
if cmds.optionVar(exists='mayaUsd_MakePathRelativeTo' + relativeToWhat):
relative = cmds.optionVar(query='mayaUsd_MakePathRelativeTo' + relativeToWhat)
if cmds.optionVar(exists='mayaUsd_MakePathRelativeTo' + cls.kRelativeToWhat):
relative = cmds.optionVar(query='mayaUsd_MakePathRelativeTo' + cls.kRelativeToWhat)
cmds.checkBox(cls.kMakePathRelativeCheckBox, edit=True, value=relative)

# If if cannot be relative, then the checkbox and label should be disabled.
Expand All @@ -135,7 +135,7 @@ def uiInit(cls, parentLayout, canBeRelative, relativeToWhat):
if cls._haveRelativePathFields:
# We may need to hide the preview fields in certain cases
showPreviewFields = True
if relativeToWhat == 'SceneFile':
if cls.kRelativeToWhat == 'SceneFile':
showPreviewFields = cmds.file(q=True, exists=True)

cmds.textFieldGrp(cls.kUnresolvedPathTextField, edit=True, visible=showPreviewFields)
Expand All @@ -145,20 +145,18 @@ def uiInit(cls, parentLayout, canBeRelative, relativeToWhat):
cls.onMakePathRelativeChanged(makePathRelative)

@classmethod
def uiCommit(cls, parentLayout, relativeToWhat):
def uiCommit(cls, parentLayout):
"""
Helper method to commit the UI layout for the file relative actions.
Input parentLayout arg is expected to the a scroll layout into which controls
can be added.
Input relativeToWhat tells what the file is relative to. See the class docs.
"""
cmds.setParent(parentLayout)

# Get the current checkbox state and save to optionVar.
relative = cmds.checkBox(cls.kMakePathRelativeCheckBox, query=True, value=True)
cmds.optionVar(iv=('mayaUsd_MakePathRelativeTo' + relativeToWhat, relative))
cmds.optionVar(iv=('mayaUsd_MakePathRelativeTo' + cls.kRelativeToWhat, relative))

@staticmethod
def findWindowNameFromLayout(layoutName):
Expand Down Expand Up @@ -279,7 +277,7 @@ class usdRootFileRelative(usdFileRelative):

@classmethod
def uiCreate(cls, parentLayout):
return super(usdRootFileRelative, cls).uiCreate(parentLayout, cls.kRelativeToWhat)
return super(usdRootFileRelative, cls).uiCreate(parentLayout)

@classmethod
def uiInit(cls, parentLayout, filterType):
Expand All @@ -292,15 +290,16 @@ def uiInit(cls, parentLayout, filterType):
# postponed relative file path assignment
cls.setRelativeFilePathRoot(cmds.file(query=True, sceneName=True))
cls._relativeToScene = True
super(usdRootFileRelative, cls).uiInit(parentLayout, True, cls.kRelativeToWhat)
cls._canBeRelative = True
super(usdRootFileRelative, cls).uiInit(parentLayout)

@classmethod
def uiCommit(cls, parentLayout, selectedFile=None):
'''
Note: the function takes an unused selectedFile argument to be compatible
with the dialog2 command API.
'''
super(usdRootFileRelative, cls).uiCommit(parentLayout, cls.kRelativeToWhat)
super(usdRootFileRelative, cls).uiCommit(parentLayout)


class usdSubLayerFileRelative(usdFileRelative):
Expand All @@ -313,26 +312,26 @@ class usdSubLayerFileRelative(usdFileRelative):

@classmethod
def uiCreate(cls, parentLayout):
return super(usdSubLayerFileRelative, cls).uiCreate(parentLayout, cls.kRelativeToWhat)
return super(usdSubLayerFileRelative, cls).uiCreate(parentLayout)

@classmethod
def uiInit(cls, parentLayout, filterType, parentLayerPath):
'''
Note: the function takes an unused filterType argument to be compatible
with the dialog2 command API.
'''

cls._relativeToDir = parentLayerPath
canBeRelative = bool(cls._relativeToDir)
super(usdSubLayerFileRelative, cls).uiInit(parentLayout, canBeRelative, cls.kRelativeToWhat)
# If the parent layer is not saved, then the checkbox and label should be disabled.
cls._canBeRelative = bool(cls._relativeToDir)
super(usdSubLayerFileRelative, cls).uiInit(parentLayout)

@classmethod
def uiCommit(cls, parentLayout, selectedFile=None):
'''
Note: the function takes an unused selectedFile argument to be compatible
with the dialog2 command API.
'''
super(usdSubLayerFileRelative, cls).uiCommit(parentLayout, cls.kRelativeToWhat)
super(usdSubLayerFileRelative, cls).uiCommit(parentLayout)


class usdFileRelativeToEditTargetLayer(usdFileRelative):
Expand All @@ -345,7 +344,7 @@ class usdFileRelativeToEditTargetLayer(usdFileRelative):

@classmethod
def uiCreate(cls, parentLayout):
return super(usdFileRelativeToEditTargetLayer, cls).uiCreate(parentLayout, cls.kRelativeToWhat)
return super(usdFileRelativeToEditTargetLayer, cls).uiCreate(parentLayout)

@classmethod
def uiInit(cls, parentLayout, filterType):
Expand All @@ -355,16 +354,16 @@ def uiInit(cls, parentLayout, filterType):
'''
cls._relativeToDir = usdFileRelative.getRelativeFilePathRoot()
# If there is no target layer saved, then the checkbox and label should be disabled.
canBeRelative = bool(cls._relativeToDir)
super(usdFileRelativeToEditTargetLayer, cls).uiInit(parentLayout, canBeRelative, cls.kRelativeToWhat)
cls._canBeRelative = bool(cls._relativeToDir)
super(usdFileRelativeToEditTargetLayer, cls).uiInit(parentLayout)

@classmethod
def uiCommit(cls, parentLayout, selectedFile=None):
'''
Note: the function takes an unused selectedFile argument to be compatible
with the dialog2 command API.
'''
super(usdFileRelativeToEditTargetLayer, cls).uiCommit(parentLayout, cls.kRelativeToWhat)
super(usdFileRelativeToEditTargetLayer, cls).uiCommit(parentLayout)

class usdAddRefOrPayloadRelativeToEditTargetLayer(usdFileRelativeToEditTargetLayer):
'''
Expand Down Expand Up @@ -443,3 +442,20 @@ def uiInit(cls, parentLayout, filterType):
# Do not force the USD file extension since we are selecting image files.
cls._ensureUsdExtension = False


class usdMayaRefRelativeToEditTargetLayer(usdFileRelativeToEditTargetLayer):
'''
Helper class to create the UI for Maya ref optionally relative to a layer file
via the current USD edit target.
'''
@classmethod
def uiInit(cls, parentLayout, filterType):
'''
Note: the function takes an unused filterType argument to be compatible
with the dialog2 command API.
'''
super(usdMayaRefRelativeToEditTargetLayer, cls).uiInit(parentLayout, filterType)

# Do not force the USD file extension since we are selecting Maya files.
cls._ensureUsdExtension = False

0 comments on commit 7a4d6c0

Please sign in to comment.