Skip to content

Commit

Permalink
Merge branch 'dev' into bailp/MAYA-127404/save-relative-sub-layers
Browse files Browse the repository at this point in the history
  • Loading branch information
pierrebai-adsk committed Mar 1, 2023
2 parents 33420d2 + d075edb commit 260cb5a
Show file tree
Hide file tree
Showing 98 changed files with 3,113 additions and 578 deletions.
125 changes: 66 additions & 59 deletions lib/mayaUsd/commands/Readme.md

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions lib/mayaUsd/commands/baseExportCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,14 @@ MSyntax MayaUSDExportCommand::createSyntax()
syntax.addFlag(
kGeomSidednessFlag, UsdMayaJobExportArgsTokens->geomSidedness.GetText(), MSyntax::kString);

syntax.addFlag(
kCustomLayerData,
UsdMayaJobExportArgsTokens->customLayerData.GetText(),
MSyntax::kString,
MSyntax::kString,
MSyntax::kString);
syntax.makeFlagMultiUse(UsdMayaJobExportArgsTokens->customLayerData.GetText());

// These are additional flags under our control.
syntax.addFlag(kFrameRangeFlag, kFrameRangeFlagLong, MSyntax::kDouble, MSyntax::kDouble);
syntax.addFlag(kFrameStrideFlag, kFrameStrideFlagLong, MSyntax::kDouble);
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/commands/baseExportCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MAYAUSD_CORE_PUBLIC MayaUSDExportCommand : public MPxCommand
static constexpr auto kApiSchemaFlag = "api";
static constexpr auto kJobContextFlag = "jc";
static constexpr auto kWorldspaceFlag = "wsp";
static constexpr auto kCustomLayerData = "cld";

// Short and Long forms of flags defined by this command itself:
static constexpr auto kAppendFlag = "a";
Expand Down
133 changes: 131 additions & 2 deletions lib/mayaUsd/fileio/jobs/jobArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <pxr/base/tf/diagnostic.h>
#include <pxr/base/tf/envSetting.h>
#include <pxr/base/tf/fileUtils.h>
#include <pxr/base/tf/getenv.h>
#include <pxr/base/tf/staticTokens.h>
#include <pxr/base/tf/token.h>
#include <pxr/base/vt/array.h>
Expand All @@ -46,6 +47,7 @@

#include <ghc/filesystem.hpp>

