Skip to content

Commit

Permalink
Merge pull request #3936 from Autodesk/barbalt/EMSUSD-1555/chaser-reg…
Browse files Browse the repository at this point in the history
…ister-prim-duplicate

EMSUSD-1555 Duplicating a Physical Sky to USD using Arnold options is missing data
  • Loading branch information
seando-adsk authored Sep 30, 2024
2 parents 70f3744 + c0c428d commit 602a22e
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 22 deletions.
10 changes: 10 additions & 0 deletions lib/mayaUsd/fileio/chaser/exportChaser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,14 @@ bool UsdMayaExportChaser::PostExport()
return true;
}

void UsdMayaExportChaser::RegisterExtraPrimsPaths(const std::vector<SdfPath>& extraPrimPaths)
{
_extraPrimsPaths.insert(_extraPrimsPaths.end(), extraPrimPaths.begin(), extraPrimPaths.end());
}

const std::vector<SdfPath>& UsdMayaExportChaser::GetExtraPrimsPaths() const
{
return _extraPrimsPaths;
}

PXR_NAMESPACE_CLOSE_SCOPE
15 changes: 15 additions & 0 deletions lib/mayaUsd/fileio/chaser/exportChaser.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <pxr/base/tf/declarePtrs.h>
#include <pxr/base/tf/refPtr.h>
#include <pxr/pxr.h>
#include <pxr/usd/sdf/path.h>
#include <pxr/usd/usd/timeCode.h>

PXR_NAMESPACE_OPEN_SCOPE
Expand Down Expand Up @@ -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<SdfPath>& 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<SdfPath>& GetExtraPrimsPaths() const;

private:
std::vector<SdfPath> _extraPrimsPaths;
};

PXR_NAMESPACE_CLOSE_SCOPE
Expand Down
5 changes: 4 additions & 1 deletion lib/mayaUsd/fileio/jobs/jobArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -847,7 +848,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;
Expand Down Expand Up @@ -1131,6 +1132,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetDefaultDictionary()
d[UsdMayaJobExportArgsTokens->filterTypes] = std::vector<VtValue>();
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();
Expand Down Expand Up @@ -1236,6 +1238,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;
Expand Down
2 changes: 2 additions & 0 deletions lib/mayaUsd/fileio/jobs/jobArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ TF_DECLARE_PUBLIC_TOKENS(
(filterTypes) \
(ignoreWarnings) \
(includeEmptyTransforms) \
(isDuplicating) \
(kind) \
(disableModelKindProcessor) \
(materialCollectionsPath) \
Expand Down Expand Up @@ -243,6 +244,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
Expand Down
15 changes: 9 additions & 6 deletions lib/mayaUsd/fileio/jobs/writeJob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include <pxr/usd/ar/resolver.h>
#include <pxr/usd/kind/registry.h>
#include <pxr/usd/sdf/layer.h>
#include <pxr/usd/sdf/primSpec.h>

#include <maya/MAnimControl.h>
#include <maya/MComputation.h>
Expand All @@ -35,13 +34,11 @@
#include <maya/MGlobal.h>
#include <maya/MItDag.h>
#include <maya/MObjectArray.h>
#include <maya/MPxNode.h>
#include <maya/MStatus.h>
#include <maya/MUuid.h>

#include <limits>
#include <map>
#include <unordered_set>
// Needed for directly removing a UsdVariant via Sdf
// Remove when UsdVariantSet::RemoveVariant() is exposed
// XXX [bug 75864]
Expand All @@ -50,7 +47,6 @@
#include <mayaUsd/fileio/jobs/jobArgs.h>
#include <mayaUsd/fileio/jobs/modelKindProcessor.h>
#include <mayaUsd/fileio/primWriter.h>
#include <mayaUsd/fileio/primWriterRegistry.h>
#include <mayaUsd/fileio/shading/shadingModeExporterContext.h>
#include <mayaUsd/fileio/transformWriter.h>
#include <mayaUsd/fileio/translators/translatorMaterial.h>
Expand All @@ -59,11 +55,9 @@
#include <mayaUsd/utils/util.h>

#include <pxr/usd/sdf/variantSetSpec.h>
#include <pxr/usd/sdf/variantSpec.h>
#include <pxr/usd/usd/editContext.h>
#include <pxr/usd/usd/modelAPI.h>
#include <pxr/usd/usd/primRange.h>
#include <pxr/usd/usd/usdcFileFormat.h>
#include <pxr/usd/usd/variantSets.h>
#include <pxr/usd/usdGeom/metrics.h>
#include <pxr/usd/usdGeom/xform.h>
Expand Down Expand Up @@ -702,12 +696,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();
}

