Skip to content

Commit

Permalink
MAYA-127770 missing discard edits
Browse files Browse the repository at this point in the history
After editing-as-Maya and then deleting teh stage, the menu for discard edit would not show up or would do nothing. Fix this by correctly updating the pulled information on the Maya node.

- Correctly compute the new pulled path in the case where the stage proxy node no longer exists.
- This happens because as part of deletion, Maya reparents child nodes before deleting them.
- Refactor some common code to extract the list of UFE components from a trie node full path.
  • Loading branch information
pierrebai-adsk committed Jun 13, 2023
1 parent c0f2d9d commit d02d2ec
Showing 1 changed file with 50 additions and 17 deletions.
67 changes: 50 additions & 17 deletions lib/mayaUsd/fileio/orphanedNodesManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@ using PullVariantInfo = OrphanedNodesManager::PullVariantInfo;
using VariantSetDescriptor = OrphanedNodesManager::VariantSetDescriptor;
using VariantSelection = OrphanedNodesManager::VariantSelection;
using PulledPrims = OrphanedNodesManager::PulledPrims;
using PulledPrimNode = OrphanedNodesManager::PulledPrimNode;
using PulledPrimNode = Ufe::TrieNode<PullVariantInfo>;

Ufe::Path trieNodeToPulledPrimUfePath(PulledPrimNode::Ptr trieNode);
Ufe::PathSegment::Components trieNodeToPathComponents(PulledPrimNode::Ptr trieNode);
Ufe::Path trieNodeToPulledPrimUfePath(PulledPrimNode::Ptr trieNode);

void renameVariantDescriptors(
std::list<VariantSetDescriptor>& descriptors,
Expand All @@ -103,25 +104,55 @@ void renameVariantInfo(
// data we must make a copy, modify the copy and call setData().
PullVariantInfo newVariantInfo = trieNode->data();

// Note: the change to USD data must be done *after* changes to Maya data because
// the outliner reacts to UFE notifications received following the USD edits
// to rebuild the node tree and the Maya node we want to hide must have been
// hidden by that point. So the node visibility change must be done *first*.
renameVariantDescriptors(newVariantInfo.variantSetDescriptors, oldPath, newPath);

Ufe::Path pulledPath = trieNodeToPulledPrimUfePath(trieNode);
TF_VERIFY(writePullInformation(pulledPath, newVariantInfo.editedAsMayaRoot));

trieNode->setData(newVariantInfo);
}

void renamePullInformation(
const PulledPrimNode::Ptr& trieNode,
const Ufe::Path& oldPath,
const Ufe::Path& newPath)
{
// Note: the trie only contains UFE path components, no UFE segments.
// So we can't build a correct UFE path with the correct run-time ID
// and the correct separators.
//
// The old and new UFE paths do contain the correct run-time ID. So
// we use them to build the correct UFE path to write the new pulled
// information. Note that we *cannot* rely on the proxy shape existing
// because we're sometimes called after it has been deleted. The reason
// is that when Maya deletes a node, it temporarily reparents its children
// to the Maya world root. This is the context in which we're sometimes
// being called. Very confusing and unfortunate.
//
// In all cases, we're being called about the proxy shape node being
// reparented, so we just assume that the new path ends at the transition
// between the Maya run-time and the USD run-time.
Ufe::Path pulledPath = newPath;

const Ufe::PathSegment::Components pathComponents = trieNodeToPathComponents(trieNode);
for (size_t i = newPath.size(); i < pathComponents.size(); ++i) {
const Ufe::PathComponent& comp = pathComponents[i];
if (pulledPath.nbSegments() < 2) {
pulledPath = pulledPath + Ufe::PathSegment(comp, ufe::getUsdRunTimeId(), '/');
} else {
pulledPath = pulledPath + comp;
}
}

const MDagPath& mayaPath = trieNode->data().editedAsMayaRoot;
TF_VERIFY(writePullInformation(pulledPath, mayaPath));
}

void recursiveRename(
const PulledPrimNode::Ptr& trieNode,
const Ufe::Path& oldPath,
const Ufe::Path& newPath)
{
if (trieNode->hasData()) {
renameVariantInfo(trieNode, oldPath, newPath);
renamePullInformation(trieNode, oldPath, newPath);
} else {
auto childrenComponents = trieNode->childrenComponents();
for (auto& c : childrenComponents) {
Expand Down Expand Up @@ -413,11 +444,10 @@ bool OrphanedNodesManager::isOrphaned(const Ufe::Path& pulledPath) const

namespace {

Ufe::Path
trieNodeToPulledPrimUfePath(Ufe::TrieNode<OrphanedNodesManager::PullVariantInfo>::Ptr trieNode)
Ufe::PathSegment::Components trieNodeToPathComponents(PulledPrimNode::Ptr trieNode)
{
// Accumulate all UFE path components, in reverse order. We will pop them
// from the back while building the pulled prim path.
// Accumulate all UFE path components, in reverse order. We then reverse
// the order to get the true path order.
//
// Note: the trie root node is not really part of the hierarchy, so do not
// include it in the components. We detect we are at the root when
Expand All @@ -427,16 +457,19 @@ trieNodeToPulledPrimUfePath(Ufe::TrieNode<OrphanedNodesManager::PullVariantInfo>
pathComponents.push_back(trieNode->component());
trieNode = trieNode->parent();
}
std::reverse(pathComponents.begin(), pathComponents.end());
return pathComponents;
}

Ufe::Path trieNodeToPulledPrimUfePath(PulledPrimNode::Ptr trieNode)
{
// We assume the prim path is comosed of two segments: one in Maya, up to the
// stage proxy shape, then in USD.
Ufe::Path primPath;
bool foundStage = false;

while (pathComponents.size() > 0) {
Ufe::PathComponent comp = pathComponents.back();
pathComponents.pop_back();

const Ufe::PathSegment::Components pathComponents = trieNodeToPathComponents(trieNode);
for (const Ufe::PathComponent& comp : pathComponents) {
// If the path is empty, it means we are starting the Maya path, so create
// a Maya UFE segment.
//
Expand Down

0 comments on commit d02d2ec

Please sign in to comment.