Skip to content

Commit

Permalink
Merge pull request #2764 from Autodesk/bailp/MAYA-126179/merge-into-v…
Browse files Browse the repository at this point in the history
…ariants

MAYA-126179 merge-to-USD into variants
  • Loading branch information
seando-adsk authored Dec 13, 2022
2 parents c37e181 + a2a3d27 commit 6d31923
Show file tree
Hide file tree
Showing 12 changed files with 446 additions and 34 deletions.
18 changes: 15 additions & 3 deletions lib/mayaUsd/fileio/orphanedNodesManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,17 @@ OrphanedNodesManager::Memento OrphanedNodesManager::remove(const Ufe::Path& pull
return oldPulledPrims;
}

const PullVariantInfo& OrphanedNodesManager::get(const Ufe::Path& pulledPath) const
{
const auto infoNode = pulledPrims().find(pulledPath);
if (!infoNode || !infoNode->hasData()) {
static const PullVariantInfo empty;
return empty;
}

return infoNode->data();
}

void OrphanedNodesManager::operator()(const Ufe::Notification& n)
{
const auto& sceneNotification = static_cast<const Ufe::SceneChanged&>(n);
Expand Down Expand Up @@ -521,9 +532,10 @@ void OrphanedNodesManager::recursiveSwitch(
// tree state don't match, the pulled node must be made invisible.
// Inactivation must not be considered, as the USD pulled node is made
// inactive on pull, to avoid rendering it.
const bool variantSetsMatch
= (trieNode->data().variantSetDescriptors == variantSetDescriptors(ufePath.pop()));
const bool orphaned = (pulledNode && !variantSetsMatch);
const auto& originalDesc = trieNode->data().variantSetDescriptors;
const auto currentDesc = variantSetDescriptors(ufePath.pop());
const bool variantSetsMatch = (originalDesc == currentDesc);
const bool orphaned = (pulledNode && !variantSetsMatch);
TF_VERIFY(setOrphaned(trieNode, orphaned));
} else {
const bool isGatewayToUsd = Ufe::SceneSegmentHandler::isGateway(ufePath);
Expand Down
4 changes: 4 additions & 0 deletions lib/mayaUsd/fileio/orphanedNodesManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ class OrphanedNodesManager : public Ufe::Observer
// purposes, to be used as argument to restore().
Memento remove(const Ufe::Path& pulledPath);

// Retrieve the variant information of a pulled prim.
// Returns an empty info if the prim was not tracked by the orphan manager.
const PullVariantInfo& get(const Ufe::Path& pulledPath) const;

// Preserve the trie of pulled prims into a memento.
Memento preserve() const;

Expand Down
39 changes: 23 additions & 16 deletions lib/mayaUsd/fileio/primUpdaterManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -648,11 +648,12 @@ bool pushCustomize(

MayaUsd::ProgressBarScope progressBar(2);

const bool isCopy = context.GetArgs()._copyOperation;
const auto& editTarget = context.GetUsdStage()->GetEditTarget();
auto dstRootPath = editTarget.MapToSpecPath(getDstSdfPath(ufePulledPath, srcRootPath, isCopy));
auto dstRootParentPath = dstRootPath.GetParentPath();
const auto& dstLayer = editTarget.GetLayer();
const bool isCopy = context.GetArgs()._copyOperation;
const UsdEditTarget& editTarget = context.GetUsdStage()->GetEditTarget();
const SdfPath dstPath = getDstSdfPath(ufePulledPath, srcRootPath, isCopy);
const SdfPath dstRootPath = editTarget.MapToSpecPath(dstPath);
const SdfPath dstRootParentPath = dstRootPath.GetParentPath();
const SdfLayerHandle& dstLayer = editTarget.GetLayer();

// Traverse the layer, creating a prim updater for each primSpec
// along the way, and call PushCopySpec on the prim.
Expand Down Expand Up @@ -994,6 +995,20 @@ bool PrimUpdaterManager::mergeToUsd(
scene.notify(Ufe::ObjectPreDelete(ufeMayaItem));
progressBar.advance();

// Remove the pulled path from the orphan node manager *before* exporting
// and merging into the original USD. Otherwise, the orphan manager can
// receive notification mid-way through the merge process, while the variants
// have not all been authored and think the variant set has changed back
// to the correct variant and thus decide to deactivate the USD prim again,
// thinking the Maya data shoudl be shown again...
#ifdef HAS_ORPHANED_NODES_MANAGER
if (_orphanedNodesManager) {
if (!TF_VERIFY(RemovePullVariantInfoUndoItem::execute(_orphanedNodesManager, pulledPath))) {
return false;
}
}
#endif

// Record all USD modifications in an undo block and item.
UsdUndoBlock undoBlock(
&UsdUndoableItemUndoItem::create("Merge to Maya USD data modifications"));
Expand Down Expand Up @@ -1152,7 +1167,9 @@ bool PrimUpdaterManager::editAsMaya(const Ufe::Path& path, const VtDictionary& u
progressBar.advance();

#ifdef HAS_ORPHANED_NODES_MANAGER
RecordPullVariantInfoUndoItem::execute(_orphanedNodesManager, path, importedPaths.first[0]);
if (_orphanedNodesManager) {
RecordPullVariantInfoUndoItem::execute(_orphanedNodesManager, path, importedPaths.first[0]);
}
#endif

if (!updaterArgs._copyOperation) {
Expand Down Expand Up @@ -1696,16 +1713,6 @@ bool PrimUpdaterManager::removePullParent(
return false;
}

#ifdef HAS_ORPHANED_NODES_MANAGER
if (!TF_VERIFY(_orphanedNodesManager)) {
return false;
}

if (!TF_VERIFY(RemovePullVariantInfoUndoItem::execute(_orphanedNodesManager, pulledPath))) {
return false;
}
#endif

MayaUsd::ProgressBarScope progressBar(2);
MStatus status = NodeDeletionUndoItem::deleteNode(
"Delete pull parent node", parentDagPath.fullPathName(), parentDagPath.node());
Expand Down
12 changes: 7 additions & 5 deletions lib/mayaUsd/fileio/utils/orphanedNodesManagerUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <ufe/trie.imp.h>

namespace MAYAUSD_NS_DEF {
namespace utils {

namespace {

Expand Down Expand Up @@ -59,6 +60,8 @@ void toText(std::string& buf, const char* pfix, const Ufe::Path& ufePath, int in
toText(buf, pfix, ufePath.string(), indent, eol);
}

} // namespace

void toText(std::string& buf, const VariantSelection& sel, int indent, bool eol)
{
toText(buf, "Variant ", sel.variantSetName, indent, eol);
Expand Down Expand Up @@ -92,9 +95,7 @@ void toText(std::string& buf, const PullVariantInfo& variantInfo, int indent, bo
toText(buf, "", "}", indent, eol);
}

} // namespace

void orphanedNodesManagerPullInfoToText(
void toText(
std::string& buffer,
const Ufe::TrieNode<PullVariantInfo>::Ptr& trieNode,
int indent,
Expand All @@ -112,7 +113,7 @@ void orphanedNodesManagerPullInfoToText(
}

for (const auto& childComp : node.childrenComponents()) {
orphanedNodesManagerPullInfoToText(buffer, node[childComp], indent + 1, eol);
toText(buffer, node[childComp], indent + 1, eol);
}

if (eol)
Expand All @@ -125,8 +126,9 @@ void printOrphanedNodesManagerPullInfo(
bool eol)
{
std::string buffer("Trie ==========================================\n");
orphanedNodesManagerPullInfoToText(buffer, trieNode, indent, eol);
toText(buffer, trieNode, indent, eol);
MGlobal::displayInfo(buffer.c_str());
}

} // namespace utils
} // namespace MAYAUSD_NS_DEF
22 changes: 21 additions & 1 deletion lib/mayaUsd/fileio/utils/orphanedNodesManagerUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,27 @@
#include <mayaUsd/fileio/orphanedNodesManager.h>

namespace MAYAUSD_NS_DEF {
namespace utils {

void orphanedNodesManagerPullInfoToText(
void toText(
std::string& buf,
const OrphanedNodesManager::VariantSelection& sel,
int indent = 0,
bool eol = true);

void toText(
std::string& buf,
const OrphanedNodesManager::VariantSetDescriptor& descriptor,
int indent = 0,
bool eol = true);

void toText(
std::string& buf,
const OrphanedNodesManager::PullVariantInfo& variantInfo,
int indent,
bool eol);

void toText(
std::string& buffer,
const Ufe::TrieNode<OrphanedNodesManager::PullVariantInfo>::Ptr& trieNode,
int indent = 0,
Expand All @@ -31,4 +50,5 @@ void printOrphanedNodesManagerPullInfo(
int indent = 0,
bool eol = true);

} // namespace utils
} // namespace MAYAUSD_NS_DEF
2 changes: 1 addition & 1 deletion lib/mayaUsd/resources/scripts/mayaUsdMergeToUsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def createMayaReferenceMenuItem(dagPath, precedingItem):
# If the pulled prim doesn't exist anymore, we won't delegate the reponsibility to
# another creator and handle the menu item in here. We already have all the information
# available.
if prim:
if prim and prim.IsDefined():
# If the pulled prim isn't a MayaReference, not our responsibility.
if prim.GetTypeName() != 'MayaReference':
return ''
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/utils/editRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ void copyTransform(
// attribute edits over to the Maya reference prim.
MayaUsdUtils::MergePrimsOptions options;
options.ignoreUpperLayerOpinions = false;
options.ignoreVariants = true;
TF_VERIFY(MayaUsdUtils::mergePrims(
srcStage, srcLayer, srcSdfPath, dstStage, dstLayer, dstSdfPathForMerge, options));
}
Expand Down
4 changes: 2 additions & 2 deletions lib/usd/utils/DiffMetadatas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ std::unordered_set<TfToken, TfToken::HashFunctor>& getIgnoredMetadata()
PXR_NS::SdfFieldKeys->SubLayers, // List of sub-layers names, we should not to deal with this when merging.
PXR_NS::SdfFieldKeys->SubLayerOffsets, // Time offset and scaling for the sub-layers. We treat animation data at the level it is already applied.
PXR_NS::SdfFieldKeys->TypeName, // Property data type. We should not have to copy this over by hand.
PXR_NS::SdfFieldKeys->VariantSetNames, // The merge/copy process will take care of copying the selected variant.
PXR_NS::SdfFieldKeys->VariantSelection, // The merge/copy process will take care of copying the selected variant.
});

// These other build-in metadata are allowed to be compared and merged:
Expand Down Expand Up @@ -92,6 +90,8 @@ std::unordered_set<TfToken, TfToken::HashFunctor>& getIgnoredMetadata()
// SdfFieldKeys->SymmetryFunction, // Property symmetry. (No docs)
// SdfFieldKeys->TimeCodesPerSecond, // Time code per second for playback (TCPS is advisory)
// SdfFieldKeys->Variability, // Control if the property can be animated.
// SdfFieldKeys->VariantSetNames, // The merge/copy process will take care of copying the selected variant.
// SdfFieldKeys->VariantSelection, // The merge/copy process will take care of copying the selected variant.
// clang-format on
return ignored;
}
Expand Down
78 changes: 72 additions & 6 deletions lib/usd/utils/MergePrims.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <pxr/base/tf/stringUtils.h>
#include <pxr/usd/sdf/copyUtils.h>
#include <pxr/usd/usd/editContext.h>
#include <pxr/usd/usd/variantSets.h>
#include <pxr/usd/usdGeom/xformCommonAPI.h>

#include <algorithm>
Expand Down Expand Up @@ -383,8 +384,10 @@ bool isDataAtPathsModified(
{
DiffResult quickDiff = DiffResult::Same;

UsdPrim srcPrim = ctx.srcStage->GetPrimAtPath(src.path.GetPrimPath());
UsdPrim dstPrim = ctx.dstStage->GetPrimAtPath(dst.path.GetPrimPath());
UsdPrim srcPrim
= ctx.srcStage->GetPrimAtPath(src.path.GetPrimPath().StripAllVariantSelections());
UsdPrim dstPrim
= ctx.dstStage->GetPrimAtPath(dst.path.GetPrimPath().StripAllVariantSelections());
if (!srcPrim.IsValid() || !dstPrim.IsValid()) {
printInvalidField(ctx, src, "prim", srcPrim.IsValid(), dstPrim.IsValid());
return srcPrim.IsValid() != dstPrim.IsValid();
Expand Down Expand Up @@ -940,6 +943,57 @@ void createMissingParents(const SdfLayerRefPtr& dstLayer, const SdfPath& dstPath
SdfJustCreatePrimInLayer(dstLayer, dstPath.GetParentPath());
}

//----------------------------------------------------------------------------------------------------------------------
// Augment a USD SdfPath with the variants selections currently active at all levels.
std::pair<SdfPath, UsdEditTarget> augmentPathWithVariants(
const UsdStageRefPtr& stage,
const SdfLayerRefPtr& layer,
const SdfPath& path)
{
SdfPath pathWithVariants;
UsdEditTarget target = stage->GetEditTarget();

SdfPathVector rootToLeaf;
path.GetPrefixes(&rootToLeaf);
for (const SdfPath& prefix : rootToLeaf) {
if (pathWithVariants.IsEmpty()) {
pathWithVariants = prefix;
} else {
pathWithVariants = pathWithVariants.AppendChild(prefix.GetNameToken());
}

const UsdPrim prim = stage->GetPrimAtPath(prefix.StripAllVariantSelections());
if (prim.IsValid()) {
UsdVariantSets variants = prim.GetVariantSets();
for (const std::string& setName : variants.GetNames()) {
UsdVariantSet varSet = variants.GetVariantSet(setName);
pathWithVariants = pathWithVariants.AppendVariantSelection(
varSet.GetName(), varSet.GetVariantSelection());
}
}
}

// Note: any trailing variant selection must be used to create a UsdEditContext,
// it must not be part of the destination path, otherwise SdfCopySpec()
// will fail: it does not handle destination paths ending with a variant
// selection correctly.
//
// If SdfCopySpec() is called with a path ending with a variant selection,
// it assumes that it is inside its own iterations, about to add the
// selection name even though what is about to be added is a prim. So
// The GetParentPath() called in CreateSpec() in usd/sdf/childrenUtils.cpp
// around line 108 will strip the variant selection instead of stripping
// the prim (including variant selection). That will end-up causing an
// error when trying to create a field in SdfData::_GetOrCreateFieldValue
// in usd\sdf\data.cpp around line 260.
if (pathWithVariants.IsPrimVariantSelectionPath()) {
target = target.ForLocalDirectVariant(layer, pathWithVariants);
pathWithVariants = pathWithVariants.GetPrimPath();
}

return std::make_pair(pathWithVariants, target);
}

} // namespace

//----------------------------------------------------------------------------------------------------------------------
Expand All @@ -957,23 +1011,35 @@ bool mergePrims(
const SdfPath& dstPath,
const MergePrimsOptions& options)
{
createMissingParents(dstLayer, dstPath);
SdfPath augmentedDstPath = dstPath;
UsdEditTarget target = dstStage->GetEditTarget();

if (!options.ignoreVariants) {
const auto pathAndTarget = augmentPathWithVariants(dstStage, dstLayer, dstPath);
augmentedDstPath = pathAndTarget.first;
target = pathAndTarget.second;
}

UsdEditContext editCtx(dstStage, target);

createMissingParents(dstLayer, augmentedDstPath);

if (options.ignoreUpperLayerOpinions) {
auto tempStage = UsdStage::CreateInMemory();
SdfLayerHandle tempLayer = tempStage->GetSessionLayer();

tempLayer->TransferContent(dstLayer);

const bool success
= mergeDiffPrims(options, srcStage, srcLayer, srcPath, tempStage, tempLayer, dstPath);
const bool success = mergeDiffPrims(
options, srcStage, srcLayer, srcPath, tempStage, tempLayer, augmentedDstPath);

if (success)
dstLayer->TransferContent(tempLayer);

return success;
} else {
return mergeDiffPrims(options, srcStage, srcLayer, srcPath, dstStage, dstLayer, dstPath);
return mergeDiffPrims(
options, srcStage, srcLayer, srcPath, dstStage, dstLayer, augmentedDstPath);
}
}

Expand Down
4 changes: 4 additions & 0 deletions lib/usd/utils/MergePrimsOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ struct MergePrimsOptions
// if true, merges children too, otherwise merge only the given prim.
bool mergeChildren { false };

// Ignore variants when building the edit target.
// Used when the destination variants have already been set by the caller.
bool ignoreVariants { false };

// If true, the merge is done in a temporary layer so to ignore opinions
// from upper layers (and children of upper layers).
bool ignoreUpperLayerOpinions { false };
Expand Down
Loading

0 comments on commit 6d31923

Please sign in to comment.