Skip to content

Commit

Permalink
EMSUSD-671 Remove the load payloads proxy shape attribute
Browse files Browse the repository at this point in the history
Instead, we will always use the existing payload rules dynamic attribute.

- Remove the "loadPayloads" attribute from the proxy shape.
- Add Python binding to new functions to set and retrieve if all payloads are loaded or not.
- Split-up existing load-rules helper functions to give more fined-grained access to the saved load rules in order to support the Python API.
- Use the new Python helper functions when creating or loading a stage.
- Adjust one unit test.
  • Loading branch information
pierrebai-adsk committed Dec 21, 2023
1 parent 8f08eb0 commit 90f788c
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 53 deletions.
41 changes: 8 additions & 33 deletions lib/mayaUsd/nodes/proxyShapeBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ MObject MayaUsdProxyShapeBase::filePathAttr;
MObject MayaUsdProxyShapeBase::filePathRelativeAttr;
MObject MayaUsdProxyShapeBase::primPathAttr;
MObject MayaUsdProxyShapeBase::excludePrimPathsAttr;
MObject MayaUsdProxyShapeBase::loadPayloadsAttr;
MObject MayaUsdProxyShapeBase::shareStageAttr;
MObject MayaUsdProxyShapeBase::timeAttr;
MObject MayaUsdProxyShapeBase::complexityAttr;
Expand Down Expand Up @@ -279,15 +278,6 @@ MStatus MayaUsdProxyShapeBase::initialize()
retValue = addAttribute(excludePrimPathsAttr);
CHECK_MSTATUS_AND_RETURN_IT(retValue);

loadPayloadsAttr
= numericAttrFn.create("loadPayloads", "lpl", MFnNumericData::kBoolean, 1.0, &retValue);
CHECK_MSTATUS_AND_RETURN_IT(retValue);
numericAttrFn.setKeyable(true);
numericAttrFn.setReadable(false);
numericAttrFn.setAffectsAppearance(true);
retValue = addAttribute(loadPayloadsAttr);
CHECK_MSTATUS_AND_RETURN_IT(retValue);

shareStageAttr
= numericAttrFn.create("shareStage", "scmp", MFnNumericData::kBoolean, 1.0, &retValue);
CHECK_MSTATUS_AND_RETURN_IT(retValue);
Expand Down Expand Up @@ -479,13 +469,6 @@ MStatus MayaUsdProxyShapeBase::initialize()
retValue = attributeAffects(shareStageAttr, outStageCacheIdAttr);
CHECK_MSTATUS_AND_RETURN_IT(retValue);

retValue = attributeAffects(loadPayloadsAttr, inStageDataCachedAttr);
CHECK_MSTATUS_AND_RETURN_IT(retValue);
retValue = attributeAffects(loadPayloadsAttr, outStageDataAttr);
CHECK_MSTATUS_AND_RETURN_IT(retValue);
retValue = attributeAffects(loadPayloadsAttr, outStageCacheIdAttr);
CHECK_MSTATUS_AND_RETURN_IT(retValue);

retValue = attributeAffects(inStageDataAttr, inStageDataCachedAttr);
CHECK_MSTATUS_AND_RETURN_IT(retValue);
retValue = attributeAffects(inStageDataAttr, outStageDataAttr);
Expand Down Expand Up @@ -1098,20 +1081,13 @@ MStatus MayaUsdProxyShapeBase::computeInStageDataCached(MDataBlock& dataBlock)

