From ae65adc1a097885062aec4ebf769378288d1ff93 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Thu, 22 Jun 2023 23:19:50 -0400 Subject: [PATCH 01/12] Add CanImport function for prim writers --- lib/mayaUsd/fileio/primWriter.h | 18 ++++++++++++++++++ lib/mayaUsd/fileio/shaderWriter.h | 13 ------------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/mayaUsd/fileio/primWriter.h b/lib/mayaUsd/fileio/primWriter.h index 02e0d3eca0..0b155edb78 100644 --- a/lib/mayaUsd/fileio/primWriter.h +++ b/lib/mayaUsd/fileio/primWriter.h @@ -61,6 +61,24 @@ class UsdMayaPrimWriter const SdfPath& usdPath, UsdMayaWriteJobContext& jobCtx); + /// The level of support a writer can offer for a given context + /// + /// A basic writer that gives correct results across most contexts should + /// report `Fallback`, while a specialized writer that really shines in a + /// given context should report `Supported` when the context is right and + /// `Unsupported` if the context is not as expected. + enum class ContextSupport + { + Supported, + Fallback, + Unsupported + }; + + /// A static function is expected for all writers and allows + /// declaring how well this class can support the current context. + MAYAUSD_CORE_PUBLIC + static ContextSupport CanImport(const UsdMayaJobExportArgs& emportArgs); + MAYAUSD_CORE_PUBLIC virtual ~UsdMayaPrimWriter(); diff --git a/lib/mayaUsd/fileio/shaderWriter.h b/lib/mayaUsd/fileio/shaderWriter.h index 0f4d8a75a6..b20635584a 100644 --- a/lib/mayaUsd/fileio/shaderWriter.h +++ b/lib/mayaUsd/fileio/shaderWriter.h @@ -43,19 +43,6 @@ class UsdMayaShaderWriter : public UsdMayaPrimWriter const SdfPath& usdPath, UsdMayaWriteJobContext& jobCtx); - /// The level of support a writer can offer for a given context - /// - /// A basic writer that gives correct results across most contexts should - /// report `Fallback`, while a specialized writer that really shines in a - /// given context should report `Supported` when the context is right and - /// `Unsupported` if the context is not as expected. - enum class ContextSupport - { - Supported, - Fallback, - Unsupported - }; - /// A static function is expected for all shader writers and allows /// declaring how well this class can support the current context. /// From d6b7d8a7eb71b780ba1b6985a0712dd5d3923905 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Wed, 28 Jun 2023 17:34:56 -0400 Subject: [PATCH 02/12] Update primwriter functions to add ContextSupport --- lib/mayaUsd/fileio/primWriter.h | 2 +- lib/mayaUsd/fileio/primWriterRegistry.cpp | 137 ++++++++++++++++++---- lib/mayaUsd/fileio/primWriterRegistry.h | 34 +++++- lib/mayaUsd/fileio/utils/adaptor.cpp | 7 +- lib/mayaUsd/fileio/writeJobContext.cpp | 2 +- 5 files changed, 154 insertions(+), 28 deletions(-) diff --git a/lib/mayaUsd/fileio/primWriter.h b/lib/mayaUsd/fileio/primWriter.h index 0b155edb78..9e7c45ad42 100644 --- a/lib/mayaUsd/fileio/primWriter.h +++ b/lib/mayaUsd/fileio/primWriter.h @@ -77,7 +77,7 @@ class UsdMayaPrimWriter /// A static function is expected for all writers and allows /// declaring how well this class can support the current context. MAYAUSD_CORE_PUBLIC - static ContextSupport CanImport(const UsdMayaJobExportArgs& emportArgs); + static ContextSupport CanImport(const UsdMayaJobExportArgs& exportArgs); MAYAUSD_CORE_PUBLIC virtual ~UsdMayaPrimWriter(); diff --git a/lib/mayaUsd/fileio/primWriterRegistry.cpp b/lib/mayaUsd/fileio/primWriterRegistry.cpp index 9bd094940c..46d48e030c 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.cpp +++ b/lib/mayaUsd/fileio/primWriterRegistry.cpp @@ -42,9 +42,73 @@ TF_DEFINE_PRIVATE_TOKENS( ); // clang-format on -typedef std::map _Registry; -static _Registry _reg; +namespace { +struct _RegistryEntry +{ + UsdMayaPrimWriterRegistry::ContextPredicateFn _pred; + UsdMayaPrimWriterRegistry::WriterFactoryFn _writer; + int _index; +}; + +// typedef std::map _Registry; +typedef std::unordered_multimap _Registry; +static _Registry _reg; static std::set _mayaTypesThatDoNotCreatePrims; +static int _indexCounter = 0; + +_Registry::const_iterator +_Find(const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs) +{ + using ContextSupport = UsdMayaPrimWriter::ContextSupport; + + _Registry::const_iterator ret = _reg.cend(); + _Registry::const_iterator first, last; + std::tie(first, last) = _reg.equal_range(mayaTypeName); + while (first != last) { + ContextSupport support = first->second._pred(exportArgs); + // Look for a "Supported" reader. If no "Supported" reader is found, use a "Fallback" reader + if (support == ContextSupport::Supported) { + ret = first; + break; + } else if (support == ContextSupport::Fallback && ret == _reg.end()) { + ret = first; + } + ++first; + } + + return ret; +} + +} // namespace + +/* static */ +void UsdMayaPrimWriterRegistry::Register( + const std::string& mayaTypeName, + UsdMayaPrimWriterRegistry::ContextPredicateFn pred, + UsdMayaPrimWriterRegistry::WriterFactoryFn fn, + bool fromPython) +{ + TF_DEBUG(PXRUSDMAYA_REGISTRY) + .Msg("Registering UsdMayaPrimWriter for maya type %s.\n", mayaTypeName.c_str()); + + int index = _indexCounter++; + _reg.insert(std::make_pair(mayaTypeName, _RegistryEntry { pred, fn, index })); + + // The unloader uses the index to know which entry to erase when there are + // more than one for the same mayaTypeName. + UsdMaya_RegistryHelper::AddUnloader( + [mayaTypeName, index]() { + _Registry::const_iterator it, itEnd; + std::tie(it, itEnd) = _reg.equal_range(mayaTypeName); + for (; it != itEnd; ++it) { + if (it->second._index == index) { + _reg.erase(it); + break; + } + } + }, + fromPython); +} /* static */ void UsdMayaPrimWriterRegistry::Register( @@ -55,14 +119,30 @@ void UsdMayaPrimWriterRegistry::Register( TF_DEBUG(PXRUSDMAYA_REGISTRY) .Msg("Registering UsdMayaPrimWriter for maya type %s.\n", mayaTypeName.c_str()); - std::pair<_Registry::iterator, bool> insertStatus - = _reg.insert(std::make_pair(mayaTypeName, fn)); - if (insertStatus.second) { - UsdMaya_RegistryHelper::AddUnloader( - [mayaTypeName]() { _reg.erase(mayaTypeName); }, fromPython); - } else { - TF_CODING_ERROR("Multiple writers for type %s", mayaTypeName.c_str()); - } + int index = _indexCounter++; + + // Use default ContextSupport if not specified + _reg.insert(std::make_pair( + mayaTypeName, + _RegistryEntry { + [](const UsdMayaJobExportArgs&) { return UsdMayaPrimWriter::ContextSupport::Fallback; }, + fn, + index })); + + // The unloader uses the index to know which entry to erase when there are + // more than one for the same mayaTypeName. + UsdMaya_RegistryHelper::AddUnloader( + [mayaTypeName, index]() { + _Registry::const_iterator it, itEnd; + std::tie(it, itEnd) = _reg.equal_range(mayaTypeName); + for (; it != itEnd; ++it) { + if (it->second._index == index) { + _reg.erase(it); + break; + } + } + }, + fromPython); } /* static */ @@ -74,32 +154,41 @@ void UsdMayaPrimWriterRegistry::RegisterRaw( } /* static */ -UsdMayaPrimWriterRegistry::WriterFactoryFn -UsdMayaPrimWriterRegistry::Find(const std::string& mayaTypeName) +UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( + const std::string& mayaTypeName, + const UsdMayaJobExportArgs& exportArgs) { TfRegistryManager::GetInstance().SubscribeTo(); - // unfortunately, usdTypeName is diff from the tfTypeName which we use to - // register. do the conversion here. - WriterFactoryFn ret = nullptr; - if (TfMapLookup(_reg, mayaTypeName, &ret)) { - return ret; + _Registry::const_iterator it = _Find(mayaTypeName, exportArgs); + + if (it != _reg.end()) { + return it->second._writer; } static const TfTokenVector SCOPE = { _tokens->UsdMaya, _tokens->PrimWriter }; UsdMaya_RegistryHelper::FindAndLoadMayaPlug(SCOPE, mayaTypeName); + it = _Find(mayaTypeName, exportArgs); + + if (it != _reg.end()) { + return it->second._writer; + } + // ideally something just registered itself. if not, we at least put it in // the registry in case we encounter it again. - if (!TfMapLookup(_reg, mayaTypeName, &ret)) { - TF_DEBUG(PXRUSDMAYA_REGISTRY) - .Msg( - "No usdMaya writer plugin for maya type %s. No maya plugin found.\n", - mayaTypeName.c_str()); - _reg[mayaTypeName] = nullptr; + if (_reg.count(mayaTypeName) == 0) { + // Nothing registered at all, remember that: + _reg.insert(std::make_pair( + mayaTypeName, + _RegistryEntry { [](const UsdMayaJobExportArgs&) { + return UsdMayaPrimWriter::ContextSupport::Fallback; + }, + nullptr, + -1 })); } - return ret; + return nullptr; } /* static */ diff --git a/lib/mayaUsd/fileio/primWriterRegistry.h b/lib/mayaUsd/fileio/primWriterRegistry.h index 90f54fc5bf..77ae17cb8c 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.h +++ b/lib/mayaUsd/fileio/primWriterRegistry.h @@ -77,6 +77,37 @@ struct UsdMayaPrimWriterRegistry /// macro. typedef std::function WriterFn; + /// Predicate function, i.e. a function that can tell the level of support + /// the writer function will provide for a given set of export options. + using ContextPredicateFn = std::function< + UsdMayaPrimWriter::ContextSupport(const UsdMayaJobExportArgs&)>; + + // TODO: Write new brief + /// \brief Register \p fn as a factory function providing a + /// UsdMayaPrimWriter subclass that can be used to write \p mayaType. + /// If you can't provide a valid UsdMayaPrimWriter for the given arguments, + /// return a null pointer from the factory function \p fn. + /// + /// Example for registering a writer factory in your custom plugin: + /// \code{.cpp} + /// class MyWriter : public UsdMayaPrimWriter { + /// static UsdMayaPrimWriterSharedPtr Create( + /// const MFnDependencyNode& depNodeFn, + /// const SdfPath& usdPath, + /// UsdMayaWriteJobContext& jobCtx); + /// }; + /// TF_REGISTRY_FUNCTION_WITH_TAG(UsdMayaPrimWriterRegistry, MyWriter) { + /// UsdMayaPrimWriterRegistry::Register("myCustomMayaNode", + /// MyWriter::Create); + /// } + /// \endcode + MAYAUSD_CORE_PUBLIC + static void Register( + const std::string& mayaType, + ContextPredicateFn pred, + WriterFactoryFn fn, + bool fromPython = false); + /// \brief Register \p fn as a factory function providing a /// UsdMayaPrimWriter subclass that can be used to write \p mayaType. /// If you can't provide a valid UsdMayaPrimWriter for the given arguments, @@ -109,7 +140,8 @@ struct UsdMayaPrimWriterRegistry /// /// If there is no writer plugin for \p mayaTypeName, returns nullptr. MAYAUSD_CORE_PUBLIC - static WriterFactoryFn Find(const std::string& mayaTypeName); + static WriterFactoryFn + Find(const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs); /// \brief Registers a maya node type to *not* create a new prim. /// diff --git a/lib/mayaUsd/fileio/utils/adaptor.cpp b/lib/mayaUsd/fileio/utils/adaptor.cpp index c68c9aa1db..22d22c0f0c 100644 --- a/lib/mayaUsd/fileio/utils/adaptor.cpp +++ b/lib/mayaUsd/fileio/utils/adaptor.cpp @@ -158,7 +158,12 @@ TfType UsdMayaAdaptor::GetUsdType() const // The adaptor type mapping might be registered externally in a prim writer // plugin. This simply pokes the prim writer registry to load the prim // writer plugin in order to pull in the adaptor mapping. - UsdMayaPrimWriterRegistry::Find(depNode.typeName().asChar()); + if (!_jobExportArgs) { + TF_CODING_ERROR("ExportArgs shouldn't be Null."); + return TfType(); + } + + UsdMayaPrimWriterRegistry::Find(depNode.typeName().asChar(), *_jobExportArgs); TfRegistryManager::GetInstance().SubscribeTo(); const auto iter = _schemaLookup.find(depNode.typeName().asChar()); diff --git a/lib/mayaUsd/fileio/writeJobContext.cpp b/lib/mayaUsd/fileio/writeJobContext.cpp index 626b6feda5..2c17538995 100644 --- a/lib/mayaUsd/fileio/writeJobContext.cpp +++ b/lib/mayaUsd/fileio/writeJobContext.cpp @@ -564,7 +564,7 @@ UsdMayaWriteJobContext::_FindWriter(const std::string& mayaNodeType) = UsdMayaUtil::GetAllAncestorMayaNodeTypes(mayaNodeType); for (auto i = ancestorTypes.rbegin(); i != ancestorTypes.rend(); ++i) { if (UsdMayaPrimWriterRegistry::WriterFactoryFn primWriterFactory - = UsdMayaPrimWriterRegistry::Find(*i)) { + = UsdMayaPrimWriterRegistry::Find(*i, mArgs)) { mWriterFactoryCache[mayaNodeType] = primWriterFactory; return primWriterFactory; } From fa18274637b5a1095e2726252c3f201d5205da71 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Thu, 29 Jun 2023 16:06:31 -0400 Subject: [PATCH 03/12] Add poke function to primWriterRegistry for loading writer plugin --- lib/mayaUsd/fileio/primWriterRegistry.cpp | 17 ++++++++++++++++- lib/mayaUsd/fileio/primWriterRegistry.h | 12 +++++++++--- lib/mayaUsd/fileio/utils/adaptor.cpp | 7 +------ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lib/mayaUsd/fileio/primWriterRegistry.cpp b/lib/mayaUsd/fileio/primWriterRegistry.cpp index 46d48e030c..3d0354ec45 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.cpp +++ b/lib/mayaUsd/fileio/primWriterRegistry.cpp @@ -53,7 +53,7 @@ struct _RegistryEntry // typedef std::map _Registry; typedef std::unordered_multimap _Registry; static _Registry _reg; -static std::set _mayaTypesThatDoNotCreatePrims; +static std::set _mayaTypesThatDoNotCreatePrims; static int _indexCounter = 0; _Registry::const_iterator @@ -191,6 +191,21 @@ UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( return nullptr; } +/* static */ +void UsdMayaPrimWriterRegistry::Poke(const std::string& mayaTypeName) +{ + TfRegistryManager::GetInstance().SubscribeTo(); + + _Registry::const_iterator first, last; + std::tie(first, last) = _reg.equal_range(mayaTypeName); + + if (first == last) { + // If the type name is not currently in our registry, check for plugin registry + static const TfTokenVector SCOPE = { _tokens->UsdMaya, _tokens->PrimWriter }; + UsdMaya_RegistryHelper::FindAndLoadMayaPlug(SCOPE, mayaTypeName); + } +} + /* static */ void UsdMayaPrimWriterRegistry::RegisterPrimless(const std::string& mayaTypeName) { diff --git a/lib/mayaUsd/fileio/primWriterRegistry.h b/lib/mayaUsd/fileio/primWriterRegistry.h index 77ae17cb8c..a3c6580052 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.h +++ b/lib/mayaUsd/fileio/primWriterRegistry.h @@ -79,12 +79,14 @@ struct UsdMayaPrimWriterRegistry /// Predicate function, i.e. a function that can tell the level of support /// the writer function will provide for a given set of export options. - using ContextPredicateFn = std::function< - UsdMayaPrimWriter::ContextSupport(const UsdMayaJobExportArgs&)>; + using ContextPredicateFn + = std::function; - // TODO: Write new brief /// \brief Register \p fn as a factory function providing a /// UsdMayaPrimWriter subclass that can be used to write \p mayaType. + /// Provide a supportability of the primWriter. Use "supported" to + /// override the default primWriter + /// /// If you can't provide a valid UsdMayaPrimWriter for the given arguments, /// return a null pointer from the factory function \p fn. /// @@ -143,6 +145,10 @@ struct UsdMayaPrimWriterRegistry static WriterFactoryFn Find(const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs); + /// \brief Check for external primWriter for \p mayaTypeName. + MAYAUSD_CORE_PUBLIC + static void Poke(const std::string& mayaTypeName); + /// \brief Registers a maya node type to *not* create a new prim. /// /// This is relevant for Maya nodes that may not result in a new prim in diff --git a/lib/mayaUsd/fileio/utils/adaptor.cpp b/lib/mayaUsd/fileio/utils/adaptor.cpp index 22d22c0f0c..3f8dcefa4c 100644 --- a/lib/mayaUsd/fileio/utils/adaptor.cpp +++ b/lib/mayaUsd/fileio/utils/adaptor.cpp @@ -158,12 +158,7 @@ TfType UsdMayaAdaptor::GetUsdType() const // The adaptor type mapping might be registered externally in a prim writer // plugin. This simply pokes the prim writer registry to load the prim // writer plugin in order to pull in the adaptor mapping. - if (!_jobExportArgs) { - TF_CODING_ERROR("ExportArgs shouldn't be Null."); - return TfType(); - } - - UsdMayaPrimWriterRegistry::Find(depNode.typeName().asChar(), *_jobExportArgs); + UsdMayaPrimWriterRegistry::Poke(depNode.typeName().asChar()); TfRegistryManager::GetInstance().SubscribeTo(); const auto iter = _schemaLookup.find(depNode.typeName().asChar()); From 0ede36e5bd89d4b5bf4fc9920cce0966c77c7158 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Tue, 4 Jul 2023 12:46:25 -0400 Subject: [PATCH 04/12] Add MFnDependencyNode as an input to CanExport function so user can inspect the node --- lib/mayaUsd/fileio/primWriter.h | 3 ++- lib/mayaUsd/fileio/primWriterRegistry.cpp | 19 +++++++++++-------- lib/mayaUsd/fileio/primWriterRegistry.h | 10 ++++++---- lib/mayaUsd/fileio/writeJobContext.cpp | 9 +++++---- lib/mayaUsd/fileio/writeJobContext.h | 2 +- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/mayaUsd/fileio/primWriter.h b/lib/mayaUsd/fileio/primWriter.h index 9e7c45ad42..7ddae1b7b4 100644 --- a/lib/mayaUsd/fileio/primWriter.h +++ b/lib/mayaUsd/fileio/primWriter.h @@ -77,7 +77,8 @@ class UsdMayaPrimWriter /// A static function is expected for all writers and allows /// declaring how well this class can support the current context. MAYAUSD_CORE_PUBLIC - static ContextSupport CanImport(const UsdMayaJobExportArgs& exportArgs); + static ContextSupport + CanExport(const UsdMayaJobExportArgs& exportArgs, const MFnDependencyNode& exportNode); MAYAUSD_CORE_PUBLIC virtual ~UsdMayaPrimWriter(); diff --git a/lib/mayaUsd/fileio/primWriterRegistry.cpp b/lib/mayaUsd/fileio/primWriterRegistry.cpp index 3d0354ec45..7c01917e20 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.cpp +++ b/lib/mayaUsd/fileio/primWriterRegistry.cpp @@ -56,8 +56,10 @@ static _Registry _reg; static std::set _mayaTypesThatDoNotCreatePrims; static int _indexCounter = 0; -_Registry::const_iterator -_Find(const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs) +_Registry::const_iterator _Find( + const std::string& mayaTypeName, + const UsdMayaJobExportArgs& exportArgs, + const MFnDependencyNode& exportNode) { using ContextSupport = UsdMayaPrimWriter::ContextSupport; @@ -65,7 +67,7 @@ _Find(const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs) _Registry::const_iterator first, last; std::tie(first, last) = _reg.equal_range(mayaTypeName); while (first != last) { - ContextSupport support = first->second._pred(exportArgs); + ContextSupport support = first->second._pred(exportArgs, exportNode); // Look for a "Supported" reader. If no "Supported" reader is found, use a "Fallback" reader if (support == ContextSupport::Supported) { ret = first; @@ -125,7 +127,7 @@ void UsdMayaPrimWriterRegistry::Register( _reg.insert(std::make_pair( mayaTypeName, _RegistryEntry { - [](const UsdMayaJobExportArgs&) { return UsdMayaPrimWriter::ContextSupport::Fallback; }, + [](const UsdMayaJobExportArgs&, const MFnDependencyNode&) { return UsdMayaPrimWriter::ContextSupport::Fallback; }, fn, index })); @@ -156,11 +158,12 @@ void UsdMayaPrimWriterRegistry::RegisterRaw( /* static */ UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( const std::string& mayaTypeName, - const UsdMayaJobExportArgs& exportArgs) + const UsdMayaJobExportArgs& exportArgs, + const MFnDependencyNode& exportNode) { TfRegistryManager::GetInstance().SubscribeTo(); - _Registry::const_iterator it = _Find(mayaTypeName, exportArgs); + _Registry::const_iterator it = _Find(mayaTypeName, exportArgs, exportNode); if (it != _reg.end()) { return it->second._writer; @@ -169,7 +172,7 @@ UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( static const TfTokenVector SCOPE = { _tokens->UsdMaya, _tokens->PrimWriter }; UsdMaya_RegistryHelper::FindAndLoadMayaPlug(SCOPE, mayaTypeName); - it = _Find(mayaTypeName, exportArgs); + it = _Find(mayaTypeName, exportArgs, exportNode); if (it != _reg.end()) { return it->second._writer; @@ -181,7 +184,7 @@ UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( // Nothing registered at all, remember that: _reg.insert(std::make_pair( mayaTypeName, - _RegistryEntry { [](const UsdMayaJobExportArgs&) { + _RegistryEntry { [](const UsdMayaJobExportArgs&, const MFnDependencyNode&) { return UsdMayaPrimWriter::ContextSupport::Fallback; }, nullptr, diff --git a/lib/mayaUsd/fileio/primWriterRegistry.h b/lib/mayaUsd/fileio/primWriterRegistry.h index a3c6580052..1433dfdc13 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.h +++ b/lib/mayaUsd/fileio/primWriterRegistry.h @@ -79,8 +79,8 @@ struct UsdMayaPrimWriterRegistry /// Predicate function, i.e. a function that can tell the level of support /// the writer function will provide for a given set of export options. - using ContextPredicateFn - = std::function; + using ContextPredicateFn = std::function< + UsdMayaPrimWriter::ContextSupport(const UsdMayaJobExportArgs&, const MFnDependencyNode&)>; /// \brief Register \p fn as a factory function providing a /// UsdMayaPrimWriter subclass that can be used to write \p mayaType. @@ -142,8 +142,10 @@ struct UsdMayaPrimWriterRegistry /// /// If there is no writer plugin for \p mayaTypeName, returns nullptr. MAYAUSD_CORE_PUBLIC - static WriterFactoryFn - Find(const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs); + static WriterFactoryFn Find( + const std::string& mayaTypeName, + const UsdMayaJobExportArgs& exportArgs, + const MFnDependencyNode& exportNode); /// \brief Check for external primWriter for \p mayaTypeName. MAYAUSD_CORE_PUBLIC diff --git a/lib/mayaUsd/fileio/writeJobContext.cpp b/lib/mayaUsd/fileio/writeJobContext.cpp index 2c17538995..0af72d0b92 100644 --- a/lib/mayaUsd/fileio/writeJobContext.cpp +++ b/lib/mayaUsd/fileio/writeJobContext.cpp @@ -537,8 +537,7 @@ UsdMayaPrimWriterSharedPtr UsdMayaWriteJobContext::CreatePrimWriter( // This is either a DG node or a non-instanced DAG node, so try to look up // a writer plugin. We search through the node's type ancestors, working // backwards until we find a prim writer plugin. - const std::string mayaTypeName(depNodeFn.typeName().asChar()); - if (UsdMayaPrimWriterRegistry::WriterFactoryFn primWriterFactory = _FindWriter(mayaTypeName)) { + if (UsdMayaPrimWriterRegistry::WriterFactoryFn primWriterFactory = _FindWriter(depNodeFn)) { if (UsdMayaPrimWriterSharedPtr primPtr = primWriterFactory(depNodeFn, writePath, *this)) { // We found a registered user prim writer that handles this node // type, so return now. @@ -551,8 +550,10 @@ UsdMayaPrimWriterSharedPtr UsdMayaWriteJobContext::CreatePrimWriter( } UsdMayaPrimWriterRegistry::WriterFactoryFn -UsdMayaWriteJobContext::_FindWriter(const std::string& mayaNodeType) +UsdMayaWriteJobContext::_FindWriter(const MFnDependencyNode& mayaNode) { + const std::string mayaNodeType(mayaNode.typeName().asChar()); + // Check if type is already cached locally. auto iter = mWriterFactoryCache.find(mayaNodeType); if (iter != mWriterFactoryCache.end()) { @@ -564,7 +565,7 @@ UsdMayaWriteJobContext::_FindWriter(const std::string& mayaNodeType) = UsdMayaUtil::GetAllAncestorMayaNodeTypes(mayaNodeType); for (auto i = ancestorTypes.rbegin(); i != ancestorTypes.rend(); ++i) { if (UsdMayaPrimWriterRegistry::WriterFactoryFn primWriterFactory - = UsdMayaPrimWriterRegistry::Find(*i, mArgs)) { + = UsdMayaPrimWriterRegistry::Find(*i, mArgs, mayaNode)) { mWriterFactoryCache[mayaNodeType] = primWriterFactory; return primWriterFactory; } diff --git a/lib/mayaUsd/fileio/writeJobContext.h b/lib/mayaUsd/fileio/writeJobContext.h index c125f27f45..367a1ccde0 100644 --- a/lib/mayaUsd/fileio/writeJobContext.h +++ b/lib/mayaUsd/fileio/writeJobContext.h @@ -186,7 +186,7 @@ class UsdMayaWriteJobContext std::vector::const_iterator* end) const; /// Prim writer search with ancestor type resolution behavior. - UsdMayaPrimWriterRegistry::WriterFactoryFn _FindWriter(const std::string& mayaNodeType); + UsdMayaPrimWriterRegistry::WriterFactoryFn _FindWriter(const MFnDependencyNode& mayaNode); struct MObjectHandleComp { From ac4f5e0d5a1be276b29b9d748387492781c3d5d6 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Tue, 4 Jul 2023 12:51:24 -0400 Subject: [PATCH 05/12] clang format fix --- lib/mayaUsd/fileio/primWriterRegistry.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/mayaUsd/fileio/primWriterRegistry.cpp b/lib/mayaUsd/fileio/primWriterRegistry.cpp index 7c01917e20..d9f1b34399 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.cpp +++ b/lib/mayaUsd/fileio/primWriterRegistry.cpp @@ -126,10 +126,11 @@ void UsdMayaPrimWriterRegistry::Register( // Use default ContextSupport if not specified _reg.insert(std::make_pair( mayaTypeName, - _RegistryEntry { - [](const UsdMayaJobExportArgs&, const MFnDependencyNode&) { return UsdMayaPrimWriter::ContextSupport::Fallback; }, - fn, - index })); + _RegistryEntry { [](const UsdMayaJobExportArgs&, const MFnDependencyNode&) { + return UsdMayaPrimWriter::ContextSupport::Fallback; + }, + fn, + index })); // The unloader uses the index to know which entry to erase when there are // more than one for the same mayaTypeName. From a43f3e898745c286b1441ff1cab9a04468816ed1 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Tue, 11 Jul 2023 14:32:24 -0400 Subject: [PATCH 06/12] Change CanExport function to take MObject and updated python wrapper --- lib/mayaUsd/fileio/primWriter.h | 2 +- lib/mayaUsd/fileio/primWriterRegistry.cpp | 14 ++-- lib/mayaUsd/fileio/primWriterRegistry.h | 4 +- lib/mayaUsd/fileio/shaderWriterRegistry.cpp | 4 +- lib/mayaUsd/fileio/shaderWriterRegistry.h | 2 +- .../fileio/shading/symmetricShaderWriter.cpp | 2 +- lib/mayaUsd/fileio/writeJobContext.cpp | 2 +- lib/mayaUsd/python/wrapPrimWriter.cpp | 72 +++++++++++-------- .../usdPreviewSurfaceWriter.cpp | 2 +- .../translators/shading/mtlxBaseWriter.cpp | 2 +- .../shading/mtlxSymmetricShaderWriter.cpp | 2 +- .../shading/usdDisplacementShaderWriter.cpp | 2 +- .../shading/usdFileTextureWriter.cpp | 2 +- .../translators/shading/usdMaterialWriter.cpp | 2 +- 14 files changed, 65 insertions(+), 49 deletions(-) diff --git a/lib/mayaUsd/fileio/primWriter.h b/lib/mayaUsd/fileio/primWriter.h index 7ddae1b7b4..95f266d145 100644 --- a/lib/mayaUsd/fileio/primWriter.h +++ b/lib/mayaUsd/fileio/primWriter.h @@ -78,7 +78,7 @@ class UsdMayaPrimWriter /// declaring how well this class can support the current context. MAYAUSD_CORE_PUBLIC static ContextSupport - CanExport(const UsdMayaJobExportArgs& exportArgs, const MFnDependencyNode& exportNode); + CanExport(const UsdMayaJobExportArgs& exportArgs, const MObject& exportObj); MAYAUSD_CORE_PUBLIC virtual ~UsdMayaPrimWriter(); diff --git a/lib/mayaUsd/fileio/primWriterRegistry.cpp b/lib/mayaUsd/fileio/primWriterRegistry.cpp index d9f1b34399..ab54a0cb4f 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.cpp +++ b/lib/mayaUsd/fileio/primWriterRegistry.cpp @@ -59,7 +59,7 @@ static int _indexCounter = 0; _Registry::const_iterator _Find( const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs, - const MFnDependencyNode& exportNode) + const MObject& exportObj) { using ContextSupport = UsdMayaPrimWriter::ContextSupport; @@ -67,7 +67,7 @@ _Registry::const_iterator _Find( _Registry::const_iterator first, last; std::tie(first, last) = _reg.equal_range(mayaTypeName); while (first != last) { - ContextSupport support = first->second._pred(exportArgs, exportNode); + ContextSupport support = first->second._pred(exportArgs, exportObj); // Look for a "Supported" reader. If no "Supported" reader is found, use a "Fallback" reader if (support == ContextSupport::Supported) { ret = first; @@ -126,7 +126,7 @@ void UsdMayaPrimWriterRegistry::Register( // Use default ContextSupport if not specified _reg.insert(std::make_pair( mayaTypeName, - _RegistryEntry { [](const UsdMayaJobExportArgs&, const MFnDependencyNode&) { + _RegistryEntry { [](const UsdMayaJobExportArgs&, const MObject&) { return UsdMayaPrimWriter::ContextSupport::Fallback; }, fn, @@ -160,11 +160,11 @@ void UsdMayaPrimWriterRegistry::RegisterRaw( UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs, - const MFnDependencyNode& exportNode) + const MObject& exportObj) { TfRegistryManager::GetInstance().SubscribeTo(); - _Registry::const_iterator it = _Find(mayaTypeName, exportArgs, exportNode); + _Registry::const_iterator it = _Find(mayaTypeName, exportArgs, exportObj); if (it != _reg.end()) { return it->second._writer; @@ -173,7 +173,7 @@ UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( static const TfTokenVector SCOPE = { _tokens->UsdMaya, _tokens->PrimWriter }; UsdMaya_RegistryHelper::FindAndLoadMayaPlug(SCOPE, mayaTypeName); - it = _Find(mayaTypeName, exportArgs, exportNode); + it = _Find(mayaTypeName, exportArgs, exportObj); if (it != _reg.end()) { return it->second._writer; @@ -185,7 +185,7 @@ UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( // Nothing registered at all, remember that: _reg.insert(std::make_pair( mayaTypeName, - _RegistryEntry { [](const UsdMayaJobExportArgs&, const MFnDependencyNode&) { + _RegistryEntry { [](const UsdMayaJobExportArgs&, const MObject&) { return UsdMayaPrimWriter::ContextSupport::Fallback; }, nullptr, diff --git a/lib/mayaUsd/fileio/primWriterRegistry.h b/lib/mayaUsd/fileio/primWriterRegistry.h index 1433dfdc13..d9712e00ea 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.h +++ b/lib/mayaUsd/fileio/primWriterRegistry.h @@ -80,7 +80,7 @@ struct UsdMayaPrimWriterRegistry /// Predicate function, i.e. a function that can tell the level of support /// the writer function will provide for a given set of export options. using ContextPredicateFn = std::function< - UsdMayaPrimWriter::ContextSupport(const UsdMayaJobExportArgs&, const MFnDependencyNode&)>; + UsdMayaPrimWriter::ContextSupport(const UsdMayaJobExportArgs&, const MObject&)>; /// \brief Register \p fn as a factory function providing a /// UsdMayaPrimWriter subclass that can be used to write \p mayaType. @@ -145,7 +145,7 @@ struct UsdMayaPrimWriterRegistry static WriterFactoryFn Find( const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs, - const MFnDependencyNode& exportNode); + const MObject& exportObj); /// \brief Check for external primWriter for \p mayaTypeName. MAYAUSD_CORE_PUBLIC diff --git a/lib/mayaUsd/fileio/shaderWriterRegistry.cpp b/lib/mayaUsd/fileio/shaderWriterRegistry.cpp index 668fe70a3d..8a1323d828 100644 --- a/lib/mayaUsd/fileio/shaderWriterRegistry.cpp +++ b/lib/mayaUsd/fileio/shaderWriterRegistry.cpp @@ -57,7 +57,7 @@ static int _indexCounter = 0; _Registry::const_iterator _Find(const TfToken& usdInfoId, const UsdMayaJobExportArgs& exportArgs) { - using ContextSupport = UsdMayaShaderWriter::ContextSupport; + using ContextSupport = UsdMayaPrimWriter::ContextSupport; TfToken conversion = exportArgs.convertMaterialsTo; const bool noFallback @@ -141,7 +141,7 @@ UsdMayaShaderWriterRegistry::WriterFactoryFn UsdMayaShaderWriterRegistry::Find( _reg.insert(std::make_pair( mayaTypeName, _RegistryEntry { [](const UsdMayaJobExportArgs&) { - return UsdMayaShaderWriter::ContextSupport::Fallback; + return UsdMayaPrimWriter::ContextSupport::Fallback; }, nullptr, -1 })); diff --git a/lib/mayaUsd/fileio/shaderWriterRegistry.h b/lib/mayaUsd/fileio/shaderWriterRegistry.h index fe83baf312..4daf845b25 100644 --- a/lib/mayaUsd/fileio/shaderWriterRegistry.h +++ b/lib/mayaUsd/fileio/shaderWriterRegistry.h @@ -84,7 +84,7 @@ struct UsdMayaShaderWriterRegistry /// Predicate function, i.e. a function that can tell the level of support /// the writer function will provide for a given set of export options. using ContextPredicateFn - = std::function; + = std::function; /// \brief Register \p fn as a factory function providing a /// UsdMayaShaderWriter subclass that can be used to write \p mayaType. diff --git a/lib/mayaUsd/fileio/shading/symmetricShaderWriter.cpp b/lib/mayaUsd/fileio/shading/symmetricShaderWriter.cpp index 19bf5b2193..04dee81f3c 100644 --- a/lib/mayaUsd/fileio/shading/symmetricShaderWriter.cpp +++ b/lib/mayaUsd/fileio/shading/symmetricShaderWriter.cpp @@ -67,7 +67,7 @@ void UsdMayaSymmetricShaderWriter::RegisterWriter( } /* static */ -UsdMayaShaderWriter::ContextSupport UsdMayaSymmetricShaderWriter::CanExport( +UsdMayaPrimWriter::ContextSupport UsdMayaSymmetricShaderWriter::CanExport( const UsdMayaJobExportArgs& exportArgs, const TfToken& materialConversionName) { diff --git a/lib/mayaUsd/fileio/writeJobContext.cpp b/lib/mayaUsd/fileio/writeJobContext.cpp index 0af72d0b92..7349535490 100644 --- a/lib/mayaUsd/fileio/writeJobContext.cpp +++ b/lib/mayaUsd/fileio/writeJobContext.cpp @@ -565,7 +565,7 @@ UsdMayaWriteJobContext::_FindWriter(const MFnDependencyNode& mayaNode) = UsdMayaUtil::GetAllAncestorMayaNodeTypes(mayaNodeType); for (auto i = ancestorTypes.rbegin(); i != ancestorTypes.rend(); ++i) { if (UsdMayaPrimWriterRegistry::WriterFactoryFn primWriterFactory - = UsdMayaPrimWriterRegistry::Find(*i, mArgs, mayaNode)) { + = UsdMayaPrimWriterRegistry::Find(*i, mArgs, mayaNode.object())) { mWriterFactoryCache[mayaNodeType] = primWriterFactory; return primWriterFactory; } diff --git a/lib/mayaUsd/python/wrapPrimWriter.cpp b/lib/mayaUsd/python/wrapPrimWriter.cpp index 3881885e8d..5aefb18500 100644 --- a/lib/mayaUsd/python/wrapPrimWriter.cpp +++ b/lib/mayaUsd/python/wrapPrimWriter.cpp @@ -206,20 +206,32 @@ class PrimWriterWrapper return sptr; } + UsdMayaPrimWriter::ContextSupport + operator()(const UsdMayaJobExportArgs& exportArgs, const MObject& exportObj) + { + + boost::python::object pyClass = GetPythonObject(_classIndex); + if (!pyClass) { + // Prototype was unregistered + return UsdMayaPrimWriter::ContextSupport::Unsupported; + } + TfPyLock pyLock; + boost::python::object CanExport = pyClass.attr("CanExport"); + PyObject* callable = CanExport.ptr(); + auto res = boost::python::call(callable, exportArgs, exportObj); + return UsdMayaPrimWriter::ContextSupport(res); + } + // Create a new wrapper for a Python class that is seen for the first time for a given // purpose. If we already have a registration for this purpose: update the class to // allow the previously issued factory function to use it. - static UsdMayaPrimWriterRegistry::WriterFactoryFn - Register(boost::python::object cl, const std::string& mayaTypeName) + static FactoryFnWrapper + Register(boost::python::object cl, const std::string& mayaTypeName, bool& updated) { size_t classIndex = RegisterPythonObject(cl, GetKey(cl, mayaTypeName)); - if (classIndex != UsdMayaPythonObjectRegistry::UPDATED) { - // Return a new factory function: - return FactoryFnWrapper { classIndex }; - } else { - // We already registered a factory function for this purpose: - return nullptr; - } + updated = classIndex == UsdMayaPythonObjectRegistry::UPDATED; + // Return a new factory function: + return FactoryFnWrapper { classIndex }; } // Unregister a class for a given purpose. This will cause the associated factory @@ -246,10 +258,10 @@ class PrimWriterWrapper static void Register(boost::python::object cl, const std::string& mayaTypeName) { - UsdMayaPrimWriterRegistry::WriterFactoryFn fn - = FactoryFnWrapper::Register(cl, mayaTypeName); - if (fn) { - UsdMayaPrimWriterRegistry::Register(mayaTypeName, fn, true); + bool updated = false; + FactoryFnWrapper fn = FactoryFnWrapper::Register(cl, mayaTypeName, updated); + if (!updated) { + UsdMayaPrimWriterRegistry::Register(mayaTypeName, fn, fn, true); } } @@ -349,18 +361,18 @@ class ShaderWriterWrapper : public PrimWriterWrapper } // We can have multiple function objects, this one apapts the CanImport function: - UsdMayaShaderWriter::ContextSupport operator()(const UsdMayaJobExportArgs& exportArgs) + UsdMayaPrimWriter::ContextSupport operator()(const UsdMayaJobExportArgs& exportArgs) { boost::python::object pyClass = GetPythonObject(_classIndex); if (!pyClass) { // Prototype was unregistered - return UsdMayaShaderWriter::ContextSupport::Unsupported; + return UsdMayaPrimWriter::ContextSupport::Unsupported; } TfPyLock pyLock; boost::python::object CanExport = pyClass.attr("CanExport"); PyObject* callable = CanExport.ptr(); auto res = boost::python::call(callable, exportArgs); - return UsdMayaShaderWriter::ContextSupport(res); + return UsdMayaPrimWriter::ContextSupport(res); } // Create a new wrapper for a Python class that is seen for the first time for a given @@ -598,11 +610,24 @@ void wrapJobExportArgs() .staticmethod("GetDefaultMaterialsScopeName"); } +TF_REGISTRY_FUNCTION(TfEnum) +{ + TF_ADD_ENUM_NAME(UsdMayaPrimWriter::ContextSupport::Supported, "Supported"); + TF_ADD_ENUM_NAME(UsdMayaPrimWriter::ContextSupport::Fallback, "Fallback"); + TF_ADD_ENUM_NAME(UsdMayaPrimWriter::ContextSupport::Unsupported, "Unsupported"); +} + void wrapPrimWriter() { - boost::python::class_, boost::noncopyable>( - "PrimWriter", boost::python::no_init) - .def("__init__", make_constructor(&PrimWriterWrapper<>::New)) + + boost::python::class_, boost::noncopyable> c( + "PrimWriter", boost::python::no_init); + + boost::python::scope s(c); + + TfPyWrapEnum(); + + c.def("__init__", make_constructor(&PrimWriterWrapper<>::New)) .def( "PostExport", &PrimWriterWrapper<>::PostExport, @@ -658,13 +683,6 @@ void wrapPrimWriter() .staticmethod("Unregister"); } -TF_REGISTRY_FUNCTION(TfEnum) -{ - TF_ADD_ENUM_NAME(UsdMayaShaderWriter::ContextSupport::Supported, "Supported"); - TF_ADD_ENUM_NAME(UsdMayaShaderWriter::ContextSupport::Fallback, "Fallback"); - TF_ADD_ENUM_NAME(UsdMayaShaderWriter::ContextSupport::Unsupported, "Unsupported"); -} - //---------------------------------------------------------------------------------------------------------------------- void wrapShaderWriter() { @@ -674,8 +692,6 @@ void wrapShaderWriter() boost::python::scope s(c); - TfPyWrapEnum(); - c.def("__init__", make_constructor(&ShaderWriterWrapper::New)) .def( "GetShadingAttributeNameForMayaAttrName", diff --git a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceWriter.cpp b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceWriter.cpp index 465eb2ff99..b89e24f0c2 100644 --- a/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceWriter.cpp +++ b/lib/usd/pxrUsdPreviewSurface/usdPreviewSurfaceWriter.cpp @@ -135,7 +135,7 @@ void _ValidateNormalMap(const MPlug& shadingNodePlug) } // namespace -UsdMayaShaderWriter::ContextSupport +UsdMayaPrimWriter::ContextSupport PxrMayaUsdPreviewSurface_Writer::CanExport(const UsdMayaJobExportArgs& exportArgs) { if (exportArgs.convertMaterialsTo == UsdImagingTokens->UsdPreviewSurface) { diff --git a/lib/usd/translators/shading/mtlxBaseWriter.cpp b/lib/usd/translators/shading/mtlxBaseWriter.cpp index a0b785ed3a..f0154959d9 100644 --- a/lib/usd/translators/shading/mtlxBaseWriter.cpp +++ b/lib/usd/translators/shading/mtlxBaseWriter.cpp @@ -75,7 +75,7 @@ REGISTER_SHADING_MODE_EXPORT_MATERIAL_CONVERSION( TrMtlxTokens->niceName, TrMtlxTokens->exportDescription); -UsdMayaShaderWriter::ContextSupport +UsdMayaPrimWriter::ContextSupport MtlxUsd_BaseWriter::CanExport(const UsdMayaJobExportArgs& exportArgs) { return exportArgs.convertMaterialsTo == TrMtlxTokens->conversionName diff --git a/lib/usd/translators/shading/mtlxSymmetricShaderWriter.cpp b/lib/usd/translators/shading/mtlxSymmetricShaderWriter.cpp index 3b39f79274..749a02e3d9 100644 --- a/lib/usd/translators/shading/mtlxSymmetricShaderWriter.cpp +++ b/lib/usd/translators/shading/mtlxSymmetricShaderWriter.cpp @@ -146,7 +146,7 @@ void MtlxUsd_SymmetricShaderWriter::RegisterWriter( } /* static */ -UsdMayaShaderWriter::ContextSupport +UsdMayaPrimWriter::ContextSupport MtlxUsd_SymmetricShaderWriter::CanExport(const UsdMayaJobExportArgs& exportArgs) { if (exportArgs.convertMaterialsTo == TrMtlxTokens->conversionName) { diff --git a/lib/usd/translators/shading/usdDisplacementShaderWriter.cpp b/lib/usd/translators/shading/usdDisplacementShaderWriter.cpp index d355e221c9..4e139211f3 100644 --- a/lib/usd/translators/shading/usdDisplacementShaderWriter.cpp +++ b/lib/usd/translators/shading/usdDisplacementShaderWriter.cpp @@ -152,7 +152,7 @@ void PxrUsdTranslators_DisplacementShaderWriter::Write(const UsdTimeCode& usdTim } /* static */ -UsdMayaShaderWriter::ContextSupport +UsdMayaPrimWriter::ContextSupport PxrUsdTranslators_DisplacementShaderWriter::CanExport(const UsdMayaJobExportArgs& exportArgs) { if (exportArgs.convertMaterialsTo == UsdImagingTokens->UsdPreviewSurface) { diff --git a/lib/usd/translators/shading/usdFileTextureWriter.cpp b/lib/usd/translators/shading/usdFileTextureWriter.cpp index c2062a2fc4..02f842bf04 100644 --- a/lib/usd/translators/shading/usdFileTextureWriter.cpp +++ b/lib/usd/translators/shading/usdFileTextureWriter.cpp @@ -115,7 +115,7 @@ TF_DEFINE_PRIVATE_TOKENS( ); // clang-format on -UsdMayaShaderWriter::ContextSupport +UsdMayaPrimWriter::ContextSupport PxrUsdTranslators_FileTextureWriter::CanExport(const UsdMayaJobExportArgs& exportArgs) { if (exportArgs.convertMaterialsTo == UsdImagingTokens->UsdPreviewSurface) { diff --git a/lib/usd/translators/shading/usdMaterialWriter.cpp b/lib/usd/translators/shading/usdMaterialWriter.cpp index af04ebd441..9dee2f8e54 100644 --- a/lib/usd/translators/shading/usdMaterialWriter.cpp +++ b/lib/usd/translators/shading/usdMaterialWriter.cpp @@ -51,7 +51,7 @@ PXR_NAMESPACE_OPEN_SCOPE -UsdMayaShaderWriter::ContextSupport +UsdMayaPrimWriter::ContextSupport PxrUsdTranslators_MaterialWriter::CanExport(const UsdMayaJobExportArgs& exportArgs) { if (exportArgs.convertMaterialsTo == UsdImagingTokens->UsdPreviewSurface) { From cc0e561c54a89d729aabefdd8cc08cb5e2756314 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Tue, 11 Jul 2023 15:21:37 -0400 Subject: [PATCH 07/12] Clang format fix --- lib/mayaUsd/fileio/primWriterRegistry.cpp | 2 +- lib/mayaUsd/fileio/primWriterRegistry.h | 2 +- lib/mayaUsd/python/wrapPrimWriter.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mayaUsd/fileio/primWriterRegistry.cpp b/lib/mayaUsd/fileio/primWriterRegistry.cpp index ab54a0cb4f..b49b6f30c5 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.cpp +++ b/lib/mayaUsd/fileio/primWriterRegistry.cpp @@ -59,7 +59,7 @@ static int _indexCounter = 0; _Registry::const_iterator _Find( const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs, - const MObject& exportObj) + const MObject& exportObj) { using ContextSupport = UsdMayaPrimWriter::ContextSupport; diff --git a/lib/mayaUsd/fileio/primWriterRegistry.h b/lib/mayaUsd/fileio/primWriterRegistry.h index d9712e00ea..cde16e4b76 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.h +++ b/lib/mayaUsd/fileio/primWriterRegistry.h @@ -145,7 +145,7 @@ struct UsdMayaPrimWriterRegistry static WriterFactoryFn Find( const std::string& mayaTypeName, const UsdMayaJobExportArgs& exportArgs, - const MObject& exportObj); + const MObject& exportObj); /// \brief Check for external primWriter for \p mayaTypeName. MAYAUSD_CORE_PUBLIC diff --git a/lib/mayaUsd/python/wrapPrimWriter.cpp b/lib/mayaUsd/python/wrapPrimWriter.cpp index 5aefb18500..6b956acfe9 100644 --- a/lib/mayaUsd/python/wrapPrimWriter.cpp +++ b/lib/mayaUsd/python/wrapPrimWriter.cpp @@ -209,7 +209,7 @@ class PrimWriterWrapper UsdMayaPrimWriter::ContextSupport operator()(const UsdMayaJobExportArgs& exportArgs, const MObject& exportObj) { - + boost::python::object pyClass = GetPythonObject(_classIndex); if (!pyClass) { // Prototype was unregistered @@ -219,7 +219,7 @@ class PrimWriterWrapper boost::python::object CanExport = pyClass.attr("CanExport"); PyObject* callable = CanExport.ptr(); auto res = boost::python::call(callable, exportArgs, exportObj); - return UsdMayaPrimWriter::ContextSupport(res); + return UsdMayaPrimWriter::ContextSupport(res); } // Create a new wrapper for a Python class that is seen for the first time for a given From 84cff9fcffaaa221ea8750269f0f049d672d8579 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Tue, 11 Jul 2023 17:18:05 -0400 Subject: [PATCH 08/12] Add default context support for cases CanExport not implemented --- lib/mayaUsd/python/wrapPrimWriter.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/mayaUsd/python/wrapPrimWriter.cpp b/lib/mayaUsd/python/wrapPrimWriter.cpp index 6b956acfe9..80073aff2c 100644 --- a/lib/mayaUsd/python/wrapPrimWriter.cpp +++ b/lib/mayaUsd/python/wrapPrimWriter.cpp @@ -215,11 +215,15 @@ class PrimWriterWrapper // Prototype was unregistered return UsdMayaPrimWriter::ContextSupport::Unsupported; } - TfPyLock pyLock; - boost::python::object CanExport = pyClass.attr("CanExport"); - PyObject* callable = CanExport.ptr(); - auto res = boost::python::call(callable, exportArgs, exportObj); - return UsdMayaPrimWriter::ContextSupport(res); + TfPyLock pyLock; + if (PyObject_HasAttrString(pyClass.ptr(), "CanExport")) { + boost::python::object CanExport = pyClass.attr("CanExport"); + PyObject* callable = CanExport.ptr(); + auto res = boost::python::call(callable, exportArgs, exportObj); + return UsdMayaPrimWriter::ContextSupport(res); + } else { + return UsdMayaPrimWriter::ContextSupport::Fallback; + } } // Create a new wrapper for a Python class that is seen for the first time for a given From 1d5fabee5fe0486bde32e5ee6eb7a2a71afed118 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Fri, 21 Jul 2023 20:37:12 -0400 Subject: [PATCH 09/12] Update unit test for primWriter and shaderWriter --- test/lib/mayaUsd/fileio/testPrimWriter.py | 3 +++ test/lib/mayaUsd/fileio/testShaderWriter.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/test/lib/mayaUsd/fileio/testPrimWriter.py b/test/lib/mayaUsd/fileio/testPrimWriter.py index ec03d551b7..3688da0fee 100644 --- a/test/lib/mayaUsd/fileio/testPrimWriter.py +++ b/test/lib/mayaUsd/fileio/testPrimWriter.py @@ -49,6 +49,9 @@ def __init__(self, *args, **kwargs): self._SetUsdPrim(usdPrim) primWriterTest.InitCalled = True + def CanExport(cls, exportArgs, exportObj=None): + return mayaUsdLib.PrimWriter.ContextSupport.Supported + def Write(self, usdTime): depNodeFn = OpenMaya.MFnDependencyNode(self.GetMayaObject()) plg = depNodeFn.findPlug('inMesh', True) diff --git a/test/lib/mayaUsd/fileio/testShaderWriter.py b/test/lib/mayaUsd/fileio/testShaderWriter.py index dbff2c3242..3192999735 100644 --- a/test/lib/mayaUsd/fileio/testShaderWriter.py +++ b/test/lib/mayaUsd/fileio/testShaderWriter.py @@ -35,7 +35,7 @@ class shaderWriterTest(mayaUsdLib.ShaderWriter): @classmethod def CanExport(cls, exportArgs): shaderWriterTest.CanExportCalled = True - return mayaUsdLib.ShaderWriter.ContextSupport.Supported + return mayaUsdLib.PrimWriter.ContextSupport.Supported def Write(self, usdTime): shaderWriterTest.WriteCalledCount += 1 From 3f18188de8c4cb52104915ed909e57fc7bef5dcb Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Mon, 24 Jul 2023 13:03:04 -0400 Subject: [PATCH 10/12] Add classmethod decorator to CanExport --- test/lib/mayaUsd/fileio/testPrimWriter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/lib/mayaUsd/fileio/testPrimWriter.py b/test/lib/mayaUsd/fileio/testPrimWriter.py index 3688da0fee..4d0d0d1936 100644 --- a/test/lib/mayaUsd/fileio/testPrimWriter.py +++ b/test/lib/mayaUsd/fileio/testPrimWriter.py @@ -49,6 +49,7 @@ def __init__(self, *args, **kwargs): self._SetUsdPrim(usdPrim) primWriterTest.InitCalled = True + @classmethod def CanExport(cls, exportArgs, exportObj=None): return mayaUsdLib.PrimWriter.ContextSupport.Supported From d9e10017981e9e4c1f261cfaa0e83880772ada84 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Wed, 26 Jul 2023 13:58:38 -0400 Subject: [PATCH 11/12] Rename poke function and refine comments --- lib/mayaUsd/fileio/primWriterRegistry.cpp | 6 ++++-- lib/mayaUsd/fileio/primWriterRegistry.h | 2 +- lib/mayaUsd/fileio/utils/adaptor.cpp | 2 +- lib/mayaUsd/python/wrapPrimWriter.cpp | 5 ++++- test/lib/mayaUsd/fileio/testPrimWriter.py | 3 +++ 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/mayaUsd/fileio/primWriterRegistry.cpp b/lib/mayaUsd/fileio/primWriterRegistry.cpp index b49b6f30c5..ccbace42ba 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.cpp +++ b/lib/mayaUsd/fileio/primWriterRegistry.cpp @@ -179,8 +179,10 @@ UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( return it->second._writer; } - // ideally something just registered itself. if not, we at least put it in + // if nothing was found and nothing was registered, we at least put it in // the registry in case we encounter it again. + TF_DEBUG(PXRUSDMAYA_REGISTRY) + .Msg("No usdMaya writer plugin for TfType %s. No maya plugin.\n", mayaTypeName); if (_reg.count(mayaTypeName) == 0) { // Nothing registered at all, remember that: _reg.insert(std::make_pair( @@ -196,7 +198,7 @@ UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( } /* static */ -void UsdMayaPrimWriterRegistry::Poke(const std::string& mayaTypeName) +void UsdMayaPrimWriterRegistry::CheckForWriterPlugin(const std::string& mayaTypeName) { TfRegistryManager::GetInstance().SubscribeTo(); diff --git a/lib/mayaUsd/fileio/primWriterRegistry.h b/lib/mayaUsd/fileio/primWriterRegistry.h index cde16e4b76..73a823573a 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.h +++ b/lib/mayaUsd/fileio/primWriterRegistry.h @@ -149,7 +149,7 @@ struct UsdMayaPrimWriterRegistry /// \brief Check for external primWriter for \p mayaTypeName. MAYAUSD_CORE_PUBLIC - static void Poke(const std::string& mayaTypeName); + static void CheckForWriterPlugin(const std::string& mayaTypeName); /// \brief Registers a maya node type to *not* create a new prim. /// diff --git a/lib/mayaUsd/fileio/utils/adaptor.cpp b/lib/mayaUsd/fileio/utils/adaptor.cpp index 3f8dcefa4c..4b7a022e6a 100644 --- a/lib/mayaUsd/fileio/utils/adaptor.cpp +++ b/lib/mayaUsd/fileio/utils/adaptor.cpp @@ -158,7 +158,7 @@ TfType UsdMayaAdaptor::GetUsdType() const // The adaptor type mapping might be registered externally in a prim writer // plugin. This simply pokes the prim writer registry to load the prim // writer plugin in order to pull in the adaptor mapping. - UsdMayaPrimWriterRegistry::Poke(depNode.typeName().asChar()); + UsdMayaPrimWriterRegistry::CheckForWriterPlugin(depNode.typeName().asChar()); TfRegistryManager::GetInstance().SubscribeTo(); const auto iter = _schemaLookup.find(depNode.typeName().asChar()); diff --git a/lib/mayaUsd/python/wrapPrimWriter.cpp b/lib/mayaUsd/python/wrapPrimWriter.cpp index 80073aff2c..d630065835 100644 --- a/lib/mayaUsd/python/wrapPrimWriter.cpp +++ b/lib/mayaUsd/python/wrapPrimWriter.cpp @@ -233,7 +233,7 @@ class PrimWriterWrapper Register(boost::python::object cl, const std::string& mayaTypeName, bool& updated) { size_t classIndex = RegisterPythonObject(cl, GetKey(cl, mayaTypeName)); - updated = classIndex == UsdMayaPythonObjectRegistry::UPDATED; + updated = (classIndex == UsdMayaPythonObjectRegistry::UPDATED); // Return a new factory function: return FactoryFnWrapper { classIndex }; } @@ -265,6 +265,9 @@ class PrimWriterWrapper bool updated = false; FactoryFnWrapper fn = FactoryFnWrapper::Register(cl, mayaTypeName, updated); if (!updated) { + + // fn is used twice because the register function will handle both + // CanExport and FactoryFn UsdMayaPrimWriterRegistry::Register(mayaTypeName, fn, fn, true); } } diff --git a/test/lib/mayaUsd/fileio/testPrimWriter.py b/test/lib/mayaUsd/fileio/testPrimWriter.py index 4d0d0d1936..53c3d30a3f 100644 --- a/test/lib/mayaUsd/fileio/testPrimWriter.py +++ b/test/lib/mayaUsd/fileio/testPrimWriter.py @@ -32,6 +32,7 @@ class primWriterTest(mayaUsdLib.PrimWriter): InitCalled = False WriteCalled = False PostExportCalled = False + CanExportCalled = False def __init__(self, *args, **kwargs): super(primWriterTest, self).__init__(*args, **kwargs) @@ -51,6 +52,7 @@ def __init__(self, *args, **kwargs): @classmethod def CanExport(cls, exportArgs, exportObj=None): + primWriterTest.CanExportCalled = True return mayaUsdLib.PrimWriter.ContextSupport.Supported def Write(self, usdTime): @@ -92,6 +94,7 @@ def testSimplePrimWriter(self): shadingMode='none') self.assertTrue(primWriterTest.InitCalled) + self.assertTrue(primWriterTest.CanExportCalled) self.assertTrue(primWriterTest.WriteCalled) self.assertTrue(primWriterTest.PostExportCalled) From 2725e962d48560e5ea76ee820161d024cdc32d61 Mon Sep 17 00:00:00 2001 From: Samuel Liu Date: Wed, 26 Jul 2023 14:25:13 -0400 Subject: [PATCH 12/12] Bug fix for string conversion --- lib/mayaUsd/fileio/primWriterRegistry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mayaUsd/fileio/primWriterRegistry.cpp b/lib/mayaUsd/fileio/primWriterRegistry.cpp index ccbace42ba..5ee4ffa6d0 100644 --- a/lib/mayaUsd/fileio/primWriterRegistry.cpp +++ b/lib/mayaUsd/fileio/primWriterRegistry.cpp @@ -182,7 +182,7 @@ UsdMayaPrimWriterRegistry::WriterFactoryFn UsdMayaPrimWriterRegistry::Find( // if nothing was found and nothing was registered, we at least put it in // the registry in case we encounter it again. TF_DEBUG(PXRUSDMAYA_REGISTRY) - .Msg("No usdMaya writer plugin for TfType %s. No maya plugin.\n", mayaTypeName); + .Msg("No usdMaya writer plugin for TfType %s. No maya plugin.\n", mayaTypeName.c_str()); if (_reg.count(mayaTypeName) == 0) { // Nothing registered at all, remember that: _reg.insert(std::make_pair(