Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LOOKDEVX-1688 - Fix extra Arnold refresh when moving nodes #3241

Merged
merged 2 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion lib/mayaUsd/listeners/stageNoticeListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <pxr/usd/usd/notice.h>
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usd/tokens.h>
#include <pxr/usd/usdShade/nodeGraph.h>
#include <pxr/usd/usdShade/shader.h>
#include <pxr/usd/usdUI/tokens.h>

#include <mutex>
Expand Down Expand Up @@ -193,6 +195,11 @@ bool _IsUiSchemaPrepend(const VtValue& v)
}
return false;
}

bool _IsShadingPrim(const UsdPrim& prim)
{
return prim && (prim.IsA<UsdShadeShader>() || prim.IsA<UsdShadeNodeGraph>());
}
} // namespace

UsdMayaStageNoticeListener::ChangeType
Expand Down Expand Up @@ -238,8 +245,14 @@ UsdMayaStageNoticeListener::ClassifyObjectsChanged(UsdNotice::ObjectsChanged con
for (PathRange::const_iterator it = pathsToUpdate.begin(); it != pathsToUpdate.end(); ++it) {
if (it->IsAbsoluteRootOrPrimPath()) {
const TfTokenVector changedFields = it.GetChangedFields();
if (!changedFields.empty()) {
for (auto&& changedField : changedFields) {
if (changedField == SdfFieldKeys->CustomData && it->IsPrimPath()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these two if conditions be combined?

if (_IsShadingPrim(notice.GetStage()->GetPrimAtPath(it->GetPrimPath()))) {
continue;
}
}
retVal = ChangeType::kUpdate;
break;
}
} else if (it->IsPropertyPath()) {
// We have a bunch of UI properties to ignore. Especially anything that comes from UI
Expand Down
13 changes: 0 additions & 13 deletions lib/mayaUsd/nodes/proxyShapeBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,9 @@ MObject MayaUsdProxyShapeBase::drawGuidePurposeAttr;
MObject MayaUsdProxyShapeBase::sessionLayerNameAttr;
MObject MayaUsdProxyShapeBase::rootLayerNameAttr;
MObject MayaUsdProxyShapeBase::mutedLayersAttr;
#if MAYA_API_VERSION >= 20240000 && MAYA_API_VERSION <= 20249999
// Change counter attributes
MObject MayaUsdProxyShapeBase::updateCounterAttr;
MObject MayaUsdProxyShapeBase::resyncCounterAttr;
#endif
// Output attributes
MObject MayaUsdProxyShapeBase::outTimeAttr;
MObject MayaUsdProxyShapeBase::outStageDataAttr;
Expand Down Expand Up @@ -396,7 +394,6 @@ MStatus MayaUsdProxyShapeBase::initialize()
retValue = addAttribute(outStageDataAttr);
CHECK_MSTATUS_AND_RETURN_IT(retValue);

#if MAYA_API_VERSION >= 20240000 && MAYA_API_VERSION <= 20249999
updateCounterAttr
= numericAttrFn.create("updateId", "upid", MFnNumericData::kInt64, -1, &retValue);
CHECK_MSTATUS_AND_RETURN_IT(retValue);
Expand All @@ -416,7 +413,6 @@ MStatus MayaUsdProxyShapeBase::initialize()
numericAttrFn.setInternal(true);
retValue = addAttribute(resyncCounterAttr);
CHECK_MSTATUS_AND_RETURN_IT(retValue);
#endif

outStageCacheIdAttr
= numericAttrFn.create("outStageCacheId", "ostcid", MFnNumericData::kInt, -1, &retValue);
Expand Down Expand Up @@ -591,7 +587,6 @@ void MayaUsdProxyShapeBase::postConstructor()
}
}

#if MAYA_API_VERSION >= 20240000 && MAYA_API_VERSION <= 20249999
/* virtual */
bool MayaUsdProxyShapeBase::getInternalValue(const MPlug& plug, MDataHandle& handle)
{
Expand All @@ -607,7 +602,6 @@ bool MayaUsdProxyShapeBase::getInternalValue(const MPlug& plug, MDataHandle& han

return retVal;
}
#endif

/* virtual */
MStatus MayaUsdProxyShapeBase::compute(const MPlug& plug, MDataBlock& dataBlock)
Expand Down Expand Up @@ -2023,19 +2017,12 @@ void MayaUsdProxyShapeBase::_OnStageObjectsChanged(const UsdNotice::ObjectsChang
MProfilingScope profilingScope(
_shapeBaseProfilerCategory, MProfiler::kColorB_L1, "Process USD objects changed");

#if MAYA_API_VERSION >= 20240000 && MAYA_API_VERSION <= 20249999
switch (UsdMayaStageNoticeListener::ClassifyObjectsChanged(notice)) {
case UsdMayaStageNoticeListener::ChangeType::kIgnored: return;
case UsdMayaStageNoticeListener::ChangeType::kResync: ++_UsdStageResyncCounter;
// [[fallthrough]]; // We want that fallthrough to have the update always triggered.
case UsdMayaStageNoticeListener::ChangeType::kUpdate: ++_UsdStageUpdateCounter; break;
}
#else
if (UsdMayaStageNoticeListener::ClassifyObjectsChanged(notice)
== UsdMayaStageNoticeListener::ChangeType::kIgnored) {
return;
}
#endif

// This will definitely force a BBox recomputation on "Frame All" or when framing a selected
// stage. Computing bounds in USD is expensive, so if it pops up in other frequently used
Expand Down
6 changes: 0 additions & 6 deletions lib/mayaUsd/nodes/proxyShapeBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,11 @@ class MayaUsdProxyShapeBase
MAYAUSD_CORE_PUBLIC
static MObject mutedLayersAttr;

#if MAYA_API_VERSION >= 20240000 && MAYA_API_VERSION <= 20249999
// Change counter attributes
MAYAUSD_CORE_PUBLIC
static MObject updateCounterAttr;
MAYAUSD_CORE_PUBLIC
static MObject resyncCounterAttr;
#endif

// Output attributes
MAYAUSD_CORE_PUBLIC
Expand Down Expand Up @@ -171,10 +169,8 @@ class MayaUsdProxyShapeBase

MAYAUSD_CORE_PUBLIC
void postConstructor() override;
#if MAYA_API_VERSION >= 20240000 && MAYA_API_VERSION <= 20249999
MAYAUSD_CORE_PUBLIC
bool getInternalValue(const MPlug&, MDataHandle&) override;
#endif
MAYAUSD_CORE_PUBLIC
MStatus compute(const MPlug& plug, MDataBlock& dataBlock) override;
MAYAUSD_CORE_PUBLIC
Expand Down Expand Up @@ -406,11 +402,9 @@ class MayaUsdProxyShapeBase
size_t _excludePrimPathsVersion { 1 };
size_t _UsdStageVersion { 1 };

#if MAYA_API_VERSION >= 20240000 && MAYA_API_VERSION <= 20249999
// Notification counters:
MInt64 _UsdStageUpdateCounter { 1 };
MInt64 _UsdStageResyncCounter { 1 };
#endif

MayaUsd::ProxyAccessor::Owner _usdAccessor;

Expand Down
79 changes: 39 additions & 40 deletions test/lib/ufe/testContextOps.py
Original file line number Diff line number Diff line change
Expand Up @@ -1481,8 +1481,6 @@ def testGeomCoponentAssignment(self):
dagPath = sl.getDagPath(0)
dagPath.extendToShape()

proxyShapeNode = dagPath.node()

with mayaUsd.lib.OpUndoItemList():
mayaUsd.lib.PrimUpdaterManager.duplicate(cmds.ls(cubeXForm, long=True)[0], psPathStr)

Expand All @@ -1493,26 +1491,25 @@ def testGeomCoponentAssignment(self):
self.assertEqual(topSubset.GetFamilyNameAttr().Get(), "componentTag")
self.assertFalse(topSubset.GetPrim().HasAPI(UsdShade.MaterialBindingAPI))

if mayaUtils.mayaMajorVersion() == 2024:
# We also can check the old sync counters:
counters= { "resync": cmds.getAttr(psPathStr + '.resyncId'),
"update" : cmds.getAttr(psPathStr + '.upid')}

def assertIsOnlyUpdate(self, counters, shapePathStr):
resyncCounter = cmds.getAttr(shapePathStr + '.resyncId')
updateCounter = cmds.getAttr(shapePathStr + '.updateId')
self.assertEqual(resyncCounter, counters["resync"])
self.assertGreater(updateCounter, counters["update"])
counters["resync"] = resyncCounter
counters["update"] = updateCounter

def assertIsResync(self, counters, shapePathStr):
resyncCounter = cmds.getAttr(shapePathStr + '.resyncId')
updateCounter = cmds.getAttr(shapePathStr + '.updateId')
self.assertGreater(resyncCounter, counters["resync"])
self.assertGreater(updateCounter, counters["update"])
counters["resync"] = resyncCounter
counters["update"] = updateCounter
# We also can check the old sync counters:
counters= { "resync": cmds.getAttr(psPathStr + '.resyncId'),
"update" : cmds.getAttr(psPathStr + '.upid')}

def assertIsOnlyUpdate(self, counters, shapePathStr):
resyncCounter = cmds.getAttr(shapePathStr + '.resyncId')
updateCounter = cmds.getAttr(shapePathStr + '.updateId')
self.assertEqual(resyncCounter, counters["resync"])
self.assertGreater(updateCounter, counters["update"])
counters["resync"] = resyncCounter
counters["update"] = updateCounter

def assertIsResync(self, counters, shapePathStr):
resyncCounter = cmds.getAttr(shapePathStr + '.resyncId')
updateCounter = cmds.getAttr(shapePathStr + '.updateId')
self.assertGreater(resyncCounter, counters["resync"])
self.assertGreater(updateCounter, counters["update"])
counters["resync"] = resyncCounter
counters["update"] = updateCounter

messageHandler = mayaUtils.TestProxyShapeUpdateHandler(psPathStr)
messageHandler.snapshot()
Expand All @@ -1530,60 +1527,62 @@ def assertIsResync(self, counters, shapePathStr):

# We expect a resync after this assignment:
self.assertTrue(messageHandler.isResync())
if mayaUtils.mayaMajorVersion() == 2024:
assertIsResync(self, counters, psPathStr)
assertIsResync(self, counters, psPathStr)

# setting a value the first time is a resync due to the creation of the attribute:
attrs = ufe.Attributes.attributes(shaderItem)
metallicAttr = attrs.attribute("inputs:metallic")
ufeCmd.execute(metallicAttr.setCmd(0.5))
self.assertTrue(messageHandler.isResync())
if mayaUtils.mayaMajorVersion() == 2024:
assertIsResync(self, counters, psPathStr)
assertIsResync(self, counters, psPathStr)

# Subsequent changes are updates:
ufeCmd.execute(metallicAttr.setCmd(0.7))
self.assertTrue(messageHandler.isUpdate())
if mayaUtils.mayaMajorVersion() == 2024:
assertIsOnlyUpdate(self, counters, psPathStr)
assertIsOnlyUpdate(self, counters, psPathStr)

# First undo is an update:
cmds.undo()
self.assertTrue(messageHandler.isUpdate())
if mayaUtils.mayaMajorVersion() == 2024:
assertIsOnlyUpdate(self, counters, psPathStr)
assertIsOnlyUpdate(self, counters, psPathStr)

# Second undo is a resync:
cmds.undo()
self.assertTrue(messageHandler.isResync())
if mayaUtils.mayaMajorVersion() == 2024:
assertIsResync(self, counters, psPathStr)
assertIsResync(self, counters, psPathStr)

# Third undo is also resync:
cmds.undo()
self.assertTrue(messageHandler.isResync())
if mayaUtils.mayaMajorVersion() == 2024:
assertIsResync(self, counters, psPathStr)
assertIsResync(self, counters, psPathStr)

# First redo is resync:
cmds.redo()
self.assertTrue(messageHandler.isResync())
if mayaUtils.mayaMajorVersion() == 2024:
assertIsResync(self, counters, psPathStr)
assertIsResync(self, counters, psPathStr)

# Second redo is resync:
cmds.redo()
self.assertTrue(messageHandler.isResync())
if mayaUtils.mayaMajorVersion() == 2024:
assertIsResync(self, counters, psPathStr)
assertIsResync(self, counters, psPathStr)

# Third redo is update:
cmds.redo()
self.assertTrue(messageHandler.isUpdate())
if mayaUtils.mayaMajorVersion() == 2024:
assertIsOnlyUpdate(self, counters, psPathStr)
assertIsOnlyUpdate(self, counters, psPathStr)
currentCacheId = messageHandler.getStageCacheId()

# Adding custom data to a shader prim is not cause for update. This
# happens when setting position info on an input node, nodegraph, or
# material. Also happens when storing alpha channel of a backdrop
# color.
shaderHier = ufe.Hierarchy.hierarchy(shaderItem)
materialItem = shaderHier.parent()
materialPrim = usdUtils.getPrimFromSceneItem(materialItem)
materialPrim.SetCustomData({"Autodesk": {"ldx_inputPos" : "-624 -60.5",
"ldx_outputPos" : "399 -60"}})
self.assertTrue(messageHandler.isUnchanged())

# Changing the whole stage is a resync:
testFile = testUtils.getTestScene("MaterialX", "MtlxValueTypes.usda")
cmds.setAttr('{}.filePath'.format(psPathStr), testFile, type='string')
Expand Down