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

LOOKDEVX-679 - Propagate MatX metadata info #2441

Merged
merged 10 commits into from
Jul 5, 2022

Conversation

JGamache-autodesk
Copy link
Collaborator

  • Add detection code for new USD features that might appear earlier than next Pixar release
  • Show shader parameters at the top of AE
  • Implement grouping in AE if metadata is available
  • Fix missing Ufe types from LOOKDEVX-670
  • Add underscore support to UI label prettification code

- Add detection code for new USD features that might appear earlier than next Pixar release
- Show shader parameters at the top of AE
- Implement grouping in AE if metadata is available
- Fix missing Ufe types from LOOKDEVX-670
- Add underscore support to UI label prettification code

nameTxt = 'nameTxt'
attrValueFld = 'attrValueFld'
attrTypeFld = 'attrTypeFld'

def getPrettyName(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.

Moved to C++ function UsdMayaUtil::prettifyName() exported to Python as mayaUsdLib.Util.prettifyName()

@@ -507,6 +496,46 @@ def sectionNameFromSchema(self, schemaTypeName):

return schemaTypeName

def createShaderAttributesSection(self):
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Move all shader parameters to top of the AE. They used to reside in "Extra Attributes".

@@ -177,7 +177,11 @@ U getUsdAttributeVectorAsUfe(
{
VtValue vt;
if (!attr.isValid() || !attr.hasValue()) {
vt = MayaUsd::ufe::vtValueFromString(attr.typeName(), attr.defaultValue());
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do not crash if there is no default value. And do even report an error. These are problems coming from projects out of the control of Autodesk, so there is not much the end user can do about them.

@@ -335,6 +347,12 @@ namespace ufe {
UsdAttribute::UsdAttribute(const PXR_NS::UsdPrim& prim, const Ufe::AttributeDef::ConstPtr& attrDef)
: fPrim(prim)
, fAttrDef(attrDef)
, fUsdAttr(prim.GetAttribute(PXR_NS::UsdShadeUtils::GetFullName(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As was said in a previous review, the attribute can always be retrieved from the UsdPrim and the attribute name. Put that in application here to have one CTOR for Usd Attribute only, and another one for when we have an Attribute def. As was previously discussed, these two constructors should be in two classes, one derived from the other one, but that will not happen in this PR yet.

@@ -532,14 +550,13 @@ Ufe::Value UsdAttribute::getMetadata(const std::string& key) const
return Ufe::Value(ss.str());
}
}
return Ufe::Value();
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do not return immediately here. There might be information coming from the AttributeDef.

@@ -181,10 +195,10 @@ Ufe::Attribute::Ptr UsdAttributes::attribute(const std::string& name)
const PXR_NS::UsdPrim& prim, \
const Ufe::AttributeDef::ConstPtr& attrDef, \
const PXR_NS::UsdAttribute& usdAttr) { \
if (usdAttr) { \
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The code was assuming that an existing USD attribute would not require an AttributeDef. This is incorrect since there is metadata information we might want to get. Changed to select a CTOR based on the presence of an AttributeDef.

namespace {
typedef std::unordered_map<std::string, std::function<Ufe::Value(const PXR_NS::SdrShaderProperty&)>>
MetadataMap;
static const MetadataMap _metaMap = {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The metadata in USD is using Pixar's metadata nomenclature. This converts it back to MaterialX nomenclature.

@@ -600,6 +600,9 @@ Ufe::Attribute::Type usdTypeToUfe(const PXR_NS::SdrShaderPropertyConstPtr& shade
{ PXR_NS::SdrPropertyTypes->String, PXR_NS::SdfValueTypeNames->String },
{ PXR_NS::SdrPropertyTypes->Float, PXR_NS::SdfValueTypeNames->Float },
{ PXR_NS::SdrPropertyTypes->Color, PXR_NS::SdfValueTypeNames->Color3f },
#if defined(USD_HAS_COLOR4_SDR_SUPPORT)
{ PXR_NS::SdrPropertyTypes->Color4, PXR_NS::SdfValueTypeNames->Color4f },
#endif
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Without that patched USD with Color4 support, a MaterialX color4 will look and act as a Float4.

{ Ufe::Attribute::kFloat3, PXR_NS::SdfValueTypeNames->Float3 }, // GfVec3f
{ Ufe::Attribute::kDouble3, PXR_NS::SdfValueTypeNames->Double3 }, // GfVec3d
{ Ufe::Attribute::kColorFloat3, PXR_NS::SdfValueTypeNames->Color3f }, // GfVec3f
#if (UFE_PREVIEW_VERSION_NUM >= 4015)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated to support new Ufe types.

@@ -722,6 +724,32 @@ std::string UsdMayaUtil::SanitizeName(const std::string& name)
return TfStringReplace(name, ":", "_");
}

std::string UsdMayaUtil::prettifyName(const std::string& 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.

Moved from Python AE template code.

"""Use Sdr node information to populate the shader section"""
shader = UsdShade.Shader(self.prim)
nodeId = shader.GetIdAttr().Get()
if not nodeId:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should any form of error handling be done in these cases?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If we have the shader information we display a nice page. If the definition is missing (or running on an older Maya version without Ufe 4), the attributes end up in the "Extra Attributes" section as they did before.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you show this to Natalia?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes. We found some issues:

  • Float sliders do not align perfectly with color sliders
  • Ordering of attributes in UsdPreviewSurface is alphabetical, which is wrong

One of these will need a fix in Maya, I will investigate the other one.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The default ordering of the UsdPreviewSurface attributes is alphabetical in USD. Nothing can be done in MayaUSD.

@@ -50,5 +50,6 @@ void wrapUtil()
scope s(class_<UsdMayaUtilScope>("Util"));

def("IsAuthored", UsdMayaUtil::IsAuthored);
def("prettifyName", UsdMayaUtil::prettifyName);
Copy link
Collaborator

Choose a reason for hiding this comment

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

(minor) - why is IsAuthored capitalized while prettifyName is lower case?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The coding standards requires CamelCase, I will update the code.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Jerry I believe the way you named yours "lowerCamelCase" is correct and how our coding standard is. The previous function "IsAuthored" came from old Pixar code which is why it has uppercase Is.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes. I rechecked and it is indeed lowerCamelCase.

@@ -335,6 +347,12 @@ namespace ufe {
UsdAttribute::UsdAttribute(const PXR_NS::UsdPrim& prim, const Ufe::AttributeDef::ConstPtr& attrDef)
Copy link
Collaborator

Choose a reason for hiding this comment

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

My recollection was that there were two UsdAttribute constructors, one that takes an attribute and the other that takes a prim and attribute definition. When the prim version is called there shouldn't be an attribute on the prim, no? In which case the GetAttribute(...) code below should fail. Is that not correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No. You can have both an Attribute and an AttributeDef. If that causes the Attribute-only CTOR to be called, then you lose all the rich information the AttributeDef provides.

I either had to add a 3rd CTOR for Attribute+AttributeDef, or simply leverage the fact that you don't even need the attribute to call the Prim+AttributeDef CTOR.

Copy link
Collaborator

Choose a reason for hiding this comment

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

So I had a discussion with Patrick a little while ago about changing the attribute constructor to also take an attribute definition as well (nullptr for the definition if there isn't one). We scheduled work for this with a Jira ticket, but it hasn't been implemented yet. If you wanted to you could make that change.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The more we delay making interface changes that support the code in a more natural, better encapsulated way, with proper separation of concerns, the more we make client code hard to understand, full of unnecessary concepts and dependencies.

@@ -112,6 +112,11 @@ static PXR_NS::UsdAttribute _GetAttributeType(const PXR_NS::UsdPrim& prim, const

Ufe::Attribute::Type UsdAttributes::attributeType(const std::string& name)
{
// early return if name is empty.
if (name.empty()) {
throw std::invalid_argument("Empty name.");
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not really familiar with how MayaUsd exceptions are thrown. Is this enough information, or do you need to somehow include where this is coming from?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

reverted.

{ Ufe::Attribute::kDouble3, PXR_NS::SdfValueTypeNames->Double3 }, // GfVec3d
{ Ufe::Attribute::kColorFloat3, PXR_NS::SdfValueTypeNames->Color3f }, // GfVec3f
#if (UFE_PREVIEW_VERSION_NUM >= 4015)
{ Ufe::Attribute::kFilename, PXR_NS::SdfValueTypeNames->Asset },
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should you have comments equivalent to those above that show the data type? ie. // GfVec3d

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Are these comments adding value in this function?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure, but I would think for consistency they should either be removed or added.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, isn't this a trivial change? If not, by all means ignore this.

Copy link
Collaborator

@ppt-adsk ppt-adsk left a comment

Choose a reason for hiding this comment

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

Just question about error management going from return value to exception.

}

Ufe::Attribute::Ptr UsdAttributes::attribute(const std::string& name)
{
// early return if name is empty.
if (name.empty()) {
return nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

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

We've gone from indicating failure by returning an illegal value to throwing an exception. What motivated the change, and are all call sites capable of dealing with this change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The main Python call site is in UFE itself. It is one that I can actually point to on this public forum since it is installed in Maya.
Look for /runTime/Python/Lib/site-packages/ufe/__init__.py
When passing an empty string, or a name that does not exist, the code in typedAttributeFactory() calls attrs.attributeType(attrName), receives Unknown then complains that this is not found in typedAttributeDict. I found that to be a bit too obscure, hence the exception. I would have preferred KeyError instead of ValueError on the Python side though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I do have to agree that switching error handling on short notice is bug-prone though, so I would have no issue reverting that change.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Since this is code that has no backward compatibility constraints (i.e. it will only work in a future version of Maya), shouldn't we fix the UFE Python binding to more helpfully deal with an empty or unknown attribute 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.

Reverted. I will submit a fix in UFE at a later time.

ppt-adsk
ppt-adsk previously approved these changes Jun 27, 2022
seando-adsk
seando-adsk previously approved these changes Jun 28, 2022
"""Use Sdr node information to populate the shader section"""
shader = UsdShade.Shader(self.prim)
nodeId = shader.GetIdAttr().Get()
if not nodeId:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you show this to Natalia?

seando-adsk
seando-adsk previously approved these changes Jul 5, 2022
@JGamache-autodesk JGamache-autodesk added the ready-for-merge Development process is finished, PR is ready for merge label Jul 5, 2022
@seando-adsk seando-adsk added the ufe-usd Related to UFE-USD plugin in Maya-Usd label Jul 5, 2022
@seando-adsk seando-adsk merged commit e223433 into dev Jul 5, 2022
@seando-adsk seando-adsk deleted the t_gamaj/LOOKDEVX-679/propagate_materialx_metadata branch July 5, 2022 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-for-merge Development process is finished, PR is ready for merge ufe-usd Related to UFE-USD plugin in Maya-Usd
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants