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

MAYA-123720 - As a user, I'd like Display Layer membership to survive the 'Edit As Maya Data' workflow #2628

Merged
merged 10 commits into from
Oct 14, 2022
4 changes: 4 additions & 0 deletions lib/mayaUsd/fileio/primUpdaterContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <mayaUsd/base/api.h>
#include <mayaUsd/fileio/primUpdaterArgs.h>
#include <mayaUsd/ufe/Utils.h>

#include <pxr/base/tf/hashmap.h>
#include <pxr/pxr.h>
Expand Down Expand Up @@ -67,6 +68,9 @@ class UsdMayaPrimUpdaterContext
MAYAUSD_CORE_PUBLIC
MDagPath MapSdfPathToDagPath(const SdfPath& sdfPath) const;

mutable MayaUsd::ufe::PullExtras _pullExtras;
mutable MayaUsd::ufe::PushExtras _pushExtras;

private:
const UsdTimeCode& _timeCode;
const UsdStageRefPtr _stage;
Expand Down
16 changes: 14 additions & 2 deletions lib/mayaUsd/fileio/primUpdaterManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@ PullImportPaths pullImport(
Ufe::Path::Segments s { ps, Ufe::PathSegment(v.first, rtid, '/') };
Ufe::Path p(std::move(s));
objToUfePath.insert(ObjToUfePath::value_type(MObjectHandle(v.second), p));

context._pullExtras.processItem(p, v.second);
}
progressBar.advance();

