-
Notifications
You must be signed in to change notification settings - Fork 202
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-105175: Rewrote the rename restriction algorithm from scratch to cover more edge cases. #786
Conversation
… cover more edge cases.
//! Returns the layer in composition arc where HasSpecs is set to true | ||
MAYA_USD_UTILS_PUBLIC | ||
std::vector<SdfLayerHandle> layerInCompositionArcsWithSpec(const UsdPrim& prim); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleaned up the usd utility functions. We no longer use them.
UsdPrimCompositionQuery is a nice utility but doesn't deal with SubLayer comp arcs. For the sake of this task, I stopped using it altogether.
commandName.c_str(), | ||
prim.GetName().GetString().c_str(), | ||
layerDisplayName.c_str()); | ||
throw std::runtime_error(err.c_str()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This algorithm heavily relies on using "Prim's PrimStack" rather than "Stage's LayerStack" which makes it much easier to interrogate about the SdfPrimSpec(s) in different composition arcs.
lib/mayaUsd/ufe/private/Utils.cpp
Outdated
if(spec->GetSpecifier() == SdfSpecifierOver && spec->HasReferences()) { | ||
break; | ||
} | ||
|
||
// if the over exist in the session layer | ||
if (spec->GetSpecifier() == SdfSpecifierOver) { | ||
auto sessionLayer = prim.GetStage()->GetSessionLayer(); | ||
if (sessionLayer == spec->GetLayer()){ | ||
layerDisplayName.append("[" + spec->GetLayer()->GetDisplayName() + "]" + ","); | ||
} | ||
} | ||
|
||
// if the def primspec is in another layer other than current stage's local layer. | ||
if (spec->GetSpecifier() == SdfSpecifierDef && primSpec->GetLayer() != spec->GetLayer()) { | ||
layerDisplayName.append("[" + spec->GetLayer()->GetDisplayName() + "]" + ","); | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle different cases around "over" specifier.
…he session layer.
…mSpec will be found and instead USD returns an "over".
if(!parentPrim.IsPseudoRoot()){ | ||
ufe::applyCommandRestriction(childPrim, "reparent"); | ||
ufe::applyCommandRestriction(parentPrim, "reparent"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was unconditionally applying the restriction rules here but realized that If parent prim is the pseudo-root, no def primSpec will be found and instead USD returns the "over".
This case happens when one tries to parent a prim under proxy shape ('/').
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So does that mean there are no restrictions for children of the pseudo-root? That would be surprising! If I have a child of the pseudo-root with opinions on a stronger layer, I shouldn't be able to rename it, no?
lib/mayaUsd/ufe/private/Utils.cpp
Outdated
} | ||
else | ||
|
||
if(!layerDisplayName.empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplified the logic by removing the redundant primSpec check and loop in primStack.
lib/mayaUsd/ufe/private/Utils.cpp
Outdated
if (sessionLayer == spec->GetLayer()){ | ||
layerDisplayName.append("[" + spec->GetLayer()->GetDisplayName() + "]" + ","); | ||
} | ||
layerDisplayName.append("[" + spec->GetLayer()->GetDisplayName() + "]" + ","); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove redundant check to distinguish if the "over" specifier is in the session layer.
- remove unnecessary primSpec->GetLayer() == spec->GetLayer() check - comment clean up
if(!parentPrim.IsPseudoRoot()){ | ||
ufe::applyCommandRestriction(childPrim, "reparent"); | ||
ufe::applyCommandRestriction(parentPrim, "reparent"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So does that mean there are no restrictions for children of the pseudo-root? That would be surprising! If I have a child of the pseudo-root with opinions on a stronger layer, I shouldn't be able to rename it, no?
lib/mayaUsd/ufe/private/Utils.cpp
Outdated
prim.GetName().GetString().c_str(), | ||
layerDisplayNames.c_str()); | ||
throw std::runtime_error(err.c_str()); | ||
// if exists a def sepc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: 'sepc'.
lib/mayaUsd/ufe/private/Utils.cpp
Outdated
} | ||
} | ||
|
||
if(!layerDisplayName.empty()) { | ||
layerDisplayName.pop_back(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the pop_back()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the pop_back is just for make up purposes in the error message. It just removes the last "," in the case where there are multiple layers:
[bob],[foo],
I pop back the last "," so it looks
[bob],[foo]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, you've explained this to me once before... A shortened version of your explanation would make a great code comment.
lib/mayaUsd/ufe/private/Utils.cpp
Outdated
} | ||
else { | ||
// if exist a primSpec with reference | ||
if(spec->HasReferences()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should comment on why we abort the loop here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason for the skipping the reference is to not clash with the over that may be created in the stage's local sessioLayer or other layers.
Consider the case, where we have a stage that has opened a USD file called RefExample.usda and in that file we have
a prim with over which has an external reference to another Usd file called HelloWorld.usda.
RefExample.usda
over "refSphere2" (
prepend references = @./HelloWorld.usda@
)
HelloWorld.usda
#usda 1.0
(
defaultPrim = "hello"
)
def Xform "hello"
{
...........
}
All PrimStack knows at this point is that "refSphere2" has two specs in 2 different places in order from strong to weak:
RefExample.usda ---> over
HelloWorld.usda ---> def
Now in line 161, I unconditionally check if there is an override and then record it's layer name which then results in error message to be displayed which is not desirable:
// if exists an over sepc
if (spec->GetSpecifier() == SdfSpecifierOver) {
layerDisplayName.append("[" + layerName + "]" + ",");
}
one should be able to rename "refSphere2" since it is created in "RefExample.usda" and itself doesn't have any other "over" in the stage's local layers.
This is why I previously had a condition to check if the "over" was created in sessioLayer or not.
Hope this makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does. Can you distill this into a code comment somehow? I know it's a bit challenging, you don't want to have a 2-page code comment, but it would still be nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh yes of course! I was planning to do it after the planning meeting.
commandName.c_str(), | ||
prim.GetName().GetString().c_str(), | ||
prim.GetName().GetString().c_str(), | ||
message.c_str(), | ||
layerDisplayName.c_str()); | ||
throw std::runtime_error(err.c_str()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- polished the algorithm slightly to make it easier to reason about the code and added appropriate comments.
- added proper messaging. we now only need to deal with two messages ( no more fancy words ) :
- Cannot rename something because It is defined on another layer
- Cannot rename something because It has a stronger opinion on another layer
please see 2472eec .
Also ignore my typo in the commit message: I meant "polished" not "published". Sigh..............
_parentLayer = parentPrim.IsPseudoRoot() | ||
? parent->prim().GetStage()->GetEditTarget().GetLayer() | ||
: MayaUsdUtils::defPrimSpecLayer(parentPrim); | ||
_childLayer = childPrim.GetStage()->GetEditTarget().GetLayer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ppt-adsk clean up the legacy old code for getting the appropriate layer for _parentLayer .
ufe::applyCommandRestriction in line 71 and 72 will always put us in a position to use appropriate layer to use for performing the parent operation.
if (prim.IsPseudoRoot()){ | ||
return; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ppt-adsk per out offline discussion, PseudoRoot() is a special case and should be treated differently.
After some thinking, it makes more sense to simply return early if we are dealing with the root layer.
@@ -25,6 +25,8 @@ | |||
|
|||
#include <mayaUsdUtils/util.h> | |||
|
|||
#include <iostream> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just noticed I left out to clean up this iostream. Will have it remove in another PR.
This PR makes a major improvement in the way "Rename" restriction behaves in Maya.