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

Hide orphaned pulled nodes on ancestor structure change. #2576

Merged
merged 8 commits into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
315 changes: 302 additions & 13 deletions lib/mayaUsd/fileio/primUpdaterManager.cpp

Large diffs are not rendered by default.

106 changes: 103 additions & 3 deletions lib/mayaUsd/fileio/primUpdaterManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
#include <pxr/pxr.h>
#include <pxr/usd/sdf/path.h>

#include <maya/MApiNamespace.h>
#include <maya/MCallbackIdArray.h>
#include <maya/MDagPath.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MObject.h>
#include <ufe/observer.h>
#include <ufe/path.h>
#include <ufe/sceneItem.h>
#include <ufe/sceneNotification.h>
#include <ufe/trie.h>

PXR_NAMESPACE_OPEN_SCOPE

Expand Down Expand Up @@ -78,6 +80,53 @@ class PrimUpdaterManager : public PXR_NS::TfWeakBase
bool hasPulledPrims() const { return _hasPulledPrims; }

private:
struct VariantSelection
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To detect when a change in variant should hide or show a pulled hierarchy, we save the complete list of variant sets and their variant selection along the ancestor chain. If this variant configuration matches, we show the pulled hierarchy, if it doesn't, we hide the pulled hierarchy. We cannot rely only on the path, because the path may be identical in two different variants, e.g. all variants of a cup might have a top-level prim called "Cup", so that the path to the selected variant is the same.

{
VariantSelection() = default;
VariantSelection(const std::string& vsn, const std::string& vs)
: variantSetName(vsn)
, variantSelection(vs)
{
}
bool operator==(const VariantSelection& rhs) const
{
return (variantSetName == rhs.variantSetName)
&& (variantSelection == rhs.variantSelection);
}

std::string variantSetName;
std::string variantSelection;
};

struct VariantSetDescriptor
{
VariantSetDescriptor() = default;
VariantSetDescriptor(const Ufe::Path& p, const std::list<VariantSelection>& vs)
: path(p)
, variantSelections(vs)
{
}
bool operator==(const VariantSetDescriptor& rhs) const
{
return (path == rhs.path) && (variantSelections == rhs.variantSelections);
}

Ufe::Path path;
std::list<VariantSelection> variantSelections;
};

struct PullVariantInfo
{
PullVariantInfo() = default;
PullVariantInfo(const MDagPath& dp, const std::list<VariantSetDescriptor>& vsd)
: dagPath(dp)
, variantSetDescriptors(vsd)
{
}
MDagPath dagPath;
std::list<VariantSetDescriptor> variantSetDescriptors;
};

PrimUpdaterManager();

PrimUpdaterManager(PrimUpdaterManager&) = delete;
Expand All @@ -90,7 +139,8 @@ class PrimUpdaterManager : public PXR_NS::TfWeakBase
void onProxyContentChanged(const MayaUsdProxyStageObjectsChangedNotice& notice);

//! Ensure the Dag pull root exists. This is the child of the Maya world
//! node under which all pulled nodes are created.
//! node under which all pulled nodes are created. Complexity is O(n) for
//! n children of the Maya world node.
MObject findOrCreatePullRoot();

//! Create the pull parent for the pulled hierarchy. This is the node
Expand All @@ -103,14 +153,64 @@ class PrimUpdaterManager : public PXR_NS::TfWeakBase
//! Create the pull parent and set it into the prim updater context.
MDagPath setupPullParent(const Ufe::Path& pulledPath, VtDictionary& args);

//! Record pull information for the pulled path, for inspection on
//! scene changes.
void recordPullVariantInfo(const Ufe::Path& pulledPath, const MDagPath& pullParentPath);

// Maya file new or open callback. Member function to access other private
// member functions.
static void beforeNewOrOpenCallback(void* clientData);

void beginManagePulledPrims();
void endManagePulledPrims();

// Member function to access private nested classes.
static std::list<VariantSetDescriptor> variantSetDescriptors(const Ufe::Path& path);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: having a class named VariantSetDescriptors and a function named variantSetDescriptors is a bit confusing. Maybe a "get"or "compute" prefix on the function?


friend class TfSingleton<PrimUpdaterManager>;

class OrphanedNodesManager : public Ufe::Observer
{
public:
OrphanedNodesManager(const Ufe::Trie<PullVariantInfo>& pulledPrims);

void operator()(const Ufe::Notification&) override;

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

static void recursiveSetVisibility(
const Ufe::TrieNode<PullVariantInfo>::Ptr& trieNode,
bool visibility);
static void recursiveSwitch(
const Ufe::TrieNode<PullVariantInfo>::Ptr& trieNode,
const Ufe::Path& ufePath);

static bool
setVisibilityPlug(const Ufe::TrieNode<PullVariantInfo>::Ptr& trieNode, bool visibility);

const Ufe::Trie<PullVariantInfo>& _pulledPrims;
};

bool _inPushPull { false };

// Becomes true when there is at least one pulled prim.
// The goal is to let code that can be optimized when there is no pull prim
// to check rapidly.
bool _hasPulledPrims { false };

// Trie for fast lookup of descendant pulled prims. The Trie key is the
// UFE pulled path, and the Trie value is the corresponding Dag pull parent
// and all ancestor variant set selections.
Ufe::Trie<PullVariantInfo> _pulledPrims {};

// Orphaned nodes manager that observes the scene, to determine when to hide
// pulled prims that have become orphaned, or to show them again, because
// of structural changes to their USD or Maya ancestors.
Ufe::Observer::Ptr _orphanedNodesManager {};

// Maya scene observation, to stop UFE scene observation.
MCallbackIdArray _fileCbs;
};

PXR_NAMESPACE_CLOSE_SCOPE
Expand Down
1 change: 1 addition & 0 deletions test/lib/mayaUsd/fileio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ if(CMAKE_UFE_V3_FEATURES_AVAILABLE)
testPrimUpdater.py
testCacheToUsd.py
testMayaUsdOptions.py
testHideOrphanedNodes.py
)
endif()

Expand Down
Loading