Skip to content

Commit

Permalink
Merge pull request #3350 from Autodesk/bailp/EMSUSD-623/multi-maya-re…
Browse files Browse the repository at this point in the history
…fs-in-variants

EMSUSD-623 edit as Maya multiple variants
  • Loading branch information
seando-adsk authored Oct 3, 2023
2 parents 3dff4c1 + 5257879 commit 2779e5c
Show file tree
Hide file tree
Showing 32 changed files with 907 additions and 292 deletions.
303 changes: 189 additions & 114 deletions lib/mayaUsd/fileio/orphanedNodesManager.cpp

Large diffs are not rendered by default.

36 changes: 24 additions & 12 deletions lib/mayaUsd/fileio/orphanedNodesManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ class MAYAUSD_CORE_PUBLIC OrphanedNodesManager : public Ufe::Observer
std::list<VariantSetDescriptor> variantSetDescriptors;
};

using PullVariantInfos = std::vector<PullVariantInfo>;
using PulledPrims = Ufe::Trie<PullVariantInfos>;
using PulledPrimNode = Ufe::TrieNode<PullVariantInfos>;

/// \brief Entire state of the OrphanedNodesManager at a point in time, used for undo/redo.
class MAYAUSD_CORE_PUBLIC Memento
{
Expand All @@ -117,11 +121,11 @@ class MAYAUSD_CORE_PUBLIC OrphanedNodesManager : public Ufe::Observer
// Private, for opacity.
friend class OrphanedNodesManager;

Memento(Ufe::Trie<PullVariantInfo>&& pulledPrims);
Memento(PulledPrims&& pulledPrims);

Ufe::Trie<PullVariantInfo> release();
PulledPrims release();

Ufe::Trie<PullVariantInfo> _pulledPrims;
PulledPrims _pulledPrims;
};

// Construct an empty orphan manager.
Expand All @@ -135,14 +139,17 @@ class MAYAUSD_CORE_PUBLIC OrphanedNodesManager : public Ufe::Observer
// Asserts that the pulled path is not in the trie.
void add(const Ufe::Path& pulledPath, const MDagPath& editedAsMayaRoot);

// Verify if the pulled path and the root of the generated
// Maya nodes to the trie of pulled prims are alredy tracked.
bool has(const Ufe::Path& pulledPath, const MDagPath& editedAsMayaRoot) const;

// Verify if the pulled path with its current variant set is alredy tracked.
bool has(const Ufe::Path& pulledPath) const;

// Remove the pulled path from the trie of pulled prims. Asserts that the
// path is in the trie. Returns a memento (see Memento Pattern) for undo
// 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;
Memento remove(const Ufe::Path& pulledPath, const MDagPath& editedAsMayaRoot);

// Preserve the trie of pulled prims into a memento.
Memento preserve() const;
Expand All @@ -158,19 +165,24 @@ class MAYAUSD_CORE_PUBLIC OrphanedNodesManager : public Ufe::Observer

// Return whether the Dag hierarchy corresponding to the pulled path is
// orphaned.
bool isOrphaned(const Ufe::Path& pulledPath) const;
bool isOrphaned(const Ufe::Path& pulledPath, const MDagPath& editedAsMayaRoot) const;

using PulledPrims = Ufe::Trie<PullVariantInfo>;
using PulledPrimNode = Ufe::TrieNode<PullVariantInfo>;
const PulledPrims& getPulledPrims() const { return _pulledPrims; }

private:
void handleOp(const Ufe::SceneCompositeNotification::Op& op);

static void recursiveSetOrphaned(const PulledPrimNode::Ptr& trieNode, bool orphaned);
static void recursiveSwitch(const PulledPrimNode::Ptr& trieNode, const Ufe::Path& ufePath);
static void recursiveSwitch(
const PulledPrimNode::Ptr& trieNode,
const Ufe::Path& ufePath,
const bool processOrphans);

static bool setOrphaned(const PulledPrimNode::Ptr& trieNode, bool orphaned);
static bool setOrphaned(
const PulledPrimNode::Ptr& trieNode,
const PullVariantInfo& variantInfo,
bool orphaned);