Expand Down
7 changes: 7 additions & 0 deletions lib/mayaUsd/fileio/jobs/writeJob.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ class UsdMaya_WriteJob
MAYAUSD_CORE_PUBLIC
const std::vector<SdfPath>& GetMaterialPaths() { return mJobCtx.GetMaterialPaths(); }

// Cached prims paths from chasers
MAYAUSD_CORE_PUBLIC
const std::vector<SdfPath>& 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.
Expand Down Expand Up @@ -103,6 +107,9 @@ class UsdMaya_WriteJob

UsdMayaUtil::MDagPathMap<SdfPath> mDagPathToUsdPathMap;

// Array to track any extra prims created chasers
std::vector<SdfPath> _extrasPrimsPaths;

// Currently only used if stripNamespaces is on, to ensure we don't have clashes
TfHashMap<SdfPath, MDagPath, SdfPath::Hash> mUsdPathToDagPathMap;

Expand Down
21 changes: 11 additions & 10 deletions lib/mayaUsd/fileio/primUpdaterManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "primUpdaterManager.h"

#include <mayaUsd/base/tokens.h>
#include <mayaUsd/fileio/fallbackPrimUpdater.h>
#include <mayaUsd/fileio/importData.h>
#include <mayaUsd/fileio/jobs/jobArgs.h>
#include <mayaUsd/fileio/jobs/readJob.h>
Expand All @@ -38,7 +37,6 @@
#include <mayaUsd/utils/traverseLayer.h>
#include <mayaUsd/utils/trieVisitor.h>

#include <usdUfe/ufe/UsdSceneItem.h>
#include <usdUfe/ufe/Utils.h>
#include <usdUfe/undo/UsdUndoBlock.h>

Expand Down Expand Up @@ -520,6 +518,7 @@ struct PushExportResult
SdfLayerRefPtr layer;
std::shared_ptr<UsdPathToDagPathMap> usdToDag;
std::vector<SdfPath> materialPaths;
std::vector<SdfPath> extraPrimsPaths;
};

PushExportResult pushExport(const MObject& mayaObject, const UsdMayaPrimUpdaterContext& context)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1663,6 +1663,7 @@ std::vector<Ufe::Path> 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();
Expand Down Expand Up @@ -1714,15 +1715,15 @@ std::vector<Ufe::Path> PrimUpdaterManager::duplicateToUsd(
options.progressBar = &progressBar;
options.mergeScopes = true;

std::vector<SdfPath> 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);

Expand Down
10 changes: 10 additions & 0 deletions lib/mayaUsd/python/wrapExportChaser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/python/wrapPrimWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ void wrapJobExportArgs()
&UsdMayaJobExportArgs::geomSidedness, return_value_policy<return_by_value>()))
.def_readonly("ignoreWarnings", &UsdMayaJobExportArgs::ignoreWarnings)
.def_readonly("includeEmptyTransforms", &UsdMayaJobExportArgs::includeEmptyTransforms)
.def_readonly("isDuplicating", &UsdMayaJobExportArgs::isDuplicating)
.add_property(
"includeAPINames",
make_getter(
Expand Down
49 changes: 44 additions & 5 deletions test/lib/mayaUsd/fileio/testExportChaserJobContext.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
from maya import standalone

import fixturesUtils, os
import mayaUtils
import mayaUsd_createStageWithNewLayer
import mayaUsdDuplicateAsUsdDataOptions

import unittest

Expand All @@ -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):
Expand All @@ -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
Expand Down Expand Up @@ -153,6 +172,7 @@ def ExportFrame(self, frame):

def PostExport(self):
ChaserExample2.postExportCalled = True

return True

@staticmethod
Expand Down Expand Up @@ -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()
Expand All @@ -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')
Expand All @@ -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)

0 comments on commit 602a22e

Please sign in to comment.