From c0c428dff7b8b8f2c35555465aff9b9401a93931 Mon Sep 17 00:00:00 2001 From: Talis Barbalho Date: Fri, 27 Sep 2024 12:54:06 -0400 Subject: [PATCH] Squashed commit of the following: commit 1327c68173a3daefc5953e0a287255fab4ab3b9d Author: Talis Barbalho Date: Fri Sep 27 12:00:38 2024 -0400 spacing commit 7797b9d9b64d0e9c4dde13122f14f2927ead5409 Author: Talis Barbalho Date: Fri Sep 27 11:55:37 2024 -0400 Fix range import commit 1733f224b094afd972677eba03e78d73bb7de08f Author: Talis Barbalho Date: Fri Sep 27 10:26:07 2024 -0400 Skip test commit 3c4a8ef1c78d0ccf3fffbb2a5ff6cb31661960a7 Author: Talis Barbalho Date: Thu Sep 26 15:50:22 2024 -0400 formatting commit d8f42ab3c2c45fb06846f974e4c9689d977a0633 Author: Talis Barbalho Date: Thu Sep 26 15:48:43 2024 -0400 Added isDuplicating export arg commit 7ba0b06075e3911cd154450ddbe648b81b6ea9d3 Author: Talis Barbalho Date: Fri Sep 20 09:20:30 2024 -0400 Revert changes to transform writer commit e736bd34cbaf50b466826400e165e270cfa9473a Author: Talis Barbalho Date: Fri Sep 20 09:12:25 2024 -0400 Copy all prims from temp stage commit 13db258cefe8437d68b5f68b890e90e1e4fca58a Author: Talis Barbalho Date: Wed Sep 18 17:39:31 2024 -0400 fix merge conflict commit b63e2c81ffaad6fd90796d20b6ecc32b10002457 Merge: a07fcca87 3e62584f7 Author: Talis Barbalho <143224172+barbalt@users.noreply.github.com> Date: Wed Sep 18 17:30:01 2024 -0400 Merge branch 'dev' into barbalt/EMSUSD-1555/Duplicate-extra-prims commit a07fcca87fc9a87a4298d0d7a6eab23163f546f7 Merge: cc7559a54 1b6471a81 Author: Talis Barbalho Date: Wed Sep 18 17:19:07 2024 -0400 Merge branch 'dev' into barbalt/EMSUSD-1555/Duplicate-extra-prims commit cc7559a544c5c1742dc406a28df05fc454042b99 Author: Talis Barbalho Date: Wed Sep 18 11:54:24 2024 -0400 Update due to failed tests commit 591c0c69969d8799a88033f23cdb3f7b76917c5a Author: Talis Barbalho Date: Wed Sep 18 09:53:47 2024 -0400 Remove double registration commit 8e73e963f81677249fa89834f4e4940c2b26b28d Author: Talis Barbalho Date: Wed Sep 18 09:03:33 2024 -0400 + test commit 23c2e49f79cd53f88405acd0cc93bfe6aa698d49 Author: Talis Barbalho Date: Tue Sep 17 16:52:59 2024 -0400 Added new chaser method to cache extra prims --- lib/mayaUsd/fileio/chaser/exportChaser.cpp | 10 ++++ lib/mayaUsd/fileio/chaser/exportChaser.h | 15 ++++++ lib/mayaUsd/fileio/jobs/jobArgs.cpp | 5 +- lib/mayaUsd/fileio/jobs/jobArgs.h | 2 + lib/mayaUsd/fileio/jobs/writeJob.cpp | 15 +++--- lib/mayaUsd/fileio/jobs/writeJob.h | 7 +++ lib/mayaUsd/fileio/primUpdaterManager.cpp | 21 ++++---- lib/mayaUsd/python/wrapExportChaser.cpp | 10 ++++ lib/mayaUsd/python/wrapPrimWriter.cpp | 1 + .../fileio/testExportChaserJobContext.py | 49 +++++++++++++++++-- 10 files changed, 113 insertions(+), 22 deletions(-) diff --git a/lib/mayaUsd/fileio/chaser/exportChaser.cpp b/lib/mayaUsd/fileio/chaser/exportChaser.cpp index 43aed4d013..4edfc38c16 100644 --- a/lib/mayaUsd/fileio/chaser/exportChaser.cpp +++ b/lib/mayaUsd/fileio/chaser/exportChaser.cpp @@ -35,4 +35,14 @@ bool UsdMayaExportChaser::PostExport() return true; } +void UsdMayaExportChaser::RegisterExtraPrimsPaths(const std::vector& extraPrimPaths) +{ + _extraPrimsPaths.insert(_extraPrimsPaths.end(), extraPrimPaths.begin(), extraPrimPaths.end()); +} + +const std::vector& UsdMayaExportChaser::GetExtraPrimsPaths() const +{ + return _extraPrimsPaths; +} + PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/mayaUsd/fileio/chaser/exportChaser.h b/lib/mayaUsd/fileio/chaser/exportChaser.h index 9a839ad96d..502212408a 100644 --- a/lib/mayaUsd/fileio/chaser/exportChaser.h +++ b/lib/mayaUsd/fileio/chaser/exportChaser.h @@ -21,6 +21,7 @@ #include #include #include +#include #include PXR_NAMESPACE_OPEN_SCOPE @@ -69,6 +70,20 @@ class UsdMayaExportChaser : public TfRefBase /// Returning false will terminate the whole export. MAYAUSD_CORE_PUBLIC virtual bool PostExport(); + + /// Optional helper method to cache the given path array in the chaser. + /// The cached array is used internally to track any extra prim created by the chasers. + /// For example: when duplicating Maya data to USD we'll internally ask the chaser for those. + MAYAUSD_CORE_PUBLIC + virtual void RegisterExtraPrimsPaths(const std::vector& extraPrimPaths); + + /// Get the array of extra prim paths set by the chaser. + /// Returns the array of cached prim paths. + MAYAUSD_CORE_PUBLIC + virtual const std::vector& GetExtraPrimsPaths() const; + +private: + std::vector _extraPrimsPaths; }; PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/mayaUsd/fileio/jobs/jobArgs.cpp b/lib/mayaUsd/fileio/jobs/jobArgs.cpp index 2c46ffd6a5..253e568c1e 100644 --- a/lib/mayaUsd/fileio/jobs/jobArgs.cpp +++ b/lib/mayaUsd/fileio/jobs/jobArgs.cpp @@ -729,6 +729,7 @@ UsdMayaJobExportArgs::UsdMayaJobExportArgs( , ignoreWarnings(extractBoolean(userArgs, UsdMayaJobExportArgsTokens->ignoreWarnings)) , includeEmptyTransforms( extractBoolean(userArgs, UsdMayaJobExportArgsTokens->includeEmptyTransforms)) + , isDuplicating(extractBoolean(userArgs, UsdMayaJobExportArgsTokens->isDuplicating)) , materialCollectionsPath( extractAbsolutePath(userArgs, UsdMayaJobExportArgsTokens->materialCollectionsPath)) , materialsScopeName(_GetMaterialsScopeName( @@ -840,7 +841,7 @@ std::ostream& operator<<(std::ostream& out, const UsdMayaJobExportArgs& exportAr << "file: " << exportArgs.file << std::endl << "ignoreWarnings: " << TfStringify(exportArgs.ignoreWarnings) << std::endl << "includeEmptyTransforms: " << TfStringify(exportArgs.includeEmptyTransforms) - << std::endl; + << "isDuplicating: " << TfStringify(exportArgs.isDuplicating) << std::endl; out << "includeAPINames (" << exportArgs.includeAPINames.size() << ")" << std::endl; for (const std::string& includeAPIName : exportArgs.includeAPINames) { out << " " << includeAPIName << std::endl; @@ -1124,6 +1125,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetDefaultDictionary() d[UsdMayaJobExportArgsTokens->filterTypes] = std::vector(); d[UsdMayaJobExportArgsTokens->ignoreWarnings] = false; d[UsdMayaJobExportArgsTokens->includeEmptyTransforms] = true; + d[UsdMayaJobExportArgsTokens->isDuplicating] = false; d[UsdMayaJobExportArgsTokens->kind] = std::string(); d[UsdMayaJobExportArgsTokens->disableModelKindProcessor] = false; d[UsdMayaJobExportArgsTokens->materialCollectionsPath] = std::string(); @@ -1228,6 +1230,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetGuideDictionary() d[UsdMayaJobExportArgsTokens->filterTypes] = _stringVector; d[UsdMayaJobExportArgsTokens->ignoreWarnings] = _boolean; d[UsdMayaJobExportArgsTokens->includeEmptyTransforms] = _boolean; + d[UsdMayaJobExportArgsTokens->isDuplicating] = _boolean; d[UsdMayaJobExportArgsTokens->kind] = _string; d[UsdMayaJobExportArgsTokens->disableModelKindProcessor] = _boolean; d[UsdMayaJobExportArgsTokens->materialCollectionsPath] = _string; diff --git a/lib/mayaUsd/fileio/jobs/jobArgs.h b/lib/mayaUsd/fileio/jobs/jobArgs.h index d7c8b24c18..852cfe2ef2 100644 --- a/lib/mayaUsd/fileio/jobs/jobArgs.h +++ b/lib/mayaUsd/fileio/jobs/jobArgs.h @@ -93,6 +93,7 @@ TF_DECLARE_PUBLIC_TOKENS( (filterTypes) \ (ignoreWarnings) \ (includeEmptyTransforms) \ + (isDuplicating) \ (kind) \ (disableModelKindProcessor) \ (materialCollectionsPath) \ @@ -232,6 +233,7 @@ struct UsdMayaJobExportArgs const std::string file; const bool ignoreWarnings; const bool includeEmptyTransforms; + const bool isDuplicating; /// If this is not empty, then a set of collections are exported on the /// prim pointed to by the path, each representing the collection of diff --git a/lib/mayaUsd/fileio/jobs/writeJob.cpp b/lib/mayaUsd/fileio/jobs/writeJob.cpp index fadd827df0..e14fbb84e5 100644 --- a/lib/mayaUsd/fileio/jobs/writeJob.cpp +++ b/lib/mayaUsd/fileio/jobs/writeJob.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -35,13 +34,11 @@ #include #include #include -#include #include #include #include #include -#include // Needed for directly removing a UsdVariant via Sdf // Remove when UsdVariantSet::RemoveVariant() is exposed // XXX [bug 75864] @@ -50,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -58,11 +54,9 @@ #include #include -#include #include #include #include -#include #include #include #include @@ -644,12 +638,21 @@ bool UsdMaya_WriteJob::_FinishWriting() primWriterLoop.loopAdvance(); } + _extrasPrimsPaths.clear(); + // Run post export function on the chasers. MayaUsd::ProgressBarLoopScope chasersLoop(mChasers.size()); for (const UsdMayaExportChaserRefPtr& chaser : mChasers) { if (!chaser->PostExport()) { return false; } + + // Collect extra prims paths from chasers + _extrasPrimsPaths.insert( + _extrasPrimsPaths.end(), + chaser->GetExtraPrimsPaths().begin(), + chaser->GetExtraPrimsPaths().end()); + chasersLoop.loopAdvance(); } diff --git a/lib/mayaUsd/fileio/jobs/writeJob.h b/lib/mayaUsd/fileio/jobs/writeJob.h index 3449d52c84..88308825f2 100644 --- a/lib/mayaUsd/fileio/jobs/writeJob.h +++ b/lib/mayaUsd/fileio/jobs/writeJob.h @@ -59,6 +59,10 @@ class UsdMaya_WriteJob MAYAUSD_CORE_PUBLIC const std::vector& GetMaterialPaths() { return mJobCtx.GetMaterialPaths(); } + // Cached prims paths from chasers + MAYAUSD_CORE_PUBLIC + const std::vector& GetExtraPrimsPaths() { return _extrasPrimsPaths; } + private: /// Begins constructing the USD stage, writing out the values at the default /// time. Returns \c true if the stage can be created successfully. @@ -102,6 +106,9 @@ class UsdMaya_WriteJob UsdMayaUtil::MDagPathMap mDagPathToUsdPathMap; + // Array to track any extra prims created chasers + std::vector _extrasPrimsPaths; + // Currently only used if stripNamespaces is on, to ensure we don't have clashes TfHashMap mUsdPathToDagPathMap; diff --git a/lib/mayaUsd/fileio/primUpdaterManager.cpp b/lib/mayaUsd/fileio/primUpdaterManager.cpp index 77d1ab2f64..38bc3cc825 100644 --- a/lib/mayaUsd/fileio/primUpdaterManager.cpp +++ b/lib/mayaUsd/fileio/primUpdaterManager.cpp @@ -16,7 +16,6 @@ #include "primUpdaterManager.h" #include -#include #include #include #include @@ -38,7 +37,6 @@ #include #include -#include #include #include @@ -520,6 +518,7 @@ struct PushExportResult SdfLayerRefPtr layer; std::shared_ptr usdToDag; std::vector materialPaths; + std::vector extraPrimsPaths; }; PushExportResult pushExport(const MObject& mayaObject, const UsdMayaPrimUpdaterContext& context) @@ -587,6 +586,7 @@ PushExportResult pushExport(const MObject& mayaObject, const UsdMayaPrimUpdaterC if (!writeJob.Write(fileName, false /* append */)) { return result; } + result.extraPrimsPaths = writeJob.GetExtraPrimsPaths(); progressBar.advance(); result.srcRootPath = writeJob.MapDagPathToSdfPath(dagPath); @@ -1663,6 +1663,7 @@ std::vector PrimUpdaterManager::duplicateToUsd( // Setting the export-selected flag will allow filtering materials so that // only materials in the prim selected to be copied will be included. ctxArgs[UsdMayaJobExportArgsTokens->exportSelected] = true; + ctxArgs[UsdMayaJobExportArgsTokens->isDuplicating] = true; const UsdStageRefPtr dstStage = dstProxyShape->getUsdStage(); const SdfLayerHandle& layer = dstStage->GetEditTarget().GetLayer(); @@ -1714,15 +1715,15 @@ std::vector PrimUpdaterManager::duplicateToUsd( options.progressBar = &progressBar; options.mergeScopes = true; + std::vector primsToCopy = { pushExportResult.srcRootPath }; + primsToCopy.reserve(primsToCopy.size() + pushExportResult.extraPrimsPaths.size()); + primsToCopy.insert( + primsToCopy.end(), + pushExportResult.extraPrimsPaths.begin(), + pushExportResult.extraPrimsPaths.end()); + CopyLayerPrimsResult copyResult = copyLayerPrims( - srcStage, - srcLayer, - srcParentPath, - dstStage, - dstLayer, - dstParentPath, - { pushExportResult.srcRootPath }, - options); + srcStage, srcLayer, srcParentPath, dstStage, dstLayer, dstParentPath, primsToCopy, options); context._pushExtras.finalize(MayaUsd::ufe::stagePath(dstStage), copyResult.renamedPaths); diff --git a/lib/mayaUsd/python/wrapExportChaser.cpp b/lib/mayaUsd/python/wrapExportChaser.cpp index 05dfc4b9ec..18430c53cb 100644 --- a/lib/mayaUsd/python/wrapExportChaser.cpp +++ b/lib/mayaUsd/python/wrapExportChaser.cpp @@ -176,6 +176,16 @@ void wrapExportChaser() .def("ExportDefault", &This::ExportDefault, &ExportChaserWrapper::default_ExportDefault) .def("ExportFrame", &This::ExportFrame, &ExportChaserWrapper::default_ExportFrame) .def("PostExport", &This::PostExport, &ExportChaserWrapper::default_PostExport) + .def( + "RegisterExtraPrimsPaths", + &This::RegisterExtraPrimsPaths, + boost::python::arg("extraPrimPaths"), + "Method to cache the path for any extra prim path created by the chaser.") + .def( + "GetExtraPrimsPaths", + &This::GetExtraPrimsPaths, + boost::python::return_internal_reference<>(), + "Get the array of the currently cached extra paths.") .def("Register", &ExportChaserWrapper::Register) .staticmethod("Register") .def("Unregister", &ExportChaserWrapper::Unregister) diff --git a/lib/mayaUsd/python/wrapPrimWriter.cpp b/lib/mayaUsd/python/wrapPrimWriter.cpp index 9a2e21f70e..df71c84a9a 100644 --- a/lib/mayaUsd/python/wrapPrimWriter.cpp +++ b/lib/mayaUsd/python/wrapPrimWriter.cpp @@ -574,6 +574,7 @@ void wrapJobExportArgs() &UsdMayaJobExportArgs::geomSidedness, return_value_policy())) .def_readonly("ignoreWarnings", &UsdMayaJobExportArgs::ignoreWarnings) .def_readonly("includeEmptyTransforms", &UsdMayaJobExportArgs::includeEmptyTransforms) + .def_readonly("isDuplicating", &UsdMayaJobExportArgs::isDuplicating) .add_property( "includeAPINames", make_getter( diff --git a/test/lib/mayaUsd/fileio/testExportChaserJobContext.py b/test/lib/mayaUsd/fileio/testExportChaserJobContext.py index 27649f8bda..233779a3e3 100644 --- a/test/lib/mayaUsd/fileio/testExportChaserJobContext.py +++ b/test/lib/mayaUsd/fileio/testExportChaserJobContext.py @@ -23,6 +23,9 @@ from maya import standalone import fixturesUtils, os +import mayaUtils +import mayaUsd_createStageWithNewLayer +import mayaUsdDuplicateAsUsdDataOptions import unittest @@ -47,15 +50,25 @@ class ChaserExample1(mayaUsd.lib.ExportChaser): seenChasers = None seenChaserArgs = None + isDuplicating = False + def __init__(self, factoryContext, *args, **kwargs): super(ChaserExample1, self).__init__(factoryContext, *args, **kwargs) jobArgs = factoryContext.GetJobArgs() + self.stage = factoryContext.GetStage() + self.isDuplicating = factoryContext.GetJobArgs().isDuplicating ChaserExample1.seenChasers = jobArgs.chaserNames if ChaserExample1.name in jobArgs.allChaserArgs: ChaserExample1.seenChaserArgs = jobArgs.allChaserArgs[ChaserExample1.name] def ExportDefault(self): ChaserExample1.exportDefaultCalled = True + + if self.isDuplicating: + # creating an extra prim to be tested on Duplicate As + scope = self.stage.DefinePrim("/TestExportDefault", "Scope") + self.RegisterExtraPrimsPaths([scope.GetPath()]) + return self.ExportFrame(Usd.TimeCode.Default()) def ExportFrame(self, frame): @@ -64,6 +77,12 @@ def ExportFrame(self, frame): def PostExport(self): ChaserExample1.postExportCalled = True + + if self.isDuplicating: + # creating an extra prim to be tested on Duplicate As + scope = self.stage.DefinePrim("/TestPostExport", "Scope") + self.RegisterExtraPrimsPaths([scope.GetPath()]) + return True @staticmethod @@ -153,6 +172,7 @@ def ExportFrame(self, frame): def PostExport(self): ChaserExample2.postExportCalled = True + return True @staticmethod @@ -202,6 +222,11 @@ def setUpClass(cls): fixturesUtils.setUpClass(__file__) cls.temp_dir = os.path.abspath('.') + ChaserExample1.register() + ChaserExample2.register() + JobContextExample1.register() + JobContextExample2.register() + @classmethod def tearDownClass(cls): standalone.uninitialize() @@ -210,11 +235,6 @@ def setUp(self): cmds.file(new=True, force=True) def testSimpleExportChaser(self): - ChaserExample1.register() - ChaserExample2.register() - JobContextExample1.register() - JobContextExample2.register() - cmds.polySphere(r = 3.5, name='apple') usdFilePath = os.path.join(self.temp_dir,'testExportChaser.usda') @@ -241,6 +261,25 @@ def testSimpleExportChaser(self): self.assertTrue(ChaserExample2.exportFrameCalled) self.assertTrue(ChaserExample2.postExportCalled) + @unittest.skipUnless(mayaUtils.mayaMajorVersion() >= 2023, 'Requires Maya fixes only available in Maya 2023 or greater.') + def testChaserWithDuplicateAsUsd(self): + sphere = cmds.polySphere(r = 1, name='TestSphere') + + # Create a stage to receive the USD duplicate. + psPathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer() + defaultDuplicateAsUsdDataOptions = mayaUsdDuplicateAsUsdDataOptions.getDuplicateAsUsdDataOptionsText() + modifiedDuplicateAsUsdDataOptions = defaultDuplicateAsUsdDataOptions + ";jobContext=[JobContextExample1]" + cmds.mayaUsdDuplicate(cmds.ls(sphere, long=True)[0], psPathStr, exportOptions=modifiedDuplicateAsUsdDataOptions) + + # Check if the extra prims have also been duplicated + stage = mayaUsd.lib.GetPrim(psPathStr).GetStage() + spherePrim = stage.GetPrimAtPath("/TestSphere") + scopeExportPrim = stage.GetPrimAtPath("/TestExportDefault") + scopePostPrim = stage.GetPrimAtPath("/TestPostExport") + + self.assertTrue(spherePrim.IsValid()) + self.assertTrue(scopeExportPrim.IsValid()) + self.assertTrue(scopePostPrim.IsValid()) if __name__ == '__main__': unittest.main(verbosity=2)