if (finalUsdStage) {
// Compute the load set for the stage.
MDataHandle loadPayloadsHandle = dataBlock.inputValue(loadPayloadsAttr, &retValue);
CHECK_MSTATUS_AND_RETURN_IT(retValue);

// Apply the payload rules based on either the saved payload rules
// dynamic attribute containing the exact load rules for payload,
// or the load-payload attribute.
// dynamic attribute containing the exact load rules for payload.
// If no such attribute exists, load everything.
if (hasLoadRulesAttribute(*this)) {
copyLoadRulesFromAttribute(*this, *finalUsdStage);
} else {
if (loadPayloadsHandle.asBool()) {
finalUsdStage->Load(SdfPath("/"), UsdLoadPolicy::UsdLoadWithDescendants);
} else {
finalUsdStage->Unload(SdfPath("/"));
}
finalUsdStage->Load(SdfPath("/"), UsdLoadPolicy::UsdLoadWithDescendants);
}

primPath = finalUsdStage->GetPseudoRoot().GetPath();
Expand Down Expand Up @@ -1150,9 +1126,9 @@ MStatus MayaUsdProxyShapeBase::computeInStageDataCached(MDataBlock& dataBlock)
UsdStageRefPtr MayaUsdProxyShapeBase::getUnsharedStage(UsdStage::InitialLoadSet loadSet)
{
// The unshared stages are *also* kept in a stage cache so that we can find them
// again when proxy shape attribute change. For example, if the 'loadPayloads'
// attribute change, we want to find the same unshared stage, we don't want to lose
// edits, in particular in its session layer.
// again when proxy shape attribute change. For example, if the payloads loading
// change, we want to find the same unshared stage, we don't want to lose edits,
// in particular in its session layer.
//
// We also need to be able to find them when switching a stage between non-shared
// and shared, so that we can transfer the content of the session layer.
Expand Down Expand Up @@ -1660,7 +1636,6 @@ MStatus MayaUsdProxyShapeBase::preEvaluation(
// All the plugs that affect outStageDataAttr
evaluationNode.dirtyPlugExists(filePathAttr)
|| evaluationNode.dirtyPlugExists(primPathAttr)
|| evaluationNode.dirtyPlugExists(loadPayloadsAttr)
|| evaluationNode.dirtyPlugExists(shareStageAttr)
|| evaluationNode.dirtyPlugExists(inStageDataAttr)
|| evaluationNode.dirtyPlugExists(stageCacheIdAttr)) {
Expand Down Expand Up @@ -1714,8 +1689,8 @@ MStatus MayaUsdProxyShapeBase::setDependentsDirty(const MPlug& plug, MPlugArray&
} else if (
plug == outStageDataAttr ||
// All the plugs that affect outStageDataAttr
plug == filePathAttr || plug == primPathAttr || plug == loadPayloadsAttr
|| plug == shareStageAttr || plug == inStageDataAttr || plug == stageCacheIdAttr) {
plug == filePathAttr || plug == primPathAttr || plug == shareStageAttr
|| plug == inStageDataAttr || plug == stageCacheIdAttr) {
_IncreaseUsdStageVersion();
MayaUsdProxyStageInvalidateNotice(*this).Send();
}
Expand Down
2 changes: 0 additions & 2 deletions lib/mayaUsd/nodes/proxyShapeBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ class MayaUsdProxyShapeBase
MAYAUSD_CORE_PUBLIC
static MObject excludePrimPathsAttr;
MAYAUSD_CORE_PUBLIC
static MObject loadPayloadsAttr;
MAYAUSD_CORE_PUBLIC
static MObject shareStageAttr;
MAYAUSD_CORE_PUBLIC
static MObject timeAttr;
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ target_sources(${PYTHON_TARGET_NAME}
wrapColorSpace.cpp
wrapConverter.cpp
wrapDiagnosticDelegate.cpp
wrapLoadRules.cpp
wrapMeshWriteUtils.cpp
wrapOpUndoItem.cpp
wrapQuery.cpp
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/python/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ TF_WRAP_MODULE
TF_WRAP(Converter);
TF_WRAP(ConverterArgs);
TF_WRAP(DiagnosticDelegate);
TF_WRAP(LoadRules);
TF_WRAP(MeshWriteUtils);
#ifdef UFE_V3_FEATURES_AVAILABLE
TF_WRAP(PrimUpdater);
Expand Down
55 changes: 55 additions & 0 deletions lib/mayaUsd/python/wrapLoadRules.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// Copyright 2023 Autodesk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <mayaUsd/utils/loadRules.h>
#include <mayaUsd/utils/util.h>

#include <pxr/base/tf/pyResultConversions.h>

#include <boost/python/def.hpp>

using namespace boost::python;

namespace {

bool setLoadRules(const std::string& shapeName, bool loadAllPayloads)
{
MObject shapeObj;
UsdMayaUtil::GetMObjectByName(shapeName, shapeObj);
return MayaUsd::setLoadRulesAttribute(shapeObj, loadAllPayloads);
}

bool isLoadingAll(const std::string& shapeName)
{
MObject shapeObj;
UsdMayaUtil::GetMObjectByName(shapeName, shapeObj);

PXR_NS::UsdStageLoadRules rules;
MStatus status = MayaUsd::getLoadRulesFromAttribute(shapeObj, rules);

// Note: when there are no load rules set, we load all payloads.
if (!status)
return true;

return rules.IsLoadedWithAllDescendants(PXR_NS::SdfPath("/"));
}

} // namespace

void wrapLoadRules()
{
def("setLoadRulesAttribute", setLoadRules);
def("isLoadingAllPaylaods", isLoadingAll);
}
16 changes: 16 additions & 0 deletions lib/mayaUsd/utils/loadRules.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <pxr/usd/usd/stage.h>

#include <maya/MApiNamespace.h>
#include <maya/MObject.h>

namespace MAYAUSD_NS_DEF {

Expand All @@ -43,6 +44,21 @@ MStatus copyLoadRulesFromAttribute(
const PXR_NS::MayaUsdProxyShapeBase& proxyShape,
PXR_NS::UsdStage& stage);

/*! \brief get the load rules from data in a dynamic attribute on the object.
*/
MAYAUSD_CORE_PUBLIC
MStatus getLoadRulesFromAttribute(const MObject& proxyObj, PXR_NS::UsdStageLoadRules& rules);

/*! \brief set the load rules to load-all or unload-all in a dynamic attribute on the object.
Used to set the initial load rules when creating a proxy shape.
*/
MAYAUSD_CORE_PUBLIC
MStatus
setLoadRulesAttribute(const PXR_NS::MayaUsdProxyShapeBase& proxyShape, bool loadAllPayloads);

MAYAUSD_CORE_PUBLIC
MStatus setLoadRulesAttribute(const MObject& proxyObj, bool loadAllPayloads);

} // namespace MAYAUSD_NS_DEF

#endif
41 changes: 37 additions & 4 deletions lib/mayaUsd/utils/loadRulesAttribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,16 @@ MStatus copyLoadRulesToAttribute(const PXR_NS::UsdStage& stage, MayaUsdProxyShap

MStatus copyLoadRulesFromAttribute(const MayaUsdProxyShapeBase& proxyShape, PXR_NS::UsdStage& stage)
{
MObject proxyObj = proxyShape.thisMObject();
PXR_NS::UsdStageLoadRules rules;
MStatus status = MayaUsd::getLoadRulesFromAttribute(proxyShape.thisMObject(), rules);
if (status == MS::kSuccess)
UsdUfe::setLoadRules(stage, rules);

return status;
}

MStatus getLoadRulesFromAttribute(const MObject& proxyObj, PXR_NS::UsdStageLoadRules& rules)
{
if (proxyObj.isNull())
return MS::kFailure;

Expand All @@ -73,10 +82,34 @@ MStatus copyLoadRulesFromAttribute(const MayaUsdProxyShapeBase& proxyShape, PXR_

MString loadRulesText;
MStatus status = getDynamicAttribute(depNode, loadRulesAttrName, loadRulesText);
if (status == MS::kSuccess)
UsdUfe::setLoadRulesFromText(stage, loadRulesText.asChar());
if (!status)
return status;

return status;
rules = UsdUfe::createLoadRulesFromText(loadRulesText.asChar());
return MS::kSuccess;
}

MStatus setLoadRulesAttribute(const PXR_NS::MayaUsdProxyShapeBase& proxyShape, bool loadAllPayloads)
{
return setLoadRulesAttribute(proxyShape.thisMObject(), loadAllPayloads);
}

MStatus setLoadRulesAttribute(const MObject& proxyObj, bool loadAllPayloads)
{
if (proxyObj.isNull())
return MS::kFailure;

PXR_NS::UsdStageLoadRules rules;
if (loadAllPayloads) {
rules.LoadWithDescendants(PXR_NS::SdfPath("/"));
} else {
rules.Unload(PXR_NS::SdfPath("/"));
}

const std::string loadRulesText = UsdUfe::convertLoadRulesToText(rules);

MFnDependencyNode depNode(proxyObj);
return setDynamicAttribute(depNode, loadRulesAttrName, loadRulesText.c_str());
}

} // namespace MAYAUSD_NS_DEF
5 changes: 5 additions & 0 deletions lib/usdUfe/utils/loadRules.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ std::string convertLoadRulesToText(const PXR_NS::UsdStage& stage);
USDUFE_PUBLIC
void setLoadRulesFromText(PXR_NS::UsdStage& stage, const std::string& text);

/*! \brief set the stage load rules if they are different from the current ones.
*/
USDUFE_PUBLIC
void setLoadRules(PXR_NS::UsdStage& stage, const PXR_NS::UsdStageLoadRules& newLoadRules);

/*! \brief convert the load rules to a text format.
*/
USDUFE_PUBLIC
Expand Down
6 changes: 5 additions & 1 deletion lib/usdUfe/utils/loadRulesText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ std::string convertLoadRulesToText(const PXR_NS::UsdStage& stage)

void setLoadRulesFromText(PXR_NS::UsdStage& stage, const std::string& text)
{
const auto newLoadRules = createLoadRulesFromText(text);
setLoadRules(stage, createLoadRulesFromText(text));
}

void setLoadRules(PXR_NS::UsdStage& stage, const PXR_NS::UsdStageLoadRules& newLoadRules)
{
if (stage.GetLoadRules() != newLoadRules)
stage.SetLoadRules(newLoadRules);
}
Expand Down
6 changes: 4 additions & 2 deletions plugin/adsk/scripts/AETemplateHelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def ProxyShapeFilePathChanged(filePathAttr, newFilePath=None):
# in that case.
primPath = cmds.getAttr(stageName+'.primPath') or ''
excludedPrimPaths = cmds.getAttr(stageName+'.excludePrimPaths') or ''
loadPayloads = cmds.getAttr(stageName+'.loadPayloads') or 0
loadPayloads = mayaUsdLib.isLoadingAllPaylaods(stageName)

cmds.optionVar(stringValue=('stageFromFile_primPath', primPath))
cmds.optionVar(stringValue=('stageFromFile_excludePrimPath', excludedPrimPaths))
Expand Down Expand Up @@ -214,11 +214,13 @@ def ProxyShapeFilePathChanged(filePathAttr, newFilePath=None):
excludedPrimPaths = cmds.optionVar(query='stageFromFile_excludePrimPath')
loadPayloads = cmds.optionVar(query='stageFromFile_loadPayloads')

# Note: load rules must be the first thing set so the stage gets loaded in teh correct state right away.
mayaUsdLib.setLoadRulesAttribute(stageName, loadPayloads)

cmds.setAttr(filePathAttr, usdFileToLoad, type='string')
cmds.setAttr(filePathAttr+"Relative", requireRelative)
cmds.setAttr(stageName+'.primPath', primPath, type="string")
cmds.setAttr(stageName+'.excludePrimPaths', excludedPrimPaths, type="string")
cmds.setAttr(stageName+'.loadPayloads', loadPayloads)

return True
elif newFilePath is not None:
Expand Down
23 changes: 14 additions & 9 deletions plugin/adsk/scripts/mayaUsd_createStageFromFile.mel
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ proc setOptionVars(int $forceFactorySettings)
optionVar -stringValue stageFromFile_excludePrimPath "";
}

if ($forceFactorySettings || !`optionVar -exists stageFromFile_loadPayloads`) {
optionVar -intValue stageFromFile_loadPayloads 1;
if ($forceFactorySettings || !`optionVar -exists stageFromFile_loadAllPayloads`) {
optionVar -intValue stageFromFile_loadAllPayloads 1;
}
}

Expand Down Expand Up @@ -81,7 +81,7 @@ global proc string stageFromFile_UISetup(string $parent)
checkBoxGrp -l `getMayaUsdString("kLoadPayloads")`
-ann `getMayaUsdString("kLoadPayloadsAnn")`
-sbm `getMayaUsdString("kLoadPayloadsSbm")`
loadPayloadsCheckBox;
loadAllPayloadsCheckBox;

frameLayout -label `getMayaUsdString("kLabelStageDisplay")` -parent $frame -collapsable false;
textFieldGrp -l `getMayaUsdString("kPrimPath")`
Expand All @@ -107,12 +107,12 @@ global proc stageFromFile_UIInit(string $parent, string $filterType)

string $ppath = `optionVar -q stageFromFile_primPath`;
string $exppath = `optionVar -q stageFromFile_excludePrimPath`;
int $loadp = `optionVar -q stageFromFile_loadPayloads`;
int $loadp = `optionVar -q stageFromFile_loadAllPayloads`;

setParent $parent;
textFieldGrp -e -text $ppath primPathField;
textFieldGrp -e -text $exppath excludePrimPathField;
checkBoxGrp -e -value1 $loadp loadPayloadsCheckBox;
checkBoxGrp -e -value1 $loadp loadAllPayloadsCheckBox;
}

global proc stageFromFile_UICommit(string $parent)
Expand All @@ -127,8 +127,8 @@ global proc stageFromFile_UICommit(string $parent)
(`textFieldGrp -q -text primPathField`);
optionVar -stringValue stageFromFile_excludePrimPath
(`textFieldGrp -q -text excludePrimPathField`);
optionVar -intValue stageFromFile_loadPayloads
(`checkBoxGrp -q -value1 loadPayloadsCheckBox`);
optionVar -intValue stageFromFile_loadAllPayloads
(`checkBoxGrp -q -value1 loadAllPayloadsCheckBox`);
}

proc string doCreateStage(string $fileName)
Expand All @@ -140,7 +140,11 @@ proc string doCreateStage(string $fileName)

string $ppath = `optionVar -q stageFromFile_primPath`;
string $exppath = `optionVar -q stageFromFile_excludePrimPath`;
int $loadp = `optionVar -q stageFromFile_loadPayloads`;
int $loadp = `optionVar -q stageFromFile_loadAllPayloads`;
string $loadpStr = "True";
if ($loadp == 0) {
$loadpStr = "False";
}

string $fileNameToSave = $fileName;
int $requireRelative = (`optionVar -exists mayaUsd_MakePathRelativeToSceneFile` && `optionVar -query mayaUsd_MakePathRelativeToSceneFile`);
Expand All @@ -149,11 +153,12 @@ proc string doCreateStage(string $fileName)
}

string $shapeNode = `createNode "mayaUsdProxyShape" -skipSelect -name ($baseName+"Shape")`;
// Note: load rules must be the first thing set so the stage gets loaded in teh correct state right away.
python("import mayaUsd.lib as mayaUsdLib; mayaUsdLib.setLoadRulesAttribute('" + $shapeNode + "', " + $loadpStr + ")");
setAttr -type "string" ($shapeNode+".filePath") $fileNameToSave;
setAttr ($shapeNode+".filePathRelative") $requireRelative;
setAttr -type "string" ($shapeNode+".primPath") $ppath;
setAttr -type "string" ($shapeNode+".excludePrimPaths") $exppath;
setAttr ($shapeNode+".loadPayloads") $loadp;
connectAttr time1.outTime ($shapeNode+".time");
select -r $shapeNode;
string $fullPath[] = `ls -l $shapeNode`;
Expand Down
4 changes: 2 additions & 2 deletions test/lib/mayaUsd/nodes/testProxyShapeBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,10 +574,10 @@ def testUnsavedStagePreserveRootLayerWhenUpdated(self):
# verify that the prim exists.
self._verifyPrim()

# Set an attribute on the proxy shape. Here we set the loadPayloads.
# Set an attribute on the proxy shape. Here we set the shareStage.
# It was already set, this only triggers a Maya node recompute.
_, proxyShapePath = self._getStage()
cmds.setAttr('{}.{}'.format(proxyShapePath,"loadPayloads"), True)
cmds.setAttr('{}.{}'.format(proxyShapePath,"shareStage"), True)

# Verify that we did not lose the data on the root layer.
self._verifyPrim()
Expand Down

0 comments on commit 90f788c

Please sign in to comment.