#include <cstdlib>
#include <mutex>
#include <ostream>
#include <string>
Expand Down Expand Up @@ -78,6 +80,10 @@ TF_DEFINE_PRIVATE_TOKENS(

namespace {

// Default material scope name as defined by USD Assets working group.
// See https://wiki.aswf.io/display/WGUSD/Guidelines+for+Structuring+USD+Assets
static constexpr auto kDefaultMaterialScopeName = "mtl";

using namespace MayaUsd::DictUtils;

// The chaser args are stored as vectors of vectors (since this is how you
Expand Down Expand Up @@ -123,6 +129,116 @@ std::map<std::string, std::string> _UVSetRemaps(const VtDictionary& userArgs, co
return result;
}

bool _striequals(const std::string& a, const std::string& b)
{
size_t aSize = a.size();
if (b.size() != aSize) {
return false;
}
for (size_t i = 0; i < aSize; ++i)
if (std::tolower(a[i]) != std::tolower(b[i])) {
return false;
}
return true;
}

// The Custom Layer Data is stored as a vector of vectors (as this is
// how a multi use , multi argument flag is passed in).
// This function converts it to a VtDictionary.
// Parsing failures skip the value instead of early returning.
static VtDictionary _CustomLayerData(const VtDictionary& userArgs, const TfToken& userArgKey)
{
const std::vector<std::vector<VtValue>> keyValueTypes
= extractVector<std::vector<VtValue>>(userArgs, userArgKey);

VtDictionary data = VtDictionary(keyValueTypes.size());

for (const std::vector<VtValue>& argTriple : keyValueTypes) {
if (argTriple.size() != 3) {
TF_WARN("Each customLayerData argument must be a triple (key, value, type)");
continue;
}

const std::string& key = argTriple[0].Get<std::string>();
const std::string& raw_value = argTriple[1].Get<std::string>();
const std::string& type = argTriple[2].Get<std::string>();

VtValue val = VtValue();
if (type == "string") {
val = raw_value;
} else if (type == "int") {
char* e = NULL;
val = static_cast<int>(std::strtol(raw_value.c_str(), &e, 10));
if (e != &raw_value[0] + raw_value.size()) {
TF_WARN(
"Could not parse '%s' as an integer; the first invalid digit was: %s",
raw_value.c_str(),
e);
continue;
} else if (errno == ERANGE) {
TF_WARN(
"Could not parse '%s' as an integer; it would have exceeded the valid range.",
raw_value.c_str());
continue;
}
} else if (type == "float") {
char* e = NULL;
val = static_cast<float>(std::strtof(raw_value.c_str(), &e));
if (e != &raw_value[0] + raw_value.size()) {
TF_WARN(
"Could not parse '%s' as a float; the first invalid digit was: %s",
raw_value.c_str(),
e);
errno = 0;
continue;
} else if (errno == ERANGE) {
TF_WARN(
"Could not parse '%s' as a float; it would have exceeded the valid range.",
raw_value.c_str());
errno = 0;
continue;
}
} else if (type == "double") {
char* e = NULL;
val = static_cast<double>(std::strtod(raw_value.c_str(), &e));
if (e != &raw_value[0] + raw_value.size()) {
TF_WARN(
"Could not parse '%s' as a double; the first invalid digit was: %s",
raw_value.c_str(),
e);
errno = 0;
continue;
} else if (errno == ERANGE) {
TF_WARN(
"Could not parse '%s' as a double; it would have exceeded the valid range.",
raw_value.c_str());
errno = 0;
continue;
}
} else if (type == "bool") {
if (raw_value == "1") {
val = true;
} else if (raw_value == "0") {
val = false;
} else if (_striequals(raw_value, "true")) {
val = true;
} else if (_striequals(raw_value, "false")) {
val = false;
} else {
TF_WARN("Could not parse '%s' as bool", raw_value.c_str());
continue;
}
} else {
TF_WARN("Unsupported customLayerData type '%s' for '%s'", type.c_str(), key.c_str());
continue;
}

data.SetValueAtPath(key, val);
}

return data;
}

// The shadingMode args are stored as vectors of vectors (since this is how you
// would need to pass them in the Maya Python command API).
UsdMayaJobImportArgs::ShadingModes
Expand Down Expand Up @@ -176,6 +292,12 @@ TfToken _GetMaterialsScopeName(const std::string& materialsScopeName)
// If the env setting is set, make sure we don't allow the materials
// scope name to be overridden by a parameter value.
return defaultMaterialsScopeName;
} else {
const std::string mayaUsdDefaultMaterialsScopeName
= TfGetenv("MAYAUSD_MATERIALS_SCOPE_NAME");
if (!mayaUsdDefaultMaterialsScopeName.empty()) {
return TfToken(mayaUsdDefaultMaterialsScopeName);
}
}

if (SdfPath::IsValidIdentifier(materialsScopeName)) {
Expand Down Expand Up @@ -514,6 +636,7 @@ UsdMayaJobExportArgs::UsdMayaJobExportArgs(
, jobContextNames(extractTokenSet(userArgs, UsdMayaJobExportArgsTokens->jobContext))
, chaserNames(extractVector<std::string>(userArgs, UsdMayaJobExportArgsTokens->chaser))
, allChaserArgs(_ChaserArgs(userArgs, UsdMayaJobExportArgsTokens->chaserArgs))
, customLayerData(_CustomLayerData(userArgs, UsdMayaJobExportArgsTokens->customLayerData))
, remapUVSetsTo(_UVSetRemaps(userArgs, UsdMayaJobExportArgsTokens->remapUVSetsTo))
, melPerFrameCallback(extractString(userArgs, UsdMayaJobExportArgsTokens->melPerFrameCallback))
, melPostCallback(extractString(userArgs, UsdMayaJobExportArgsTokens->melPostCallback))
Expand Down Expand Up @@ -826,8 +949,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetDefaultDictionary()
d[UsdMayaJobExportArgsTokens->kind] = std::string();
d[UsdMayaJobExportArgsTokens->disableModelKindProcessor] = false;
d[UsdMayaJobExportArgsTokens->materialCollectionsPath] = std::string();
d[UsdMayaJobExportArgsTokens->materialsScopeName]
= UsdUtilsGetMaterialsScopeName().GetString();
d[UsdMayaJobExportArgsTokens->materialsScopeName] = kDefaultMaterialScopeName;
d[UsdMayaJobExportArgsTokens->melPerFrameCallback] = std::string();
d[UsdMayaJobExportArgsTokens->melPostCallback] = std::string();
d[UsdMayaJobExportArgsTokens->mergeTransformAndShape] = true;
Expand All @@ -851,6 +973,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetDefaultDictionary()
d[UsdMayaJobExportArgsTokens->staticSingleSample] = false;
d[UsdMayaJobExportArgsTokens->geomSidedness]
= UsdMayaJobExportArgsTokens->derived.GetString();
d[UsdMayaJobExportArgsTokens->customLayerData] = std::vector<VtValue>();

// plugInfo.json site defaults.
// The defaults dict should be correctly-typed, so enable
Expand Down Expand Up @@ -889,6 +1012,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetGuideDictionary()
d[UsdMayaJobExportArgsTokens->chaser] = _stringVector;
d[UsdMayaJobExportArgsTokens->chaserArgs] = _stringTripletVector;
d[UsdMayaJobExportArgsTokens->remapUVSetsTo] = _stringPairVector;
d[UsdMayaJobExportArgsTokens->customLayerData] = _stringTripletVector;
d[UsdMayaJobExportArgsTokens->compatibility] = _string;
d[UsdMayaJobExportArgsTokens->defaultCameras] = _boolean;
d[UsdMayaJobExportArgsTokens->defaultMeshScheme] = _string;
Expand Down Expand Up @@ -940,6 +1064,11 @@ const VtDictionary& UsdMayaJobExportArgs::GetGuideDictionary()
return d;
}

const std::string UsdMayaJobExportArgs::GetDefaultMaterialsScopeName()
{
return _GetMaterialsScopeName(kDefaultMaterialScopeName);
}

std::string UsdMayaJobExportArgs::GetResolvedFileName() const
{
MFileObject fileObj;
Expand Down
10 changes: 9 additions & 1 deletion lib/mayaUsd/fileio/jobs/jobArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ TF_DECLARE_PUBLIC_TOKENS(
(staticSingleSample) \
(geomSidedness) \
(worldspace) \
(customLayerData) \
/* Special "none" token */ \
(none) \
/* referenceObjectMode values */ \
Expand All @@ -124,7 +125,7 @@ TF_DECLARE_PUBLIC_TOKENS(
/* geomSidedness values */ \
(derived) \
(single) \
((double_, "double")) \
((double_, "double"))
// clang-format on

TF_DECLARE_PUBLIC_TOKENS(
Expand Down Expand Up @@ -230,6 +231,7 @@ struct UsdMayaJobExportArgs
using ChaserArgs = std::map<std::string, std::string>;
const std::vector<std::string> chaserNames;
const std::map<std::string, ChaserArgs> allChaserArgs;
const VtDictionary customLayerData;

const std::map<std::string, std::string> remapUVSetsTo;

Expand Down Expand Up @@ -294,6 +296,12 @@ struct UsdMayaJobExportArgs
MAYAUSD_CORE_PUBLIC
static const VtDictionary& GetGuideDictionary();

/// Gets the resolved default material scope name.
///
/// Accounts for all env vars that can affect the scope name.
MAYAUSD_CORE_PUBLIC
static const std::string GetDefaultMaterialsScopeName();

/// Returns the resolved file name of the final export location
MAYAUSD_CORE_PUBLIC
std::string GetResolvedFileName() const;
Expand Down
5 changes: 5 additions & 0 deletions lib/mayaUsd/fileio/jobs/writeJob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ bool UsdMaya_WriteJob::_BeginWriting(const std::string& fileName, bool append)
mJobCtx.mStage->SetFramesPerSecond(UsdMayaUtil::GetSceneMTimeUnitAsDouble());
}

// Set the customLayerData on the layer
if (!mJobCtx.mArgs.customLayerData.empty()) {
mJobCtx.mStage->GetRootLayer()->SetCustomLayerData(mJobCtx.mArgs.customLayerData);
}

// Setup the requested render layer mode:
// defaultLayer - Switch to the default render layer before exporting,
// then switch back afterwards (no layer switching if
Expand Down
3 changes: 2 additions & 1 deletion lib/mayaUsd/fileio/translators/translatorMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@ TranslatorMeshRead::TranslatorMeshRead(
// ==================================================
// Code below this point is for handling deforming meshes, so if we don't
// have time samples to deal with, we're done.
if (m_pointsNumTimeSamples == 0u) {
// A single sample can be treated as static
if (m_pointsNumTimeSamples < 2u) {
return;
}

Expand Down
32 changes: 32 additions & 0 deletions lib/mayaUsd/listeners/stageNoticeListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ void UsdMayaStageNoticeListener::SetStageLayerMutingChangedCallback(
_UpdateStageContentsChangedRegistration();
}

void UsdMayaStageNoticeListener::SetStageEditTargetChangedCallback(
const StageEditTargetChangedCallback& callback)
{
_stageEditTargetChangedCallback = callback;

_UpdateStageContentsChangedRegistration();
}

void UsdMayaStageNoticeListener::_UpdateStageContentsChangedRegistration()
{
if (_stage && _stageContentsChangedCallback) {
Expand Down Expand Up @@ -109,6 +117,22 @@ void UsdMayaStageNoticeListener::_UpdateStageContentsChangedRegistration()
TfNotice::Revoke(_stageLayerMutingChangedKey);
}
}

if (_stage && _stageEditTargetChangedCallback) {
// Register for notices if we're not already listening.
if (!_stageEditTargetChangedKey.IsValid()) {
_stageEditTargetChangedKey = TfNotice::Register(
TfCreateWeakPtr(this),
&UsdMayaStageNoticeListener::_OnStageEditTargetChanged,
_stage);
}
} else {
// Either the stage or the callback is invalid, so stop listening for
// notices.
if (_stageEditTargetChangedKey.IsValid()) {
TfNotice::Revoke(_stageEditTargetChangedKey);
}
}
}

void UsdMayaStageNoticeListener::_OnStageContentsChanged(
Expand Down Expand Up @@ -136,4 +160,12 @@ void UsdMayaStageNoticeListener::_OnStageLayerMutingChanged(
}
}

void UsdMayaStageNoticeListener::_OnStageEditTargetChanged(
const UsdNotice::StageEditTargetChanged& notice) const
{
if (notice.GetStage() == _stage && _stageEditTargetChangedCallback) {
_stageEditTargetChangedCallback(notice);
}
}

PXR_NAMESPACE_CLOSE_SCOPE
13 changes: 12 additions & 1 deletion lib/mayaUsd/listeners/stageNoticeListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class UsdMayaStageNoticeListener : public TfWeakBase
= std::function<void(const UsdNotice::ObjectsChanged& notice)>;
using StageLayerMutingChangedCallback
= std::function<void(const UsdNotice::LayerMutingChanged& notice)>;
using StageEditTargetChangedCallback
= std::function<void(const UsdNotice::StageEditTargetChanged& notice)>;

/// Sets the callback to be invoked when the listener receives a
/// StageContentsChanged notice.
Expand All @@ -66,10 +68,15 @@ class UsdMayaStageNoticeListener : public TfWeakBase
void SetStageObjectsChangedCallback(const StageObjectsChangedCallback& callback);

/// Sets the callback to be invoked when the listener receives a
/// ObjectsChanged notice.
/// LayerMutingChanged notice.
MAYAUSD_CORE_PUBLIC
void SetStageLayerMutingChangedCallback(const StageLayerMutingChangedCallback& callback);

/// Sets the callback to be invoked when the listener receives a
/// EditTargetChanged notice.
MAYAUSD_CORE_PUBLIC
void SetStageEditTargetChangedCallback(const StageEditTargetChangedCallback& callback);

private:
UsdMayaStageNoticeListener(const UsdMayaStageNoticeListener&) = delete;
UsdMayaStageNoticeListener& operator=(const UsdMayaStageNoticeListener&) = delete;
Expand All @@ -86,12 +93,16 @@ class UsdMayaStageNoticeListener : public TfWeakBase
TfNotice::Key _stageLayerMutingChangedKey {};
StageLayerMutingChangedCallback _stageLayerMutingChangedCallback {};

TfNotice::Key _stageEditTargetChangedKey {};
StageEditTargetChangedCallback _stageEditTargetChangedCallback {};

void _UpdateStageContentsChangedRegistration();
void _OnStageContentsChanged(const UsdNotice::StageContentsChanged& notice) const;
void _OnStageLayerMutingChanged(const UsdNotice::LayerMutingChanged& notice) const;
void _OnStageObjectsChanged(
const UsdNotice::ObjectsChanged& notice,
const UsdStageWeakPtr& sender) const;
void _OnStageEditTargetChanged(const UsdNotice::StageEditTargetChanged& notice) const;
};

PXR_NAMESPACE_CLOSE_SCOPE
Expand Down
3 changes: 2 additions & 1 deletion lib/mayaUsd/nodes/layerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ void convertAnonymousLayersRecursive(
convertAnonymousLayersRecursive(subL, basename, stage);

if (subL->IsAnonymous()) {
auto newLayer = MayaUsd::utils::saveAnonymousLayer(subL, parentPtr, basename);
auto newLayer
= MayaUsd::utils::saveAnonymousLayer(stage, subL, parentPtr, basename);
if (subL == currentTarget) {
stage->SetEditTarget(newLayer);
}
Expand Down
Loading

0 comments on commit 260cb5a

Please sign in to comment.