From b9797e070674b007566970db4fcc39c49c865e66 Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Thu, 20 Jul 2023 16:50:41 -0400 Subject: [PATCH 1/2] LOOKDEVX-1688 - Fix extra Arnold refresh when moving nodes --- lib/mayaUsd/listeners/stageNoticeListener.cpp | 15 +++- lib/mayaUsd/nodes/proxyShapeBase.cpp | 13 --- lib/mayaUsd/nodes/proxyShapeBase.h | 6 -- test/lib/ufe/testContextOps.py | 79 +++++++++---------- 4 files changed, 53 insertions(+), 60 deletions(-) diff --git a/lib/mayaUsd/listeners/stageNoticeListener.cpp b/lib/mayaUsd/listeners/stageNoticeListener.cpp index b4f0a10cf0..92767d9e02 100644 --- a/lib/mayaUsd/listeners/stageNoticeListener.cpp +++ b/lib/mayaUsd/listeners/stageNoticeListener.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -193,6 +195,11 @@ bool _IsUiSchemaPrepend(const VtValue& v) } return false; } + +bool _IsShadingPrim(const UsdPrim& prim) +{ + return prim && (prim.IsA() || prim.IsA()); +} } // namespace UsdMayaStageNoticeListener::ChangeType @@ -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()) { + 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 diff --git a/lib/mayaUsd/nodes/proxyShapeBase.cpp b/lib/mayaUsd/nodes/proxyShapeBase.cpp index 2a63ce0197..d3482adf9c 100644 --- a/lib/mayaUsd/nodes/proxyShapeBase.cpp +++ b/lib/mayaUsd/nodes/proxyShapeBase.cpp @@ -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; @@ -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); @@ -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); @@ -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) { @@ -607,7 +602,6 @@ bool MayaUsdProxyShapeBase::getInternalValue(const MPlug& plug, MDataHandle& han return retVal; } -#endif /* virtual */ MStatus MayaUsdProxyShapeBase::compute(const MPlug& plug, MDataBlock& dataBlock) @@ -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 diff --git a/lib/mayaUsd/nodes/proxyShapeBase.h b/lib/mayaUsd/nodes/proxyShapeBase.h index 9f09a8cd6e..632d48b037 100644 --- a/lib/mayaUsd/nodes/proxyShapeBase.h +++ b/lib/mayaUsd/nodes/proxyShapeBase.h @@ -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 @@ -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 @@ -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; diff --git a/test/lib/ufe/testContextOps.py b/test/lib/ufe/testContextOps.py index f85865534d..b983970ba9 100644 --- a/test/lib/ufe/testContextOps.py +++ b/test/lib/ufe/testContextOps.py @@ -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) @@ -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() @@ -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') From bf9c3e97079383659851a3689d6fb351d87cb46f Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Fri, 21 Jul 2023 09:51:28 -0400 Subject: [PATCH 2/2] Improvement from review comment. --- lib/mayaUsd/listeners/stageNoticeListener.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/mayaUsd/listeners/stageNoticeListener.cpp b/lib/mayaUsd/listeners/stageNoticeListener.cpp index 92767d9e02..d644f4c655 100644 --- a/lib/mayaUsd/listeners/stageNoticeListener.cpp +++ b/lib/mayaUsd/listeners/stageNoticeListener.cpp @@ -246,10 +246,9 @@ UsdMayaStageNoticeListener::ClassifyObjectsChanged(UsdNotice::ObjectsChanged con if (it->IsAbsoluteRootOrPrimPath()) { const TfTokenVector changedFields = it.GetChangedFields(); for (auto&& changedField : changedFields) { - if (changedField == SdfFieldKeys->CustomData && it->IsPrimPath()) { - if (_IsShadingPrim(notice.GetStage()->GetPrimAtPath(it->GetPrimPath()))) { - continue; - } + if (changedField == SdfFieldKeys->CustomData && it->IsPrimPath() + && _IsShadingPrim(notice.GetStage()->GetPrimAtPath(it->GetPrimPath()))) { + continue; } retVal = ChangeType::kUpdate; break;