// Member function to access private nested classes.
static std::list<VariantSetDescriptor> variantSetDescriptors(const Ufe::Path& path);
Expand Down
64 changes: 60 additions & 4 deletions lib/mayaUsd/fileio/orphanedNodesManagerIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ namespace {
// ],
// },
// ],
// "more pull info": [
// {
// "editedAsMayaRoot": "DAG-path-of-root-of-generated-Maya-data"
// "variantSetDescriptors": [
// {
// "path": "UFE-path-of-one-ancestor",
// "variantSelections": [
// [ "variant-set-1-name", "variant-set-1-selection" ],
// [ "variant-set-2-name", "variant-set-2-selection" ],
// ],
// },
// ],
// },
// ],
// },
// },
// },
Expand All @@ -59,6 +73,7 @@ namespace {

static const std::string ufeComponentPrefix = "/";
static const std::string pullInfoJsonKey = "pull info";
static const std::string morePullInfoJsonKey = "more pull info";
static const std::string editedAsMayaRootJsonKey = "editedAsMayaRoot";
static const std::string variantSetDescriptorsJsonKey = "variantSetDescriptors";
static const std::string pathJsonKey = "path";
Expand All @@ -74,8 +89,9 @@ using VariantSelection = OrphanedNodesManager::VariantSelection;
using VariantSetDesc = OrphanedNodesManager::VariantSetDescriptor;
using VariantSetDescList = std::list<VariantSetDesc>;
using PullVariantInfo = OrphanedNodesManager::PullVariantInfo;
using PullInfoTrie = Ufe::Trie<PullVariantInfo>;
using PullInfoTrieNode = Ufe::TrieNode<PullVariantInfo>;
using PullVariantInfos = std::vector<PullVariantInfo>;
using PullInfoTrie = OrphanedNodesManager::PulledPrims;
using PullInfoTrieNode = OrphanedNodesManager::PulledPrimNode;
using Memento = OrphanedNodesManager::Memento;

////////////////////////////////////////////////////////////////////////////
Expand All @@ -90,13 +106,15 @@ PXR_NS::JsArray convertToArray(const VariantSelection& variantSel);
PXR_NS::JsObject convertToObject(const VariantSetDesc& variantDesc);
PXR_NS::JsArray convertToArray(const std::list<VariantSetDesc>& allVariantDesc);
PXR_NS::JsObject convertToObject(const PullVariantInfo& pullInfo);
PXR_NS::JsObject convertToObject(const PullVariantInfos& pullInfos);
PXR_NS::JsObject convertToObject(const PullInfoTrieNode::Ptr& pullInfoNode);
PXR_NS::JsObject convertToObject(const PullInfoTrie& allPulledInfo);

VariantSelection convertToVariantSelection(const PXR_NS::JsArray& variantSelJson);
VariantSetDesc convertToVariantSetDescriptor(const PXR_NS::JsObject& variantDescJson);
VariantSetDescList convertToVariantSetDescList(const PXR_NS::JsArray& allVariantDescJson);
PullVariantInfo convertToPullVariantInfo(const PXR_NS::JsObject& pullInfoJson);
PullVariantInfos convertToPullVariantInfos(const PXR_NS::JsObject& pullInfoJson);
void convertToPullInfoTrieNodePtr(const PXR_NS::JsObject&, PullInfoTrieNode::Ptr intoRoot);
PullInfoTrie convertToPullInfoTrie(const PXR_NS::JsObject& allPulledInfoJson);

Expand Down Expand Up @@ -199,6 +217,44 @@ PullVariantInfo convertToPullVariantInfo(const PXR_NS::JsObject& pullInfoJson)
return pullInfo;
}

PXR_NS::JsObject convertToObject(const PullVariantInfos& pullInfos)
{
PXR_NS::JsObject pullInfoJson;

if (pullInfos.size() > 0) {
pullInfoJson = convertToObject(pullInfos[0]);
}

if (pullInfos.size() > 1) {
PXR_NS::JsArray morePullInfoJson;
for (size_t i = 1; i < pullInfos.size(); ++i) {
PXR_NS::JsObject moreInfoJson = convertToObject(pullInfos[i]);
morePullInfoJson.emplace_back(moreInfoJson);
}
pullInfoJson[morePullInfoJsonKey] = morePullInfoJson;
}

return pullInfoJson;
}

PullVariantInfos convertToPullVariantInfos(const PXR_NS::JsObject& pullInfoJson)
{
PullVariantInfos pullInfos;

if (pullInfoJson.count(editedAsMayaRootJsonKey)) {
pullInfos.emplace_back(convertToPullVariantInfo(pullInfoJson));
}

if (pullInfoJson.count(morePullInfoJsonKey)) {
PXR_NS::JsArray morePullInfoJson
= convertToArray(convertJsonKeyToValue(pullInfoJson, morePullInfoJsonKey));
for (const PXR_NS::JsValue& value : morePullInfoJson) {
pullInfos.emplace_back(convertToPullVariantInfo(convertToObject(value)));
}
}
return pullInfos;
}

PXR_NS::JsObject convertToObject(const PullInfoTrieNode::Ptr& pullInfoNodePtr)
{
if (!pullInfoNodePtr)
Expand All @@ -208,7 +264,7 @@ PXR_NS::JsObject convertToObject(const PullInfoTrieNode::Ptr& pullInfoNodePtr)

PXR_NS::JsObject pullInfoNodeJson;

if (pullInfoNode.hasData()) {
if (pullInfoNode.hasData() && pullInfoNode.data().size() > 0) {
pullInfoNodeJson[pullInfoJsonKey] = convertToObject(pullInfoNode.data());
}

Expand All @@ -232,7 +288,7 @@ void convertToPullInfoTrieNodePtr(
if (key.size() <= 0) {
continue;
} else if (key == pullInfoJsonKey) {
intoRoot->setData(convertToPullVariantInfo(convertToObject(value)));
intoRoot->setData(convertToPullVariantInfos(convertToObject(value)));

} else if (key[0] == '/') {
PullInfoTrieNode::Ptr child = std::make_shared<PullInfoTrieNode>(key.substr(1));
Expand Down
72 changes: 41 additions & 31 deletions lib/mayaUsd/fileio/primUpdaterManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,18 @@ SdfPath makeDstPath(const SdfPath& dstRootParentPath, const SdfPath& srcPath)
auto relativeSrcPath = srcPath.MakeRelativePath(SdfPath::AbsoluteRootPath());
return dstRootParentPath.AppendPath(relativeSrcPath);
}
} // namespace

//------------------------------------------------------------------------------
//
// Verify if the given prim under the given UFE path is an ancestor of an already edited prim.
bool hasEditedDescendant(const Ufe::Path& ufeQueryPath)
bool PrimUpdaterManager::hasEditedDescendant(const Ufe::Path& ufeQueryPath) const
{
#ifdef HAS_ORPHANED_NODES_MANAGER
if (_orphanedNodesManager->has(ufeQueryPath))
return true;
#endif

MObject pullSetObj;
auto status = UsdMayaUtil::GetMObjectByName(kPullSetName, pullSetObj);
if (status != MStatus::kSuccess)
Expand All @@ -142,13 +148,23 @@ bool hasEditedDescendant(const Ufe::Path& ufeQueryPath)
if (!readPullInformation(pulledDagPath, pulledUfePath))
continue;

#ifdef HAS_ORPHANED_NODES_MANAGER
// If the alread-edited node is orphaned, don't take it into consideration.
if (_orphanedNodesManager) {
if (_orphanedNodesManager->isOrphaned(pulledUfePath, pulledDagPath)) {
continue;
}
}
#endif

if (pulledUfePath.startsWith(ufeQueryPath))
return true;
}

return false;
}

namespace {
//------------------------------------------------------------------------------
//
// The UFE path is to the pulled prim, and the Dag path is the corresponding
Expand Down Expand Up @@ -198,22 +214,9 @@ bool writeAllPullInformation(const Ufe::Path& ufePulledPath, const MDagPath& edi
//
void removeAllPullInformation(const Ufe::Path& ufePulledPath)
{
UsdPrim pulledPrim = MayaUsd::ufe::ufePathToPrim(ufePulledPath);
UsdStagePtr stage = pulledPrim.GetStage();
if (!stage)
return;

MayaUsd::ProgressBarScope progressBar(1);
removePulledPrimMetadata(stage, pulledPrim);
removePulledPrimMetadata(ufePulledPath);
progressBar.advance();

// Session layer cleanup
auto rootPrims = stage->GetSessionLayer()->GetRootPrims();
MayaUsd::ProgressBarLoopScope rootPrimsLoop(rootPrims.size());
for (const SdfPrimSpecHandle& rootPrimSpec : rootPrims) {
stage->GetSessionLayer()->RemovePrimIfInert(rootPrimSpec);
rootPrimsLoop.loopAdvance();
}
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -865,7 +868,7 @@ class RecordPullVariantInfoUndoItem : public MayaUsd::OpUndoItem

bool undo() override
{
_orphanedNodesManager->remove(_pulledPath);
_orphanedNodesManager->remove(_pulledPath, _editedAsMayaRoot);
return true;
}

Expand All @@ -888,13 +891,14 @@ class RemovePullVariantInfoUndoItem : public MayaUsd::OpUndoItem
// the global undo list.
static bool execute(
const std::shared_ptr<OrphanedNodesManager>& orphanedNodesManager,
const Ufe::Path& pulledPath)
const Ufe::Path& pulledPath,
const MDagPath& editedAsMayaRoot)
{
// Get the global undo list.
auto& undoInfo = OpUndoItemList::instance();

auto item
= std::make_unique<RemovePullVariantInfoUndoItem>(orphanedNodesManager, pulledPath);
auto item = std::make_unique<RemovePullVariantInfoUndoItem>(
orphanedNodesManager, pulledPath, editedAsMayaRoot);
if (!item->redo()) {
return false;
}
Expand All @@ -906,10 +910,12 @@ class RemovePullVariantInfoUndoItem : public MayaUsd::OpUndoItem

RemovePullVariantInfoUndoItem(
const std::shared_ptr<OrphanedNodesManager>& orphanedNodesManager,
const Ufe::Path& pulledPath)
const Ufe::Path& pulledPath,
const MDagPath& editedAsMayaRoot)
: OpUndoItem(std::string("Remove pull path ") + Ufe::PathString::string(pulledPath))
, _orphanedNodesManager(orphanedNodesManager)
, _pulledPath(pulledPath)
, _editedAsMayaRoot(editedAsMayaRoot)
{
}

Expand All @@ -921,13 +927,14 @@ class RemovePullVariantInfoUndoItem : public MayaUsd::OpUndoItem

bool redo() override
{
_memento = _orphanedNodesManager->remove(_pulledPath);
_memento = _orphanedNodesManager->remove(_pulledPath, _editedAsMayaRoot);
return true;
}

private:
const std::shared_ptr<OrphanedNodesManager> _orphanedNodesManager;
const Ufe::Path _pulledPath;
const MDagPath _editedAsMayaRoot;

// Created by redo().
OrphanedNodesManager::Memento _memento;
Expand Down Expand Up @@ -1056,7 +1063,8 @@ bool PrimUpdaterManager::mergeToUsd(
// thinking the Maya data shoudl be shown again...
#ifdef HAS_ORPHANED_NODES_MANAGER
if (_orphanedNodesManager) {
if (!TF_VERIFY(RemovePullVariantInfoUndoItem::execute(_orphanedNodesManager, pulledPath))) {
if (!TF_VERIFY(RemovePullVariantInfoUndoItem::execute(
_orphanedNodesManager, pulledPath, mayaDagPath))) {
return false;
}
}
Expand Down Expand Up @@ -1161,7 +1169,7 @@ bool PrimUpdaterManager::mergeToUsd(
bool PrimUpdaterManager::editAsMaya(const Ufe::Path& path, const VtDictionary& userArgs)
{
if (hasEditedDescendant(path)) {
TF_WARN("Cannot edit an ancestor of an already edited node.");
TF_WARN("Cannot edit an ancestor (%s) of an already edited node.", path.string().c_str());
return false;
}

Expand Down Expand Up @@ -1294,7 +1302,7 @@ bool PrimUpdaterManager::discardEdits(const MDagPath& dagPath)
auto usdPrim = MayaUsd::ufe::ufePathToPrim(pulledPath);

#ifdef HAS_ORPHANED_NODES_MANAGER
auto ret = _orphanedNodesManager->isOrphaned(pulledPath)
auto ret = _orphanedNodesManager->isOrphaned(pulledPath, dagPath)
? discardOrphanedEdits(dagPath, pulledPath)
: discardPrimEdits(pulledPath);
#else
Expand Down Expand Up @@ -1373,7 +1381,8 @@ bool PrimUpdaterManager::discardPrimEdits(const Ufe::Path& pulledPath)

#ifdef HAS_ORPHANED_NODES_MANAGER
if (_orphanedNodesManager) {
if (!TF_VERIFY(RemovePullVariantInfoUndoItem::execute(_orphanedNodesManager, pulledPath))) {
if (!TF_VERIFY(RemovePullVariantInfoUndoItem::execute(
_orphanedNodesManager, pulledPath, mayaDagPath))) {
return false;
}
}
Expand Down Expand Up @@ -1464,7 +1473,8 @@ bool PrimUpdaterManager::discardOrphanedEdits(const MDagPath& dagPath, const Ufe

#ifdef HAS_ORPHANED_NODES_MANAGER
if (_orphanedNodesManager) {
if (!TF_VERIFY(RemovePullVariantInfoUndoItem::execute(_orphanedNodesManager, pulledPath))) {
if (!TF_VERIFY(RemovePullVariantInfoUndoItem::execute(
_orphanedNodesManager, pulledPath, dagPath))) {
return false;
}
}
Expand Down Expand Up @@ -1883,12 +1893,12 @@ PrimUpdaterManager::PulledPrimPaths PrimUpdaterManager::getPulledPrimPaths() con
return pulledPaths;

const OrphanedNodesManager::PulledPrims& pulledPrims = _orphanedNodesManager->getPulledPrims();
MayaUsd::TrieVisitor<OrphanedNodesManager::PullVariantInfo>::visit(
MayaUsd::TrieVisitor<OrphanedNodesManager::PullVariantInfos>::visit(
pulledPrims,
[&pulledPaths](
const Ufe::Path& path,
const Ufe::TrieNode<OrphanedNodesManager::PullVariantInfo>& node) {
pulledPaths.emplace_back(path, node.data().editedAsMayaRoot);
[&pulledPaths](const Ufe::Path& path, const OrphanedNodesManager::PulledPrimNode& node) {
for (const OrphanedNodesManager::PullVariantInfo& info : node.data()) {
pulledPaths.emplace_back(path, info.editedAsMayaRoot);
}
});

#endif
Expand Down
Loading

0 comments on commit 2779e5c

Please sign in to comment.