Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API writers #2557

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/mayaUsd/fileio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# -----------------------------------------------------------------------------
target_sources(${PROJECT_NAME}
PRIVATE
apiWriterContext.cpp
apiWriterRegistry.cpp
fallbackPrimReader.cpp
functorPrimReader.cpp
functorPrimWriter.cpp
Expand Down Expand Up @@ -42,6 +44,8 @@ if(CMAKE_UFE_V3_FEATURES_AVAILABLE)
endif()

set(HEADERS
apiWriterContext.h
apiWriterRegistry.h
fallbackPrimReader.h
functorPrimReader.h
functorPrimWriter.h
Expand Down
37 changes: 37 additions & 0 deletions lib/mayaUsd/fileio/apiWriterContext.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// Copyright 2022 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "apiWriterContext.h"

PXR_NAMESPACE_OPEN_SCOPE

UsdMayaApiWriterContext::UsdMayaApiWriterContext(
const MDagPath& dagPath,
const UsdPrim& usdPrim,
const UsdTimeCode& timeCode)
: _dagPath(dagPath)
, _usdPrim(usdPrim)
, _timeCode(timeCode)
{
}

const MDagPath& UsdMayaApiWriterContext::GetMDagPath() const { return _dagPath; }

const UsdPrim& UsdMayaApiWriterContext::GetUsdPrim() const { return _usdPrim; }

const UsdTimeCode& UsdMayaApiWriterContext::GetTimeCode() const { return _timeCode; }

PXR_NAMESPACE_CLOSE_SCOPE
62 changes: 62 additions & 0 deletions lib/mayaUsd/fileio/apiWriterContext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// Copyright 2022 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef PXRUSDMAYA_APIWRITERCONTEXT_H
#define PXRUSDMAYA_APIWRITERCONTEXT_H

#include <mayaUsd/base/api.h>

#include <pxr/pxr.h>

#include <maya/MDagPath.h>

PXR_NAMESPACE_OPEN_SCOPE

class UsdPrim;
class UsdTimeCode;

/// Class that provides an interface for API writer plugins.
/// \sa UsdMayaApiWriterRegistry
class UsdMayaApiWriterContext
{
public:
MAYAUSD_CORE_PUBLIC
UsdMayaApiWriterContext(
const MDagPath& dagPath,
const UsdPrim& usdPrim,
const UsdTimeCode& timeCode);

/// Returns the MDagPath that corresponds to the \p usdPrim that was
/// exported that the API is being applied to.
MAYAUSD_CORE_PUBLIC
const MDagPath& GetMDagPath() const;

/// Returns the UsdPrim that was just exported.
MAYAUSD_CORE_PUBLIC
const UsdPrim& GetUsdPrim() const;

/// Returns the time code.
MAYAUSD_CORE_PUBLIC
const UsdTimeCode& GetTimeCode() const;

private:
const MDagPath& _dagPath;
const UsdPrim& _usdPrim;
const UsdTimeCode& _timeCode;
};

PXR_NAMESPACE_CLOSE_SCOPE

#endif
39 changes: 39 additions & 0 deletions lib/mayaUsd/fileio/apiWriterRegistry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// Copyright 2022 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "apiWriterRegistry.h"

#include <pxr/pxr.h>

PXR_NAMESPACE_OPEN_SCOPE

static std::map<std::string, UsdMayaApiWriterRegistry::WriterFn> _reg;

void UsdMayaApiWriterRegistry::Register(const std::string& writerId, const WriterFn& fn)
{
const bool inserted = _reg.insert({ writerId, fn }).second;
if (!inserted) {
TF_CODING_ERROR("Duplicate registration for %s.", writerId.c_str());
}
}

const std::map<std::string, UsdMayaApiWriterRegistry::WriterFn>& UsdMayaApiWriterRegistry::GetAll()
{
TfRegistryManager::GetInstance().SubscribeTo<UsdMayaApiWriterRegistry>();
return _reg;
}

PXR_NAMESPACE_CLOSE_SCOPE
68 changes: 68 additions & 0 deletions lib/mayaUsd/fileio/apiWriterRegistry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//
// Copyright 2022 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef PXRUSDMAYA_API_WRITER_REGISTRY_H
#define PXRUSDMAYA_API_WRITER_REGISTRY_H

#include <mayaUsd/fileio/primWriterRegistry.h>

#include <pxr/pxr.h>

#include <string>

PXR_NAMESPACE_OPEN_SCOPE

class UsdMayaApiWriterContext;

/// API writers are plugins that can apply API schemas to exported UsdPrims.
///
/// For each prim that is exported, we will then run all of the API Writers (in
/// writerId order).
class UsdMayaApiWriterRegistry
{
public:
using WriterFn = std::function<bool(UsdMayaApiWriterContext*)>;

/// Registers \p fn as an API writer. This will be identified by \p
/// writerId.
static void Register(const std::string& writerId, const WriterFn& fn);

/// Returns all a map of all the API writers.
static const std::map<std::string, WriterFn>& GetAll();

private:
};

/// This macro is for handling the case of a maya type that corresponds to an
/// API schema. In particular, the mayaTypeName should *not* result in a new
/// UsdPrim.
#define PXRUSDMAYA_DEFINE_API_WRITER(mayaTypeName, ctxVarName) \
struct UsdMayaApiWriter_##mayaTypeName \
{ \
}; \
static bool UsdMaya_ApiWriter_##mayaTypeName(UsdMayaApiWriterContext*); \
TF_REGISTRY_FUNCTION_WITH_TAG(UsdMayaPrimWriterRegistry, UsdMayaWriter_##mayaTypeName) \
{ \
UsdMayaPrimWriterRegistry::RegisterPrimless(#mayaTypeName); \
} \
TF_REGISTRY_FUNCTION_WITH_TAG(UsdMayaApiWriterRegistry, UsdMayaWriter_##mayaTypeName) \
{ \
UsdMayaApiWriterRegistry::Register(#mayaTypeName, UsdMaya_ApiWriter_##mayaTypeName); \
} \
bool UsdMaya_ApiWriter_##mayaTypeName(UsdMayaApiWriterContext* ctxVarName)

PXR_NAMESPACE_CLOSE_SCOPE

#endif
22 changes: 22 additions & 0 deletions lib/mayaUsd/fileio/primWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
//
#include "primWriter.h"

#include <mayaUsd/fileio/apiWriterContext.h>
#include <mayaUsd/fileio/apiWriterRegistry.h>
#include <mayaUsd/fileio/jobs/jobArgs.h>
#include <mayaUsd/fileio/translators/translatorGprim.h>
#include <mayaUsd/fileio/utils/adaptor.h>
Expand Down Expand Up @@ -106,6 +108,20 @@ static bool _GetClassNamesToWrite(const MObject& mObj, std::vector<std::string>*
MFnDependencyNode(mObj), MString(_tokens->USD_inheritClassNames.GetText()), outClassNames);
}

static void _WriteAPISchemasFromRegistry(UsdMayaApiWriterContext* ctx)
{
for (const auto& idAndFn : UsdMayaApiWriterRegistry::GetAll()) {
const std::string& writerId = idAndFn.first;
const UsdMayaApiWriterRegistry::WriterFn& writerFn = idAndFn.second;
if (!writerFn(ctx)) {
TF_WARN(
"API writer '%s' did not export properly at %s.",
writerId.c_str(),
ctx->GetUsdPrim().GetPath().GetText());
}
}
}

/* virtual */
void UsdMayaPrimWriter::Write(const UsdTimeCode& usdTime)
{
Expand Down Expand Up @@ -203,6 +219,12 @@ void UsdMayaPrimWriter::Write(const UsdTimeCode& usdTime)
UsdMayaWriteUtil::WriteMetadataToPrim(GetMayaObject(), _usdPrim);
}

// Write any applied API schemas via the API writer registry.
{
UsdMayaApiWriterContext ctx(GetDagPath(), _usdPrim, usdTime);
_WriteAPISchemasFromRegistry(&ctx);
}

UsdMayaWriteUtil::WriteAPISchemaAttributesToPrim(
GetMayaObject(), _usdPrim, _GetExportArgs(), usdTime, _GetSparseValueWriter());

Expand Down
14 changes: 14 additions & 0 deletions lib/mayaUsd/fileio/primWriterRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ TF_DEFINE_PRIVATE_TOKENS(

typedef std::map<std::string, UsdMayaPrimWriterRegistry::WriterFactoryFn> _Registry;
static _Registry _reg;
static std::set<std::string> _mayaTypesThatDoNotCreatePrims;

/* static */
void UsdMayaPrimWriterRegistry::Register(
Expand Down Expand Up @@ -101,4 +102,17 @@ UsdMayaPrimWriterRegistry::Find(const std::string& mayaTypeName)
return ret;
}

/* static */
void UsdMayaPrimWriterRegistry::RegisterPrimless(const std::string& mayaTypeName)
{
TfRegistryManager::GetInstance().SubscribeTo<UsdMayaPrimWriterRegistry>();
_mayaTypesThatDoNotCreatePrims.insert(mayaTypeName);
}

/* static */
bool UsdMayaPrimWriterRegistry::IsPrimless(const std::string& mayaTypeName)
{
return _mayaTypesThatDoNotCreatePrims.count(mayaTypeName) == 0;
}

PXR_NAMESPACE_CLOSE_SCOPE
27 changes: 27 additions & 0 deletions lib/mayaUsd/fileio/primWriterRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,33 @@ struct UsdMayaPrimWriterRegistry
/// If there is no writer plugin for \p mayaTypeName, returns nullptr.
MAYAUSD_CORE_PUBLIC
static WriterFactoryFn Find(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
/// Usd. For example, the Maya node may be exported as an applied API
/// schema on an exported UsdPrim.
///
/// This could be relevant when determining whether or not a transform can
/// be collapsed. For example:
/// ```
/// |Mesh (transform)
/// |MeshShape (mesh)
/// |MyNode (transform)
/// |MyNodeShape (typeThatShouldNotBeExported)
/// ```
/// The "Mesh" and "MeshShape" nodes are collapsible because "MyNode" should
/// not result in a prim.
MAYAUSD_CORE_PUBLIC
static void RegisterPrimless(const std::string& mayaTypeName);

/// \brief Returns true if \p mayaTypeName nodes should result in a prim in
/// Usd.
///
/// This typically returns true unless \p mayaTypeName was explicitly
/// registered to not be exported.
MAYAUSD_CORE_PUBLIC
static bool IsPrimless(const std::string& mayaTypeName);
};

// Note, TF_REGISTRY_FUNCTION_WITH_TAG needs a type to register with so we
Expand Down
Loading