From cfa3e29a43243b0a729a417355a833947ae884bb Mon Sep 17 00:00:00 2001 From: Jonathan Feldstein Date: Fri, 2 Sep 2022 15:38:40 -0400 Subject: [PATCH 1/3] LOOKDEVX-571 | Adds support for converting strings with options into enum strings. --- lib/mayaUsd/ufe/UsdAttribute.cpp | 75 +++++++++++++++++++++---- lib/mayaUsd/ufe/UsdAttribute.h | 5 ++ lib/mayaUsd/ufe/UsdAttributes.cpp | 25 +++++---- lib/mayaUsd/ufe/UsdShaderAttributeDef.h | 8 ++- lib/mayaUsd/ufe/Utils.cpp | 14 ++++- test/lib/ufe/testAttribute.py | 38 +++++++++++++ 6 files changed, 142 insertions(+), 23 deletions(-) diff --git a/lib/mayaUsd/ufe/UsdAttribute.cpp b/lib/mayaUsd/ufe/UsdAttribute.cpp index 2207144e2e..49e066dce7 100644 --- a/lib/mayaUsd/ufe/UsdAttribute.cpp +++ b/lib/mayaUsd/ufe/UsdAttribute.cpp @@ -18,9 +18,6 @@ #include "Utils.h" #include "private/Utils.h" -#ifdef UFE_V3_FEATURES_AVAILABLE -#include -#endif #include #include #include @@ -37,6 +34,13 @@ #include #include +#ifdef UFE_V4_FEATURES_AVAILABLE +#include "UsdShaderAttributeDef.h" +#endif +#ifdef UFE_V3_FEATURES_AVAILABLE +#include +#endif + // Note: normally we would use this using directive, but here we cannot because // our class is called UsdAttribute which is exactly the same as the one // in USD. @@ -424,7 +428,17 @@ std::string UsdAttribute::isEditAllowedMsg() const std::string UsdAttribute::typeName() const { if (isValid()) { - return usdTypeToUfe(fUsdAttr.GetTypeName()); +#ifdef UFE_V4_FEATURES_AVAILABLE + UsdShaderAttributeDef::ConstPtr shaderAttrDef + = std::dynamic_pointer_cast(fAttrDef); + if (shaderAttrDef) { + return usdTypeToUfe(shaderAttrDef->shaderProperty()); + } else { +#endif + return usdTypeToUfe(fUsdAttr.GetTypeName()); +#ifdef UFE_V4_FEATURES_AVAILABLE + } +#endif } #ifdef UFE_V4_FEATURES_AVAILABLE else { @@ -864,6 +878,12 @@ Ufe::UndoableCommand::Ptr UsdAttributeFilename::setCmd(const std::string& value) // UsdAttributeEnumString: //------------------------------------------------------------------------------ +bool UsdAttributeEnumString::isHoldingTfToken() const +{ + PXR_NS::VtValue vt; + return UsdAttribute::get(vt, UsdTimeCode::Default()) && vt.IsHolding(); +} + #ifdef UFE_V4_FEATURES_AVAILABLE UsdAttributeEnumString::UsdAttributeEnumString( const UsdSceneItem::Ptr& item, @@ -871,6 +891,7 @@ UsdAttributeEnumString::UsdAttributeEnumString( const Ufe::AttributeDef::ConstPtr& attrDef) : Ufe::AttributeEnumString(item) , UsdAttribute(prim, attrDef) + , _isHoldingTfToken(isHoldingTfToken()) { } #endif @@ -880,6 +901,7 @@ UsdAttributeEnumString::UsdAttributeEnumString( const PXR_NS::UsdAttribute& usdAttr) : Ufe::AttributeEnumString(item) , UsdAttribute(usdAttr) + , _isHoldingTfToken(isHoldingTfToken()) { } @@ -910,9 +932,13 @@ UsdAttributeEnumString::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdA std::string UsdAttributeEnumString::get() const { PXR_NS::VtValue vt; - if (UsdAttribute::get(vt, getCurrentTime(sceneItem())) && vt.IsHolding()) { - TfToken tok = vt.UncheckedGet(); - return tok.GetString(); + if (UsdAttribute::get(vt, getCurrentTime(sceneItem()))) { + if (vt.IsHolding()) { + TfToken tok = vt.UncheckedGet(); + return tok.GetString(); + } else if (vt.IsHolding()) { + return vt.UncheckedGet(); + } } return std::string(); @@ -920,8 +946,12 @@ std::string UsdAttributeEnumString::get() const void UsdAttributeEnumString::set(const std::string& value) { - PXR_NS::TfToken tok(value); - setUsdAttr(*this, tok); + if (_isHoldingTfToken) { + PXR_NS::TfToken tok(value); + setUsdAttr(*this, tok); + } else { + setUsdAttr(*this, value); + } } Ufe::UndoableCommand::Ptr UsdAttributeEnumString::setCmd(const std::string& value) @@ -949,7 +979,25 @@ Ufe::AttributeEnumString::EnumValues UsdAttributeEnumString::getEnumValues() con EnumValues tokens = PXR_NS::TfToStringVector(tokenVec); return tokens; } - +#ifdef UFE_V4_FEATURES_AVAILABLE +#if (UFE_PREVIEW_VERSION_NUM >= 4008) + else { + EnumValues result; + UsdShaderAttributeDef::ConstPtr shaderAttrDef + = std::dynamic_pointer_cast(fAttrDef); + if (shaderAttrDef) { + const auto& shaderProperty = shaderAttrDef->shaderProperty(); + if (shaderProperty) { + const auto& options = shaderProperty->GetOptions(); + for (const auto& option : options) { + result.push_back(option.first.GetString()); + } + } + } + return result; + } +#endif +#endif return EnumValues(); } @@ -1024,6 +1072,13 @@ template <> void TypedUsdAttribute::set(const std::string& value) setUsdAttr(*this, value); return; } else if (typeName == Ufe::Attribute::kEnumString) { + PXR_NS::VtValue vt; + if (UsdAttribute::get(vt, UsdTimeCode::Default())) { + if (vt.IsHolding()) { + setUsdAttr(*this, value); + return; + } + } PXR_NS::TfToken tok(value); setUsdAttr(*this, tok); return; diff --git a/lib/mayaUsd/ufe/UsdAttribute.h b/lib/mayaUsd/ufe/UsdAttribute.h index 12a4e85a6b..a148cb9b8e 100644 --- a/lib/mayaUsd/ufe/UsdAttribute.h +++ b/lib/mayaUsd/ufe/UsdAttribute.h @@ -281,6 +281,11 @@ class UsdAttributeEnumString void set(const std::string& value) override; Ufe::UndoableCommand::Ptr setCmd(const std::string& value) override; EnumValues getEnumValues() const override; + +private: + bool isHoldingTfToken() const; + + const bool _isHoldingTfToken; }; // UsdAttributeEnumString //! \brief Internal helper template class to implement the get/set methods from Ufe::TypeAttribute. diff --git a/lib/mayaUsd/ufe/UsdAttributes.cpp b/lib/mayaUsd/ufe/UsdAttributes.cpp index 03517a6781..32dcfc2c7c 100644 --- a/lib/mayaUsd/ufe/UsdAttributes.cpp +++ b/lib/mayaUsd/ufe/UsdAttributes.cpp @@ -28,6 +28,7 @@ #include #ifdef UFE_V4_FEATURES_AVAILABLE +#include "UsdShaderAttributeDef.h" #if (UFE_PREVIEW_VERSION_NUM >= 4024) #include #endif @@ -124,23 +125,27 @@ Ufe::Attribute::Type UsdAttributes::attributeType(const std::string& name) auto iter = fUsdAttributes.find(name); if (iter != std::end(fUsdAttributes)) return iter->second->type(); - - PXR_NS::TfToken tok(name); - PXR_NS::UsdAttribute usdAttr = _GetAttributeType(fPrim, name); - if (usdAttr.IsValid()) { - return getUfeTypeForAttribute(usdAttr); - } + PXR_NS::TfToken tok(name); #ifdef UFE_V4_FEATURES_AVAILABLE #if (UFE_PREVIEW_VERSION_NUM >= 4008) Ufe::NodeDef::Ptr nodeDef = UsdAttributes::nodeDef(); if (nodeDef) { - Ufe::AttributeDef::ConstPtr attrDef = nameToAttrDef(tok, nodeDef); - if (attrDef) { - return attrDef->type(); + Ufe::AttributeDef::ConstPtr attrDef = nameToAttrDef(tok, nodeDef); + UsdShaderAttributeDef::ConstPtr shaderAttrDef + = std::dynamic_pointer_cast(attrDef); + if (shaderAttrDef) { + const auto& shaderProperty = shaderAttrDef->shaderProperty(); + if (shaderProperty) { + return usdTypeToUfe(shaderProperty); + } } } #endif #endif + PXR_NS::UsdAttribute usdAttr = _GetAttributeType(fPrim, name); + if (usdAttr.IsValid()) { + return getUfeTypeForAttribute(usdAttr); + } return Ufe::Attribute::kInvalid; } @@ -173,7 +178,7 @@ Ufe::Attribute::Ptr UsdAttributes::attribute(const std::string& name) #endif #endif bool canCreateAttribute = usdAttr.IsValid(); - if (usdAttr.IsValid()) { + if (canCreateAttribute) { newAttrType = attributeType(name); } #ifdef UFE_V4_FEATURES_AVAILABLE diff --git a/lib/mayaUsd/ufe/UsdShaderAttributeDef.h b/lib/mayaUsd/ufe/UsdShaderAttributeDef.h index a07c436517..64aa41efb2 100644 --- a/lib/mayaUsd/ufe/UsdShaderAttributeDef.h +++ b/lib/mayaUsd/ufe/UsdShaderAttributeDef.h @@ -28,7 +28,8 @@ namespace ufe { class MAYAUSD_CORE_PUBLIC UsdShaderAttributeDef : public Ufe::AttributeDef { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; + typedef std::shared_ptr ConstPtr; UsdShaderAttributeDef(const PXR_NS::SdrShaderPropertyConstPtr& shaderAttributeDef); ~UsdShaderAttributeDef(); @@ -61,6 +62,11 @@ class MAYAUSD_CORE_PUBLIC UsdShaderAttributeDef : public Ufe::AttributeDef //! Returns true if metadata key has a non-empty value. bool hasMetadata(const std::string& key) const override; + inline const PXR_NS::SdrShaderPropertyConstPtr& shaderProperty() const + { + return fShaderAttributeDef; + } + private: const PXR_NS::SdrShaderPropertyConstPtr fShaderAttributeDef; diff --git a/lib/mayaUsd/ufe/Utils.cpp b/lib/mayaUsd/ufe/Utils.cpp index 22dd88b4a2..9cf0f4551f 100644 --- a/lib/mayaUsd/ufe/Utils.cpp +++ b/lib/mayaUsd/ufe/Utils.cpp @@ -627,7 +627,12 @@ Ufe::Attribute::Type usdTypeToUfe(const PXR_NS::SdrShaderPropertyConstPtr& shade TokenToSdfTypeMap::const_iterator it = tokenTypeToSdfType.find(shaderProperty->GetTypeAsSdfType().second); if (it != tokenTypeToSdfType.end()) { - return usdTypeToUfe(it->second); + Ufe::Attribute::Type type = usdTypeToUfe(it->second); + if (type == Ufe::Attribute::kString && !shaderProperty->GetOptions().empty()) { + return Ufe::Attribute::kEnumString; + } else { + return type; + } } else { #if PXR_VERSION < 2205 // Pre-22.05 boolean inputs are special: @@ -644,7 +649,12 @@ Ufe::Attribute::Type usdTypeToUfe(const PXR_NS::SdrShaderPropertyConstPtr& shade return usdTypeToUfe(PXR_NS::SdfValueTypeNames->Token); } } else { - return usdTypeToUfe(typeName); + Ufe::Attribute::Type type = usdTypeToUfe(typeName); + if (type == Ufe::Attribute::kString && !shaderProperty->GetOptions().empty()) { + return Ufe::Attribute::kEnumString; + } else { + return type; + } } } diff --git a/test/lib/ufe/testAttribute.py b/test/lib/ufe/testAttribute.py index bffacb09d3..e9e0b8d6ce 100644 --- a/test/lib/ufe/testAttribute.py +++ b/test/lib/ufe/testAttribute.py @@ -23,6 +23,7 @@ import usdUtils from pxr import Usd, UsdGeom, Vt, Gf +from pxr import UsdShade from maya import cmds from maya import standalone @@ -419,6 +420,43 @@ def testAttributeEnumString(self): # Run test using Maya's getAttr command. self.runMayaGetAttrTest(ufeAttr) + @unittest.skipIf(os.getenv('USD_HAS_MX_METADATA_SUPPORT', 'NOT-FOUND') not in ('1', "TRUE"), 'Test only available if USD can read MaterialX metadata') + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4001', 'nodeDefHandler is only available in UFE preview version 0.4.1 and greater') + def testAttributeEnumStringToken(self): + '''Test the EnumString attribute type that stores a token instead of a string.''' + + import mayaUsd_createStageWithNewLayer + mayaUsd_createStageWithNewLayer.createStageWithNewLayer() + proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) + proxyShapePath = proxyShapes[0] + stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() + materialPathStr = '/material1' + UsdShade.Material.Define(stage, materialPathStr) + materialPath = ufe.PathString.path(proxyShapePath + ',' + materialPathStr) + materialSceneItem = ufe.Hierarchy.createItem(materialPath) + + runTimeMgr = ufe.RunTimeMgr.instance() + id = runTimeMgr.getId("USD") + nodeDefHandler = runTimeMgr.nodeDefHandler(id) + nodeDef = nodeDefHandler.definition("ND_image_color3") + imageSceneItem = nodeDef.createNode(materialSceneItem, ufe.PathComponent("image1")) + imageAttrs = ufe.Attributes.attributes(imageSceneItem) + uaddressModeAttr = imageAttrs.attribute("inputs:uaddressmode") + + # Compare the initial UFE value to that directly from USD. + self.assertEqual(uaddressModeAttr.get(), 'periodic') + + # Change to 'constant' and verify the return in UFE. + uaddressModeAttr.set('constant') + self.assertEqual(uaddressModeAttr.get(), 'constant') + + uaddressModeEnumValues = uaddressModeAttr.getEnumValues() + self.assertEqual(len(uaddressModeEnumValues), 4) + self.assertTrue('constant' in uaddressModeEnumValues) + self.assertTrue('periodic' in uaddressModeEnumValues) + self.assertTrue('clamp' in uaddressModeEnumValues) + self.assertTrue('mirror' in uaddressModeEnumValues) + def testAttributeBool(self): '''Test the Bool attribute type.''' From f15d8ab218da1b86b27818c4174750c78dcda071 Mon Sep 17 00:00:00 2001 From: Jonathan Feldstein Date: Fri, 9 Sep 2022 13:06:41 -0400 Subject: [PATCH 2/3] LOOKDEVX-571 | Attempt to fix preflight. --- lib/mayaUsd/ufe/UsdAttributes.cpp | 4 +++- test/lib/ufe/testShaderNodeDef.py | 16 ++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/mayaUsd/ufe/UsdAttributes.cpp b/lib/mayaUsd/ufe/UsdAttributes.cpp index 32dcfc2c7c..47230721c0 100644 --- a/lib/mayaUsd/ufe/UsdAttributes.cpp +++ b/lib/mayaUsd/ufe/UsdAttributes.cpp @@ -28,7 +28,9 @@ #include #ifdef UFE_V4_FEATURES_AVAILABLE +#if (UFE_PREVIEW_VERSION_NUM >= 4010) #include "UsdShaderAttributeDef.h" +#endif #if (UFE_PREVIEW_VERSION_NUM >= 4024) #include #endif @@ -127,7 +129,7 @@ Ufe::Attribute::Type UsdAttributes::attributeType(const std::string& name) return iter->second->type(); PXR_NS::TfToken tok(name); #ifdef UFE_V4_FEATURES_AVAILABLE -#if (UFE_PREVIEW_VERSION_NUM >= 4008) +#if (UFE_PREVIEW_VERSION_NUM >= 4010) Ufe::NodeDef::Ptr nodeDef = UsdAttributes::nodeDef(); if (nodeDef) { Ufe::AttributeDef::ConstPtr attrDef = nameToAttrDef(tok, nodeDef); diff --git a/test/lib/ufe/testShaderNodeDef.py b/test/lib/ufe/testShaderNodeDef.py index 5d417dd3cf..ebd33a0f7c 100644 --- a/test/lib/ufe/testShaderNodeDef.py +++ b/test/lib/ufe/testShaderNodeDef.py @@ -117,13 +117,13 @@ def testDefinitionByType(self): self.assertEqual(inputs[3].type(), "Generic") self.assertEqual(inputs[3].defaultValue(), "") self.assertEqual(inputs[4].name(), "uaddressmode") - self.assertEqual(inputs[4].type(), "String") + self.assertEqual(inputs[4].type(), "EnumString") self.assertEqual(inputs[4].defaultValue(), "periodic") - self.assertEqual(inputs[5].name(), "vaddressmode") + self.assertEqual(inputs[5].name(), "Enumvaddressmode") self.assertEqual(inputs[5].type(), "String") self.assertEqual(inputs[5].defaultValue(), "periodic") self.assertEqual(inputs[6].name(), "filtertype") - self.assertEqual(inputs[6].type(), "String") + self.assertEqual(inputs[6].type(), "EnumString") self.assertEqual(inputs[6].defaultValue(), "linear") self.assertEqual(inputs[7].name(), "framerange") self.assertEqual(inputs[7].type(), "String") @@ -132,7 +132,7 @@ def testDefinitionByType(self): self.assertEqual(inputs[8].type(), "Int") self.assertEqual(inputs[8].defaultValue(), "0") self.assertEqual(inputs[9].name(), "frameendaction") - self.assertEqual(inputs[9].type(), "String") + self.assertEqual(inputs[9].type(), "EnumString") self.assertEqual(inputs[9].defaultValue(), "constant") self.assertEqual(len(outputs), 1) self.assertEqual(outputs[0].name(), "out") @@ -161,13 +161,13 @@ def testDefinitionByType(self): self.assertEqual(inputs[3].type(), "Float2") self.assertEqual(inputs[3].defaultValue(), "") self.assertEqual(inputs[4].name(), "uaddressmode") - self.assertEqual(inputs[4].type(), "String") + self.assertEqual(inputs[4].type(), "EnumString") self.assertEqual(inputs[4].defaultValue(), "periodic") self.assertEqual(inputs[5].name(), "vaddressmode") - self.assertEqual(inputs[5].type(), "String") + self.assertEqual(inputs[5].type(), "EnumString") self.assertEqual(inputs[5].defaultValue(), "periodic") self.assertEqual(inputs[6].name(), "filtertype") - self.assertEqual(inputs[6].type(), "String") + self.assertEqual(inputs[6].type(), "EnumString") self.assertEqual(inputs[6].defaultValue(), "linear") self.assertEqual(inputs[7].name(), "framerange") self.assertEqual(inputs[7].type(), "String") @@ -176,7 +176,7 @@ def testDefinitionByType(self): self.assertEqual(inputs[8].type(), "Int") self.assertEqual(inputs[8].defaultValue(), "0") self.assertEqual(inputs[9].name(), "frameendaction") - self.assertEqual(inputs[9].type(), "String") + self.assertEqual(inputs[9].type(), "EnumString") self.assertEqual(inputs[9].defaultValue(), "constant") self.assertEqual(len(outputs), 1) self.assertEqual(outputs[0].name(), "out") From 2d4441617091199df8af7cf60c660dc76bbf34ad Mon Sep 17 00:00:00 2001 From: Jonathan Feldstein Date: Fri, 9 Sep 2022 13:56:41 -0400 Subject: [PATCH 3/3] LOOKDEVX-571 | Another attempt to fix preflight. --- lib/mayaUsd/ufe/UsdAttribute.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/mayaUsd/ufe/UsdAttribute.cpp b/lib/mayaUsd/ufe/UsdAttribute.cpp index 49e066dce7..d67cab7aaa 100644 --- a/lib/mayaUsd/ufe/UsdAttribute.cpp +++ b/lib/mayaUsd/ufe/UsdAttribute.cpp @@ -35,8 +35,10 @@ #include #ifdef UFE_V4_FEATURES_AVAILABLE +#if (UFE_PREVIEW_VERSION_NUM >= 4010) #include "UsdShaderAttributeDef.h" #endif +#endif #ifdef UFE_V3_FEATURES_AVAILABLE #include #endif @@ -429,15 +431,19 @@ std::string UsdAttribute::typeName() const { if (isValid()) { #ifdef UFE_V4_FEATURES_AVAILABLE +#if (UFE_PREVIEW_VERSION_NUM >= 4010) UsdShaderAttributeDef::ConstPtr shaderAttrDef = std::dynamic_pointer_cast(fAttrDef); if (shaderAttrDef) { return usdTypeToUfe(shaderAttrDef->shaderProperty()); } else { +#endif #endif return usdTypeToUfe(fUsdAttr.GetTypeName()); #ifdef UFE_V4_FEATURES_AVAILABLE +#if (UFE_PREVIEW_VERSION_NUM >= 4010) } +#endif #endif } #ifdef UFE_V4_FEATURES_AVAILABLE @@ -980,7 +986,7 @@ Ufe::AttributeEnumString::EnumValues UsdAttributeEnumString::getEnumValues() con return tokens; } #ifdef UFE_V4_FEATURES_AVAILABLE -#if (UFE_PREVIEW_VERSION_NUM >= 4008) +#if (UFE_PREVIEW_VERSION_NUM >= 4010) else { EnumValues result; UsdShaderAttributeDef::ConstPtr shaderAttrDef