From 49d76119ca8099b36f2f60109a7a894ec1a8b009 Mon Sep 17 00:00:00 2001 From: Julien Frantz Date: Thu, 6 Jun 2024 18:45:46 +0200 Subject: [PATCH 1/3] PrimUpdaterManager - Fix displayLayer loss on mergeToUsd and duplicate --- lib/mayaUsd/fileio/primUpdaterManager.cpp | 31 +++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/mayaUsd/fileio/primUpdaterManager.cpp b/lib/mayaUsd/fileio/primUpdaterManager.cpp index 8822fa8bca..8795e5ea09 100644 --- a/lib/mayaUsd/fileio/primUpdaterManager.cpp +++ b/lib/mayaUsd/fileio/primUpdaterManager.cpp @@ -611,7 +611,6 @@ PushCustomizeSrc pushExport( auto usdPathToDagPathMap = std::make_shared(); for (const auto& v : writeJob.GetDagPathToUsdPathMap()) { usdPathToDagPathMap->insert(UsdPathToDagPathMap::value_type(v.second, v.first)); - context._pushExtras.processItem(v.first, v.second); } std::get(pushCustomizeSrc) = usdPathToDagPathMap; @@ -620,6 +619,20 @@ PushCustomizeSrc pushExport( return pushCustomizeSrc; } +//------------------------------------------------------------------------------ +// +void processPushExtras( + const MayaUsd::ufe::ReplicateExtrasToUSD& pushExtras, + const UsdPathToDagPathMap& srcDagPathMap, + const SdfPath& srcRootPath, + const SdfPath& dstRootPath) +{ + for (const auto& srcPaths : srcDagPathMap) { + const auto dstPrimPath = srcPaths.first.ReplacePrefix(srcRootPath, dstRootPath); + pushExtras.processItem(srcPaths.second, dstPrimPath); + } +} + //------------------------------------------------------------------------------ // SdfPath getDstSdfPath(const Ufe::Path& ufePulledPath, const SdfPath& srcSdfPath, bool isCopy) @@ -1094,10 +1107,18 @@ bool PrimUpdaterManager::mergeToUsd( auto pushCustomizeSrc = pushExport(pulledPath, depNodeFn.object(), context); progressBar.advance(); + const auto& srcDagPathMap = std::get(pushCustomizeSrc); + + if (TF_VERIFY(srcDagPathMap)) { + const auto& srcRootPath = std::get(pushCustomizeSrc); + const auto dstRootPath = getDstSdfPath(pulledPath, srcRootPath, isCopy); + processPushExtras(context._pushExtras, *srcDagPathMap, srcRootPath, dstRootPath); + } + // 2) Traverse the in-memory layer, creating a prim updater for each prim, // and call Push for each updater. Build a new context with the USD path // to Maya path mapping information. - context.SetUsdPathToDagPathMap(std::get(pushCustomizeSrc)); + context.SetUsdPathToDagPathMap(srcDagPathMap); if (!isCopy) { if (!FunctionUndoItem::execute( @@ -1631,6 +1652,12 @@ bool PrimUpdaterManager::duplicate( const SdfPath srcParentPath = srcRootPath.GetParentPath(); const SdfPath dstParentPath = dstParentPrim.GetPath(); + const auto& srcPathMapPtr = std::get(pushExportOutput); + + if (TF_VERIFY(srcPathMapPtr)) { + processPushExtras(context._pushExtras, *srcPathMapPtr, srcParentPath, dstParentPath); + } + CopyLayerPrimsOptions options; options.progressBar = &progressBar; From dda97353f0ad5b9b45d2697e8e07dfa50085d004 Mon Sep 17 00:00:00 2001 From: Julien Frantz Date: Thu, 6 Jun 2024 18:49:39 +0200 Subject: [PATCH 2/3] PrimUpdaterManager - unit tests for merging/duplicating non-root prims. --- test/lib/ufe/testDisplayLayer.py | 95 +++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/test/lib/ufe/testDisplayLayer.py b/test/lib/ufe/testDisplayLayer.py index b5b5c80db8..6ed9988f67 100644 --- a/test/lib/ufe/testDisplayLayer.py +++ b/test/lib/ufe/testDisplayLayer.py @@ -397,7 +397,7 @@ def testDisplayLayerDuplicate(self): layerObjs = cmds.editDisplayLayerMembers(self.LAYER1, query=True, **self.kwArgsEditDisplayLayerMembers) XFORM1_CUBE2 = '|stage1|stageShape1,/Xform1/Cube2' self.assertTrue(XFORM1_CUBE2 in layerObjs) - self._testLayerFromPath(XFORM1_CUBE2, self.LAYER1) + self._testLayerFromPath(XFORM1_CUBE2, self.LAYER1) def testDisplayLayerClear(self): cmdHelp = cmds.help('editDisplayLayerMembers') @@ -437,37 +437,68 @@ def testDisplayLayerClear(self): def testDisplayLayerEditAsMaya(self): '''Display layer membership in Edit As Maya workflow.''' - - (ps, xlateOp, xlation, aUsdUfePathStr, aUsdUfePath, aUsdItem, - _, _, _, _, _) = createSimpleXformScene() - - # Add an item to a new display layer - cmds.createDisplayLayer(name='layer1', number=1, empty=True) - cmds.editDisplayLayerMembers('layer1', '|stage1|stageShape1,/A', noRecurse=True) - - # Edit aPrim as Maya data. - with mayaUsd.lib.OpUndoItemList(): - self.assertTrue(mayaUsd.lib.PrimUpdaterManager.canEditAsMaya(aUsdUfePathStr)) - self.assertTrue(mayaUsd.lib.PrimUpdaterManager.editAsMaya(aUsdUfePathStr)) - - # Check display layer membership on the other side - layerObjs = cmds.editDisplayLayerMembers('layer1', query=True, **self.kwArgsEditDisplayLayerMembers) - self.assertTrue("|__mayaUsd__|AParent|A" in layerObjs) - - # Create a new layer and put the item there - cmds.createDisplayLayer(name='layer2', number=1, empty=True) - cmds.editDisplayLayerMembers('layer2', "|__mayaUsd__|AParent|A", noRecurse=True) - - # Merge edits back to USD. - aMayaItem = ufe.GlobalSelection.get().front() - aMayaPath = aMayaItem.path() - aMayaPathStr = ufe.PathString.string(aMayaPath) - with mayaUsd.lib.OpUndoItemList(): - self.assertTrue(mayaUsd.lib.PrimUpdaterManager.mergeToUsd(aMayaPathStr)) - - # Check display layer membership back on the USD side - layerObjs = cmds.editDisplayLayerMembers('layer2', query=True, **self.kwArgsEditDisplayLayerMembers) - self.assertTrue('|stage1|stageShape1,/A' in layerObjs) + (_, + _, _, aUsdUfePathStr, _, _, + _, _, bUsdUfePathStr, _, _) = createSimpleXformScene() + + def editAsMaya(usdUfePathStr): + with mayaUsd.lib.OpUndoItemList(): + self.assertTrue(mayaUsd.lib.PrimUpdaterManager.canEditAsMaya(usdUfePathStr)) + self.assertTrue(mayaUsd.lib.PrimUpdaterManager.editAsMaya(usdUfePathStr)) + aMayaItem = ufe.GlobalSelection.get().front() + aMayaPath = aMayaItem.path() + return ufe.PathString.string(aMayaPath) + + def mergeToUsd(mayaPathStr): + with mayaUsd.lib.OpUndoItemList(): + self.assertTrue(mayaUsd.lib.PrimUpdaterManager.mergeToUsd(mayaPathStr)) + + def duplicateToUsd(mayaPathStr, usdUfePathStr): + with mayaUsd.lib.OpUndoItemList(): + mayaUsd.lib.PrimUpdaterManager.duplicate(mayaPathStr, usdUfePathStr) + + def verifyInDisplayLayers(layerNameAndMembers): + # Verify they are in layer. + for name, members in layerNameAndMembers.items(): + # Verify they are in layer. + layerObjs = cmds.editDisplayLayerMembers(name, query=True, **self.kwArgsEditDisplayLayerMembers) + for member in members: + print(member) + self.assertTrue(member in layerObjs) + + def createDisplayLayers(layerNameAndMembers): + for name, members in layerNameAndMembers.items(): + cmds.createDisplayLayer(name=name, number=1, empty=True) + cmds.editDisplayLayerMembers(name, members, noRecurse=True) + verifyInDisplayLayers(layerNameAndMembers) + + # Verify that displayLayers survive editing the stage's root. + createDisplayLayers({"lyrA": [aUsdUfePathStr], "lyrB": [bUsdUfePathStr]}) + aMayaPathStr = editAsMaya(aUsdUfePathStr) + verifyInDisplayLayers({"lyrA": [aMayaPathStr], "lyrB": [aMayaPathStr + "|B"]}) + + # Verify that displayLayers survive merging to USD root. + createDisplayLayers({"lyrA2": [aMayaPathStr], "lyrB2": [aMayaPathStr + "|B"]}) + mergeToUsd((aMayaPathStr)) + verifyInDisplayLayers({"lyrA2": [aUsdUfePathStr], "lyrB2": [bUsdUfePathStr]}) + + # Verify that displayLayers survive editing non-root prim. + createDisplayLayers({"lyrB3": [bUsdUfePathStr]}) + bMayaPathStr = editAsMaya(bUsdUfePathStr) + verifyInDisplayLayers({"lyrB3": [bMayaPathStr]}) + + # Verify that displayLayers survive merging to non-root prim. + createDisplayLayers({"lyrB4": [bMayaPathStr]}) + mergeToUsd((bMayaPathStr)) + verifyInDisplayLayers({"lyrB4": [bUsdUfePathStr]}) + + # Verify that displayLayers survive duplicating to non-root prim. + cubeName = cmds.polyCube()[0] + cubeMayaPathStr = cmds.ls(cubeName, long=True)[0] + + createDisplayLayers({"lyrC": [cubeMayaPathStr]}) + duplicateToUsd(cubeMayaPathStr, bUsdUfePathStr) + verifyInDisplayLayers({"lyrC": [cubeMayaPathStr, bUsdUfePathStr + "/" + cubeName]}) @unittest.skipUnless(mayaUtils.ufeSupportFixLevel() >= 3, "Requires Display Layer Ufe subtree invalidate fix.") def testDisplayLayerSubtreeInvalidate(self): From c1b7602a197b6ad90f2ff259bf1cefe4a8083385 Mon Sep 17 00:00:00 2001 From: Julien Frantz Date: Thu, 6 Jun 2024 19:45:38 +0200 Subject: [PATCH 3/3] PrimUpdaterManager - Avoid unneeded SdfPath manipulations. --- lib/mayaUsd/fileio/primUpdaterManager.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/mayaUsd/fileio/primUpdaterManager.cpp b/lib/mayaUsd/fileio/primUpdaterManager.cpp index 8795e5ea09..95616bad28 100644 --- a/lib/mayaUsd/fileio/primUpdaterManager.cpp +++ b/lib/mayaUsd/fileio/primUpdaterManager.cpp @@ -627,9 +627,15 @@ void processPushExtras( const SdfPath& srcRootPath, const SdfPath& dstRootPath) { - for (const auto& srcPaths : srcDagPathMap) { - const auto dstPrimPath = srcPaths.first.ReplacePrefix(srcRootPath, dstRootPath); - pushExtras.processItem(srcPaths.second, dstPrimPath); + if (srcRootPath == dstRootPath) { + for (const auto& srcPaths : srcDagPathMap) { + pushExtras.processItem(srcPaths.second, srcPaths.first); + } + } else { + for (const auto& srcPaths : srcDagPathMap) { + const auto dstPrimPath = srcPaths.first.ReplacePrefix(srcRootPath, dstRootPath); + pushExtras.processItem(srcPaths.second, dstPrimPath); + } } }