Expand Down Expand Up @@ -631,6 +633,7 @@ PushCustomizeSrc pushExport(
auto usdPathToDagPathMap = std::make_shared<UsdPathToDagPathMap>();
for (const auto& v : writeJob.GetDagPathToUsdPathMap()) {
usdPathToDagPathMap->insert(UsdPathToDagPathMap::value_type(v.second, v.first));
context._pushExtras.processItem(v.first, v.second);
}

std::get<UsdPathToDagPathMapPtr>(pushCustomizeSrc) = usdPathToDagPathMap;
Expand Down Expand Up @@ -883,7 +886,7 @@ bool PrimUpdaterManager::mergeToUsd(
MString progStr(
VtDictionaryIsHolding<std::string>(userArgs, "rn_primName") ? "Caching to USD"
: "Merging to USD");
MayaUsd::ProgressBarScope progressBar(9, progStr);
MayaUsd::ProgressBarScope progressBar(10, progStr);
PushPullScope scopeIt(_inPushPull);

auto ctxArgs = VtDictionaryOver(userArgs, UsdMayaJobExportArgs::GetDefaultDictionary());
Expand Down Expand Up @@ -1020,6 +1023,9 @@ bool PrimUpdaterManager::mergeToUsd(
}
progressBar.advance();

context._pushExtras.finalize(MayaUsd::ufe::stagePath(context.GetUsdStage()));
progressBar.advance();

discardPullSetIfEmpty();

// Some updaters (like MayaReference) may be writing and changing the variant during merge.
Expand Down Expand Up @@ -1070,6 +1076,7 @@ bool PrimUpdaterManager::editAsMaya(const Ufe::Path& path, const VtDictionary& u

auto& scene = Ufe::Scene::instance();
auto ufeItem = Ufe::Hierarchy::createItem(path);
context._pullExtras.initRecursive(ufeItem);
if (!updaterArgs._copyOperation && TF_VERIFY(ufeItem))
scene.notify(Ufe::ObjectPreDelete(ufeItem));

Expand Down Expand Up @@ -1363,6 +1370,7 @@ bool PrimUpdaterManager::duplicate(

UsdMayaPrimUpdaterContext context(
srcProxyShape->getTime(), srcProxyShape->getUsdStage(), ctxArgs);
context._pullExtras.initRecursive(Ufe::Hierarchy::createItem(srcPath));
progressBar.advance();

pullImport(srcPath, srcPrim, context);
Expand All @@ -1377,7 +1385,7 @@ bool PrimUpdaterManager::duplicate(
return false;
}

MayaUsd::ProgressBarScope progressBar(6, "Duplicating to USD");
MayaUsd::ProgressBarScope progressBar(7, "Duplicating to USD");

auto ctxArgs = VtDictionaryOver(userArgs, UsdMayaJobExportArgs::GetDefaultDictionary());

Expand Down Expand Up @@ -1423,6 +1431,10 @@ bool PrimUpdaterManager::duplicate(
}
progressBar.advance();

std::string* rootRename = (dstChildName != srcRootPath.GetName()) ? &dstChildName : nullptr;
context._pushExtras.finalize(MayaUsd::ufe::stagePath(context.GetUsdStage()), rootRename);
progressBar.advance();

auto ufeItem = Ufe::Hierarchy::createItem(dstPath);
if (TF_VERIFY(ufeItem)) {
Ufe::Scene::instance().notify(Ufe::SubtreeInvalidate(ufeItem));
Expand Down
10 changes: 7 additions & 3 deletions lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,16 +818,20 @@ void ProxyRenderDelegate::_DirtyUsdSubtree(const UsdPrim& prim)
| HdChangeTracker::DirtyDisplayStyle | MayaUsdRPrim::DirtySelectionHighlight
| HdChangeTracker::DirtyMaterialId;

if (prim.IsA<UsdGeomGprim>()) {
if (prim.IsA<UsdGeomGprim>() && prim.IsActive()) {
auto indexPath = _sceneDelegate->ConvertCachePathToIndexPath(prim.GetPath());
changeTracker.MarkRprimDirty(indexPath, dirtyBits);
if (_renderIndex->HasRprim(indexPath)) {
changeTracker.MarkRprimDirty(indexPath, dirtyBits);
}
}

UsdPrimSubtreeRange range = prim.GetDescendants();
for (auto iter = range.begin(); iter != range.end(); ++iter) {
if (iter->IsA<UsdGeomGprim>()) {
auto indexPath = _sceneDelegate->ConvertCachePathToIndexPath(iter->GetPath());
changeTracker.MarkRprimDirty(indexPath, dirtyBits);
if (_renderIndex->HasRprim(indexPath)) {
changeTracker.MarkRprimDirty(indexPath, dirtyBits);
}
}
}
}
Expand Down
96 changes: 96 additions & 0 deletions lib/mayaUsd/ufe/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
#include <pxr/usd/usdGeom/tokens.h>
#include <pxr/usdImaging/usdImaging/delegate.h>

#ifdef MAYA_HAS_DISPLAY_LAYER_API
#include <maya/MFnDisplayLayer.h>
#include <maya/MFnDisplayLayerManager.h>
#endif

#include <maya/MFnDependencyNode.h>
#include <maya/MGlobal.h>
#include <maya/MObjectHandle.h>
Expand Down Expand Up @@ -895,5 +900,96 @@ std::vector<std::string> splitString(const std::string& str, const std::string&
return split;
}

void PullExtras::initRecursive(Ufe::SceneItem::Ptr ufeItem)
{
auto node = Ufe::Hierarchy::hierarchy(ufeItem);
if (!node) {
return;
}

// Go through the entire hierarchy
for (auto child : node->children()) {
initRecursive(child);
}

#ifdef MAYA_HAS_DISPLAY_LAYER_API
// Prepare _displayLayerMap
MFnDisplayLayerManager displayLayerManager(
MFnDisplayLayerManager::currentDisplayLayerManager());

MObject displayLayerObj
= displayLayerManager.getLayer(Ufe::PathString::string(ufeItem->path()).c_str());
if (displayLayerObj.hasFn(MFn::kDisplayLayer)) {
MFnDisplayLayer displayLayer(displayLayerObj);
if (displayLayer.name() != "defaultLayer") {
_displayLayerMap[ufeItem->path()] = displayLayerObj;
}
}
#endif
}

void PullExtras::processItem(const Ufe::Path& path, const MObject& mayaObject)
{
#ifdef MAYA_HAS_DISPLAY_LAYER_API
// Replicate display layer membership
auto it = _displayLayerMap.find(path);
if (it != _displayLayerMap.end() && it->second.hasFn(MFn::kDisplayLayer)) {
MDagPath dagPath;
if (MDagPath::getAPathTo(mayaObject, dagPath) == MStatus::kSuccess) {
MFnDisplayLayer displayLayer(it->second);
displayLayer.add(dagPath);

// In case display layer membership was removed from the USD prim that we are
// replicating, we want to restore it here to make sure that the prim will stay in its
// display layer on DiscardEdits
displayLayer.add(Ufe::PathString::string(path).c_str());
}
}
#endif
}

void PushExtras::processItem(const MDagPath& dagPath, const SdfPath& usdPath)
{
#ifdef MAYA_HAS_DISPLAY_LAYER_API
// Populate display layer membership map

// Since multiple dag paths may lead to a single USD path (like transform and node),
// we have to make sure we don't overwrite a non-default layer with a default one
bool displayLayerAssigned = false;
auto entry = _primToLayerMap.find(usdPath);
if (entry != _primToLayerMap.end() && entry->second.hasFn(MFn::kDisplayLayer)) {
MFnDisplayLayer displayLayer(entry->second);
displayLayerAssigned = (displayLayer.name() != "defaultLayer");
}

if (!displayLayerAssigned) {
MFnDisplayLayerManager displayLayerManager(
MFnDisplayLayerManager::currentDisplayLayerManager());
_primToLayerMap[usdPath] = displayLayerManager.getLayer(dagPath);
}
#endif
}

void PushExtras::finalize(const Ufe::Path& stagePath, const std::string* renameRoot)
{
#ifdef MAYA_HAS_DISPLAY_LAYER_API
// Replicate display layer membership
for (const auto& entry : _primToLayerMap) {
if (entry.second.hasFn(MFn::kDisplayLayer)) {
auto rootPath = MayaUsd::ufe::usdPathToUfePathSegment(entry.first);
if (renameRoot && !rootPath.empty()) {
*rootPath.begin() = Ufe::PathComponent(*renameRoot);
}

Ufe::Path::Segments segments { stagePath.getSegments()[0], rootPath };
Ufe::Path ufePath(std::move(segments));

MFnDisplayLayer displayLayer(entry.second);
displayLayer.add(Ufe::PathString::string(ufePath).c_str());
}
}
#endif
}

} // namespace ufe
} // namespace MAYAUSD_NS_DEF
20 changes: 20 additions & 0 deletions lib/mayaUsd/ufe/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,5 +231,25 @@ Ufe::Selection recreateDescendants(const Ufe::Selection& src, const Ufe::Path& f
MAYAUSD_CORE_PUBLIC
std::vector<std::string> splitString(const std::string& str, const std::string& separators);

class PullExtras
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need two different classes? How about a single class that can handle both cases (Maya->USD and USD->Maya). Just have two sections of methods for each case. And I guess you were thinking that in the future we could add other types of extras (now we have DisplayLayers)? The names "Pull/Push" are specific to your operation, but we'll add this for duplicate usd prim. Can we have a generic name?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@seando-adsk The two classes share neither data members nor methods, so I don't see a reason to merge them. As for renaming, would ReplicateExtrasToUSD/ReplicateExtrasFromUSD wouldwork for you?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes those names are better.

{
public:
void initRecursive(Ufe::SceneItem::Ptr);
void processItem(const Ufe::Path& path, const MObject& mayaObject);
Copy link
Collaborator

Choose a reason for hiding this comment

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

These methods need comments as to what they are doing.


private:
std::unordered_map<Ufe::Path, MObject> _displayLayerMap;
};

class PushExtras
{
public:
void processItem(const MDagPath& dagPath, const PXR_NS::SdfPath& usdPath);
void finalize(const Ufe::Path& stagePath, const std::string* renameRoot = nullptr);

private:
std::map<PXR_NS::SdfPath, MObject> _primToLayerMap;
};

} // namespace ufe
} // namespace MAYAUSD_NS_DEF