From 4f34c98259da09542763822103f5f525fa985c0d Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Wed, 18 May 2022 16:03:20 -0400 Subject: [PATCH 1/4] LOOKDEVX-670 Improved USD type support We added new types in Ufe 0.4.15. This updates maps them to their corresponding USD types. --- lib/mayaUsd/ufe/UsdAttribute.cpp | 273 +++++++++++++++- lib/mayaUsd/ufe/UsdAttribute.h | 97 ++++++ lib/mayaUsd/ufe/UsdAttributes.cpp | 67 ++-- lib/mayaUsd/ufe/UsdShaderAttributeDef.cpp | 13 +- lib/mayaUsd/ufe/Utils.cpp | 46 +-- test/lib/ufe/testAttribute.py | 303 +++++++++++++++++- test/lib/ufe/testShaderNodeDef.py | 45 +++ .../testSamples/MaterialX/MtlxValueTypes.usda | 184 +++++++++++ test/testUtils/testUtils.py | 5 + 9 files changed, 971 insertions(+), 62 deletions(-) create mode 100644 test/testSamples/MaterialX/MtlxValueTypes.usda diff --git a/lib/mayaUsd/ufe/UsdAttribute.cpp b/lib/mayaUsd/ufe/UsdAttribute.cpp index 0802c24e71..3431acb7f6 100644 --- a/lib/mayaUsd/ufe/UsdAttribute.cpp +++ b/lib/mayaUsd/ufe/UsdAttribute.cpp @@ -177,8 +177,10 @@ U getUsdAttributeVectorAsUfe(const PXR_NS::UsdAttribute& attr, const PXR_NS::Usd PXR_NS::VtValue vt; if (attr.Get(&vt, time) && vt.IsHolding()) { - T gfVec = vt.UncheckedGet(); - U ret(gfVec[0], gfVec[1], gfVec[2]); + T gfVec = vt.UncheckedGet(); + U ret; + constexpr size_t num = ret.vector.size(); + std::copy(gfVec.data(), gfVec.data() + num, ret.vector.data()); return ret; } @@ -192,10 +194,74 @@ void setUsdAttributeVectorFromUfe( const PXR_NS::UsdTimeCode& time) { T vec; - vec.Set(value.x(), value.y(), value.z()); + std::copy(value.vector.data(), value.vector.data() + value.vector.size(), vec.data()); + setUsdAttr(attr, vec); +} + +template +U getUsdAttributeColorAsUfe(const PXR_NS::UsdAttribute& attr, const PXR_NS::UsdTimeCode& time) +{ + if (!attr.IsValid() || !attr.HasValue()) + return U(); + + PXR_NS::VtValue vt; + if (attr.Get(&vt, time) && vt.IsHolding()) { + T gfVec = vt.UncheckedGet(); + U ret; + std::copy(gfVec.data(), gfVec.data() + ret.color.size(), ret.color.data()); + return ret; + } + + return U(); +} + +template +void setUsdAttributeColorFromUfe( + PXR_NS::UsdAttribute& attr, + const U& value, + const PXR_NS::UsdTimeCode& time) +{ + T vec; + std::copy(value.color.data(), value.color.data() + value.color.size(), vec.data()); setUsdAttr(attr, vec); } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +template +U getUsdAttributeMatrixAsUfe(const PXR_NS::UsdAttribute& attr, const PXR_NS::UsdTimeCode& time) +{ + if (!attr.IsValid() || !attr.HasValue()) + return U(); + + PXR_NS::VtValue vt; + if (attr.Get(&vt, time) && vt.IsHolding()) { + T gfMat = vt.UncheckedGet(); + U ret; + std::copy( + gfMat.data(), + gfMat.data() + ret.matrix.size() * ret.matrix.size(), + ret.matrix[0].data()); + return ret; + } + + return U(); +} + +template +void setUsdAttributeMatrixFromUfe( + PXR_NS::UsdAttribute& attr, + const U& value, + const PXR_NS::UsdTimeCode& time) +{ + T mat; + std::copy( + value.matrix[0].data(), + value.matrix[0].data() + value.matrix.size() * value.matrix.size(), + mat.data()); + setUsdAttr(attr, mat); +} +#endif + class UsdUndoableCommand : public Ufe::UndoableCommand { public: @@ -384,6 +450,64 @@ std::string UsdAttributeGeneric::nativeType() const return fUsdAttr.GetTypeName().GetType().GetTypeName(); } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//------------------------------------------------------------------------------ +// UsdAttributeFilename: +//------------------------------------------------------------------------------ + +UsdAttributeFilename::UsdAttributeFilename( + const UsdSceneItem::Ptr& item, + const PXR_NS::UsdAttribute& usdAttr) + : Ufe::AttributeFilename(item) + , UsdAttribute(item, usdAttr) +{ +} + +/*static*/ +UsdAttributeFilename::Ptr +UsdAttributeFilename::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr) +{ + auto attr = std::make_shared(item, usdAttr); + return attr; +} + +//------------------------------------------------------------------------------ +// UsdAttributeFilename - Ufe::AttributeFilename overrides +//------------------------------------------------------------------------------ + +std::string UsdAttributeFilename::get() const +{ + PXR_NS::VtValue vt; + if (fUsdAttr.Get(&vt, getCurrentTime(sceneItem())) && vt.IsHolding()) { + SdfAssetPath path = vt.UncheckedGet(); + return path.GetAssetPath(); + } + + return std::string(); +} + +void UsdAttributeFilename::set(const std::string& value) +{ + SdfAssetPath path(value); + setUsdAttr(fUsdAttr, path); +} + +Ufe::UndoableCommand::Ptr UsdAttributeFilename::setCmd(const std::string& value) +{ + auto self = std::dynamic_pointer_cast(shared_from_this()); + if (!TF_VERIFY(self, kErrorMsgInvalidType)) + return nullptr; + + std::string errMsg; + if (!MayaUsd::ufe::isAttributeEditAllowed(fUsdAttr, &errMsg)) { + MGlobal::displayError(errMsg.c_str()); + return nullptr; + } + + return std::make_shared>(self, value); +} +#endif + //------------------------------------------------------------------------------ // UsdAttributeEnumString: //------------------------------------------------------------------------------ @@ -524,17 +648,28 @@ template <> void TypedUsdAttribute::set(const std::string& value) template <> Ufe::Color3f TypedUsdAttribute::get() const { - return getUsdAttributeVectorAsUfe(fUsdAttr, getCurrentTime(sceneItem())); + return getUsdAttributeColorAsUfe(fUsdAttr, getCurrentTime(sceneItem())); } -// Note: cannot use setUsdAttributeVectorFromUfe since it relies on x/y/z template <> void TypedUsdAttribute::set(const Ufe::Color3f& value) { - GfVec3f vec; - vec.Set(value.r(), value.g(), value.b()); - setUsdAttr(fUsdAttr, vec); + setUsdAttributeColorFromUfe( + fUsdAttr, value, getCurrentTime(sceneItem())); } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +template <> Ufe::Color4f TypedUsdAttribute::get() const +{ + return getUsdAttributeColorAsUfe(fUsdAttr, getCurrentTime(sceneItem())); +} + +template <> void TypedUsdAttribute::set(const Ufe::Color4f& value) +{ + setUsdAttributeColorFromUfe( + fUsdAttr, value, getCurrentTime(sceneItem())); +} +#endif + template <> Ufe::Vector3i TypedUsdAttribute::get() const { return getUsdAttributeVectorAsUfe( @@ -547,6 +682,20 @@ template <> void TypedUsdAttribute::set(const Ufe::Vector3i& valu fUsdAttr, value, getCurrentTime(sceneItem())); } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +template <> Ufe::Vector2f TypedUsdAttribute::get() const +{ + return getUsdAttributeVectorAsUfe( + fUsdAttr, getCurrentTime(sceneItem())); +} + +template <> void TypedUsdAttribute::set(const Ufe::Vector2f& value) +{ + setUsdAttributeVectorFromUfe( + fUsdAttr, value, getCurrentTime(sceneItem())); +} +#endif + template <> Ufe::Vector3f TypedUsdAttribute::get() const { return getUsdAttributeVectorAsUfe( @@ -559,6 +708,20 @@ template <> void TypedUsdAttribute::set(const Ufe::Vector3f& valu fUsdAttr, value, getCurrentTime(sceneItem())); } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +template <> Ufe::Vector4f TypedUsdAttribute::get() const +{ + return getUsdAttributeVectorAsUfe( + fUsdAttr, getCurrentTime(sceneItem())); +} + +template <> void TypedUsdAttribute::set(const Ufe::Vector4f& value) +{ + setUsdAttributeVectorFromUfe( + fUsdAttr, value, getCurrentTime(sceneItem())); +} +#endif + template <> Ufe::Vector3d TypedUsdAttribute::get() const { return getUsdAttributeVectorAsUfe( @@ -571,6 +734,32 @@ template <> void TypedUsdAttribute::set(const Ufe::Vector3d& valu fUsdAttr, value, getCurrentTime(sceneItem())); } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +template <> Ufe::Matrix3d TypedUsdAttribute::get() const +{ + return getUsdAttributeMatrixAsUfe( + fUsdAttr, getCurrentTime(sceneItem())); +} + +template <> void TypedUsdAttribute::set(const Ufe::Matrix3d& value) +{ + setUsdAttributeMatrixFromUfe( + fUsdAttr, value, getCurrentTime(sceneItem())); +} + +template <> Ufe::Matrix4d TypedUsdAttribute::get() const +{ + return getUsdAttributeMatrixAsUfe( + fUsdAttr, getCurrentTime(sceneItem())); +} + +template <> void TypedUsdAttribute::set(const Ufe::Matrix4d& value) +{ + setUsdAttributeMatrixFromUfe( + fUsdAttr, value, getCurrentTime(sceneItem())); +} +#endif + template T TypedUsdAttribute::get() const { if (!hasValue()) @@ -661,6 +850,20 @@ UsdAttributeColorFloat3::create(const UsdSceneItem::Ptr& item, const PXR_NS::Usd return attr; } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//------------------------------------------------------------------------------ +// UsdAttributeColorFloat4: +//------------------------------------------------------------------------------ + +/*static*/ +UsdAttributeColorFloat4::Ptr +UsdAttributeColorFloat4::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr) +{ + auto attr = std::make_shared(item, usdAttr); + return attr; +} +#endif + //------------------------------------------------------------------------------ // UsdAttributeInt3: //------------------------------------------------------------------------------ @@ -673,6 +876,20 @@ UsdAttributeInt3::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribu return attr; } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//------------------------------------------------------------------------------ +// UsdAttributeFloat2: +//------------------------------------------------------------------------------ + +/*static*/ +UsdAttributeFloat2::Ptr +UsdAttributeFloat2::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr) +{ + auto attr = std::make_shared(item, usdAttr); + return attr; +} +#endif + //------------------------------------------------------------------------------ // UsdAttributeFloat3: //------------------------------------------------------------------------------ @@ -685,6 +902,20 @@ UsdAttributeFloat3::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttri return attr; } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//------------------------------------------------------------------------------ +// UsdAttributeFloat4: +//------------------------------------------------------------------------------ + +/*static*/ +UsdAttributeFloat4::Ptr +UsdAttributeFloat4::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr) +{ + auto attr = std::make_shared(item, usdAttr); + return attr; +} +#endif + //------------------------------------------------------------------------------ // UsdAttributeDouble3: //------------------------------------------------------------------------------ @@ -697,6 +928,32 @@ UsdAttributeDouble3::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttr return attr; } +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//------------------------------------------------------------------------------ +// UsdAttributeMatrix3d: +//------------------------------------------------------------------------------ + +/*static*/ +UsdAttributeMatrix3d::Ptr +UsdAttributeMatrix3d::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr) +{ + auto attr = std::make_shared(item, usdAttr); + return attr; +} + +//------------------------------------------------------------------------------ +// UsdAttributeMatrix4d: +//------------------------------------------------------------------------------ + +/*static*/ +UsdAttributeMatrix4d::Ptr +UsdAttributeMatrix4d::create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr) +{ + auto attr = std::make_shared(item, usdAttr); + return attr; +} +#endif + #if 0 // Note: if we were to implement generic attribute setting (via string) this // would be the way it could be done. diff --git a/lib/mayaUsd/ufe/UsdAttribute.h b/lib/mayaUsd/ufe/UsdAttribute.h index 73c43d8b4f..38189029e6 100644 --- a/lib/mayaUsd/ufe/UsdAttribute.h +++ b/lib/mayaUsd/ufe/UsdAttribute.h @@ -113,6 +113,31 @@ class UsdAttributeGeneric std::string nativeType() const override; }; // UsdAttributeGeneric +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//! \brief Interface for USD token attributes. +class UsdAttributeFilename + : public Ufe::AttributeFilename + , private UsdAttribute +{ +public: + typedef std::shared_ptr Ptr; + + UsdAttributeFilename(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); + + //! Create a UsdAttributeFilename. + static UsdAttributeFilename::Ptr + create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); + + // Ufe::Attribute overrides + UFE_ATTRIBUTE_OVERRIDES + + // Ufe::AttributeFilename overrides + std::string get() const override; + void set(const std::string& value) override; + Ufe::UndoableCommand::Ptr setCmd(const std::string& value) override; +}; // UsdAttributeFilename +#endif + //! \brief Interface for USD token attributes. class UsdAttributeEnumString : public Ufe::AttributeEnumString @@ -233,6 +258,21 @@ class UsdAttributeColorFloat3 : public TypedUsdAttribute create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); }; // UsdAttributeColorFloat3 +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//! \brief Interface for USD RGB color (float) attributes. +class UsdAttributeColorFloat4 : public TypedUsdAttribute +{ +public: + typedef std::shared_ptr Ptr; + + using TypedUsdAttribute::TypedUsdAttribute; + + //! Create a UsdAttributeColorFloat4. + static UsdAttributeColorFloat4::Ptr + create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); +}; // UsdAttributeColorFloat4 +#endif + //! \brief Interface for USD Vector3i (int) attributes. class UsdAttributeInt3 : public TypedUsdAttribute { @@ -246,6 +286,21 @@ class UsdAttributeInt3 : public TypedUsdAttribute create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); }; // UsdAttributeInt3 +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//! \brief Interface for USD Vector2f (float) attributes. +class UsdAttributeFloat2 : public TypedUsdAttribute +{ +public: + typedef std::shared_ptr Ptr; + + using TypedUsdAttribute::TypedUsdAttribute; + + //! Create a UsdAttributeFloat2. + static UsdAttributeFloat2::Ptr + create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); +}; // UsdAttributeFloat2 +#endif + //! \brief Interface for USD Vector3f (float) attributes. class UsdAttributeFloat3 : public TypedUsdAttribute { @@ -259,6 +314,21 @@ class UsdAttributeFloat3 : public TypedUsdAttribute create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); }; // UsdAttributeFloat3 +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//! \brief Interface for USD Vector4f (float) attributes. +class UsdAttributeFloat4 : public TypedUsdAttribute +{ +public: + typedef std::shared_ptr Ptr; + + using TypedUsdAttribute::TypedUsdAttribute; + + //! Create a UsdAttributeFloat4. + static UsdAttributeFloat4::Ptr + create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); +}; // UsdAttributeFloat4 +#endif + //! \brief Interface for USD Vector3d (double) attributes. class UsdAttributeDouble3 : public TypedUsdAttribute { @@ -272,5 +342,32 @@ class UsdAttributeDouble3 : public TypedUsdAttribute create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); }; // UsdAttributeDouble3 +#if (UFE_PREVIEW_VERSION_NUM >= 4015) +//! \brief Interface for USD Matrix3d (double) attributes. +class UsdAttributeMatrix3d : public TypedUsdAttribute +{ +public: + typedef std::shared_ptr Ptr; + + using TypedUsdAttribute::TypedUsdAttribute; + + //! Create a UsdAttributeDouble3. + static UsdAttributeMatrix3d::Ptr + create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); +}; // UsdAttributeMatrix3d + +//! \brief Interface for USD Matrix4d (double) attributes. +class UsdAttributeMatrix4d : public TypedUsdAttribute +{ +public: + typedef std::shared_ptr Ptr; + + using TypedUsdAttribute::TypedUsdAttribute; + + //! Create a UsdAttributeDouble4. + static UsdAttributeMatrix4d::Ptr + create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); +}; // UsdAttributeMatrix4d +#endif } // namespace ufe } // namespace MAYAUSD_NS_DEF diff --git a/lib/mayaUsd/ufe/UsdAttributes.cpp b/lib/mayaUsd/ufe/UsdAttributes.cpp index 81a968a4e3..d9eb1e07d5 100644 --- a/lib/mayaUsd/ufe/UsdAttributes.cpp +++ b/lib/mayaUsd/ufe/UsdAttributes.cpp @@ -82,33 +82,48 @@ Ufe::Attribute::Ptr UsdAttributes::attribute(const std::string& name) PXR_NS::TfToken tok(name); PXR_NS::UsdAttribute usdAttr = fPrim.GetAttribute(tok); Ufe::Attribute::Type newAttrType = getUfeTypeForAttribute(usdAttr); - Ufe::Attribute::Ptr newAttr; - - if (newAttrType == Ufe::Attribute::kBool) { - newAttr = UsdAttributeBool::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kInt) { - newAttr = UsdAttributeInt::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kFloat) { - newAttr = UsdAttributeFloat::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kDouble) { - newAttr = UsdAttributeDouble::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kString) { - newAttr = UsdAttributeString::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kColorFloat3) { - newAttr = UsdAttributeColorFloat3::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kEnumString) { - newAttr = UsdAttributeEnumString::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kInt3) { - newAttr = UsdAttributeInt3::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kFloat3) { - newAttr = UsdAttributeFloat3::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kDouble3) { - newAttr = UsdAttributeDouble3::create(fItem, usdAttr); - } else if (newAttrType == Ufe::Attribute::kGeneric) { - newAttr = UsdAttributeGeneric::create(fItem, usdAttr); - } else { - UFE_ASSERT_MSG(false, kErrorMsgUnknown); + + // Use a map of constructors to reduce the number of string comparisons. Since the naming + // convention is extremely uniform, let's use a macro to simplify definition (and prevent + // mismatch errors). +#define ADD_UFE_USD_CTOR(TYPE) \ + { \ + Ufe::Attribute::k##TYPE, [](UsdSceneItem::Ptr si, PXR_NS::UsdAttribute attr) { \ + return UsdAttribute##TYPE::create(si, attr); \ + } \ } + + static const std::unordered_map< + std::string, + std::function> + ctorMap + = { ADD_UFE_USD_CTOR(Bool), + ADD_UFE_USD_CTOR(Int), + ADD_UFE_USD_CTOR(Float), + ADD_UFE_USD_CTOR(Double), + ADD_UFE_USD_CTOR(String), + ADD_UFE_USD_CTOR(ColorFloat3), + ADD_UFE_USD_CTOR(EnumString), + ADD_UFE_USD_CTOR(Int3), + ADD_UFE_USD_CTOR(Float3), + ADD_UFE_USD_CTOR(Double3), + ADD_UFE_USD_CTOR(Generic), + ADD_UFE_USD_CTOR(Bool), +#if (UFE_PREVIEW_VERSION_NUM >= 4015) + ADD_UFE_USD_CTOR(ColorFloat4), + ADD_UFE_USD_CTOR(Filename), + ADD_UFE_USD_CTOR(Float2), + ADD_UFE_USD_CTOR(Float4), + ADD_UFE_USD_CTOR(Matrix3d), + ADD_UFE_USD_CTOR(Matrix4d), +#endif + }; + +#undef ADD_UFE_USD_CTOR + auto ctorIt = ctorMap.find(newAttrType); + UFE_ASSERT_MSG(ctorIt != ctorMap.end(), kErrorMsgUnknown); + Ufe::Attribute::Ptr newAttr = ctorIt->second(fItem, usdAttr); + fAttributes[name] = newAttr; return newAttr; } diff --git a/lib/mayaUsd/ufe/UsdShaderAttributeDef.cpp b/lib/mayaUsd/ufe/UsdShaderAttributeDef.cpp index fde1352097..6a719426b9 100644 --- a/lib/mayaUsd/ufe/UsdShaderAttributeDef.cpp +++ b/lib/mayaUsd/ufe/UsdShaderAttributeDef.cpp @@ -31,8 +31,7 @@ namespace ufe { PXR_NAMESPACE_USING_DIRECTIVE -UsdShaderAttributeDef::UsdShaderAttributeDef( - const PXR_NS::SdrShaderPropertyConstPtr& shaderAttributeDef) +UsdShaderAttributeDef::UsdShaderAttributeDef(const SdrShaderPropertyConstPtr& shaderAttributeDef) : Ufe::AttributeDef() , fShaderAttributeDef(shaderAttributeDef) { @@ -52,7 +51,7 @@ std::string UsdShaderAttributeDef::name() const std::string UsdShaderAttributeDef::type() const { TF_AXIOM(fShaderAttributeDef); - const PXR_NS::SdfValueTypeName typeName = fShaderAttributeDef->GetTypeAsSdfType().first; + const SdfValueTypeName typeName = fShaderAttributeDef->GetTypeAsSdfType().first; return usdTypeToUfe(typeName); } @@ -74,8 +73,8 @@ Ufe::AttributeDef::IOType UsdShaderAttributeDef::ioType() const Ufe::Value UsdShaderAttributeDef::getMetadata(const std::string& key) const { TF_AXIOM(fShaderAttributeDef); - const PXR_NS::NdrTokenMap& metadata = fShaderAttributeDef->GetMetadata(); - auto it = metadata.find(PXR_NS::TfToken(key)); + const NdrTokenMap& metadata = fShaderAttributeDef->GetMetadata(); + auto it = metadata.find(TfToken(key)); if (it != metadata.cend()) { return Ufe::Value(it->second); } @@ -87,8 +86,8 @@ Ufe::Value UsdShaderAttributeDef::getMetadata(const std::string& key) const bool UsdShaderAttributeDef::hasMetadata(const std::string& key) const { TF_AXIOM(fShaderAttributeDef); - const PXR_NS::NdrTokenMap& metadata = fShaderAttributeDef->GetMetadata(); - auto it = metadata.find(PXR_NS::TfToken(key)); + const NdrTokenMap& metadata = fShaderAttributeDef->GetMetadata(); + auto it = metadata.find(TfToken(key)); return (it != metadata.cend()); } diff --git a/lib/mayaUsd/ufe/Utils.cpp b/lib/mayaUsd/ufe/Utils.cpp index 7fdd037388..03826023bd 100644 --- a/lib/mayaUsd/ufe/Utils.cpp +++ b/lib/mayaUsd/ufe/Utils.cpp @@ -78,11 +78,11 @@ bool stringBeginsWithDigit(const std::string& inputString) // This function calculates the position index for a given layer across all // the site's local LayerStacks -uint32_t findLayerIndex(const UsdPrim& prim, const PXR_NS::SdfLayerHandle& layer) +uint32_t findLayerIndex(const UsdPrim& prim, const SdfLayerHandle& layer) { uint32_t position { 0 }; - const PXR_NS::PcpPrimIndex& primIndex = prim.GetPrimIndex(); + const PcpPrimIndex& primIndex = prim.GetPrimIndex(); // iterate through the expanded primIndex for (PcpNodeRef node : primIndex.GetNodeRange()) { @@ -195,7 +195,7 @@ UsdPrim ufePathToPrim(const Ufe::Path& path) : stage->GetPrimAtPath(SdfPath(segments[1].string()).GetPrimPath()); } -int ufePathToInstanceIndex(const Ufe::Path& path, PXR_NS::UsdPrim* prim) +int ufePathToInstanceIndex(const Ufe::Path& path, UsdPrim* prim) { int instanceIndex = UsdImagingDelegate::ALL_INSTANCES; @@ -376,7 +376,7 @@ bool isMayaWorldPath(const Ufe::Path& ufePath) return (ufePath.runTimeId() == g_MayaRtid && ufePath.size() == 1); } -PXR_NS::MayaUsdProxyShapeBase* getProxyShape(const Ufe::Path& path) +MayaUsdProxyShapeBase* getProxyShape(const Ufe::Path& path) { // Path should not be empty. if (!TF_VERIFY(!path.empty())) { @@ -513,7 +513,7 @@ bool isAttributeEditAllowed(const UsdPrim& prim, const TfToken& attrName) return true; } -bool isEditTargetLayerModifiable(const PXR_NS::UsdStageWeakPtr stage, std::string* errMsg) +bool isEditTargetLayerModifiable(const UsdStageWeakPtr stage, std::string* errMsg) { const auto editTarget = stage->GetEditTarget(); const auto editLayer = editTarget.GetLayer(); @@ -546,21 +546,31 @@ bool isEditTargetLayerModifiable(const PXR_NS::UsdStageWeakPtr stage, std::strin } #ifdef UFE_V2_FEATURES_AVAILABLE -Ufe::Attribute::Type usdTypeToUfe(const PXR_NS::SdfValueTypeName& usdType) +Ufe::Attribute::Type usdTypeToUfe(const SdfValueTypeName& usdType) { // Map the USD type into UFE type. - static const std::unordered_map sUsdTypeToUfe { - { PXR_NS::SdfValueTypeNames->Bool.GetHash(), Ufe::Attribute::kBool }, // bool - { PXR_NS::SdfValueTypeNames->Int.GetHash(), Ufe::Attribute::kInt }, // int32_t - { PXR_NS::SdfValueTypeNames->Float.GetHash(), Ufe::Attribute::kFloat }, // float - { PXR_NS::SdfValueTypeNames->Double.GetHash(), Ufe::Attribute::kDouble }, // double - { PXR_NS::SdfValueTypeNames->String.GetHash(), Ufe::Attribute::kString }, // std::string - { PXR_NS::SdfValueTypeNames->Token.GetHash(), Ufe::Attribute::kEnumString }, // TfToken - { PXR_NS::SdfValueTypeNames->Int3.GetHash(), Ufe::Attribute::kInt3 }, // GfVec3i - { PXR_NS::SdfValueTypeNames->Float3.GetHash(), Ufe::Attribute::kFloat3 }, // GfVec3f - { PXR_NS::SdfValueTypeNames->Double3.GetHash(), Ufe::Attribute::kDouble3 }, // GfVec3d - { PXR_NS::SdfValueTypeNames->Color3f.GetHash(), Ufe::Attribute::kColorFloat3 }, // GfVec3f - { PXR_NS::SdfValueTypeNames->Color3d.GetHash(), Ufe::Attribute::kColorFloat3 }, // GfVec3d + static const std::unordered_map sUsdTypeToUfe + { + { SdfValueTypeNames->Bool.GetHash(), Ufe::Attribute::kBool }, // bool + { SdfValueTypeNames->Int.GetHash(), Ufe::Attribute::kInt }, // int32_t + { SdfValueTypeNames->Float.GetHash(), Ufe::Attribute::kFloat }, // float + { SdfValueTypeNames->Double.GetHash(), Ufe::Attribute::kDouble }, // double + { SdfValueTypeNames->String.GetHash(), Ufe::Attribute::kString }, // std::string + { SdfValueTypeNames->Token.GetHash(), Ufe::Attribute::kEnumString }, // TfToken + { SdfValueTypeNames->Int3.GetHash(), Ufe::Attribute::kInt3 }, // GfVec3i + { SdfValueTypeNames->Float3.GetHash(), Ufe::Attribute::kFloat3 }, // GfVec3f + { SdfValueTypeNames->Double3.GetHash(), Ufe::Attribute::kDouble3 }, // GfVec3d + { SdfValueTypeNames->Color3f.GetHash(), Ufe::Attribute::kColorFloat3 }, // GfVec3f + { SdfValueTypeNames->Color3d.GetHash(), Ufe::Attribute::kColorFloat3 }, // GfVec3d +#if (UFE_PREVIEW_VERSION_NUM >= 4015) + { SdfValueTypeNames->Asset.GetHash(), Ufe::Attribute::kFilename }, // SdfAssetPath + { SdfValueTypeNames->Float2.GetHash(), Ufe::Attribute::kFloat2 }, // GfVec2f + { SdfValueTypeNames->Float4.GetHash(), Ufe::Attribute::kFloat4 }, // GfVec4f + { SdfValueTypeNames->Color4f.GetHash(), Ufe::Attribute::kColorFloat4 }, // GfVec4f + { SdfValueTypeNames->Color4d.GetHash(), Ufe::Attribute::kColorFloat4 }, // GfVec4d + { SdfValueTypeNames->Matrix3d.GetHash(), Ufe::Attribute::kMatrix3d }, // GfMatrix3d + { SdfValueTypeNames->Matrix4d.GetHash(), Ufe::Attribute::kMatrix4d }, // GfMatrix4d +#endif }; const auto iter = sUsdTypeToUfe.find(usdType.GetHash()); diff --git a/test/lib/ufe/testAttribute.py b/test/lib/ufe/testAttribute.py index 0d4d110e9a..1dece005ae 100644 --- a/test/lib/ufe/testAttribute.py +++ b/test/lib/ufe/testAttribute.py @@ -110,6 +110,22 @@ def setUp(self): '''Called initially to set up the maya test environment''' self.assertTrue(self.pluginsLoaded) + @classmethod + def openMaterialXSamplerStage(cls): + '''Open MtlxValueTypes stage in testSamples. This stage can be freely loaded even if + the underlying USD does not support MaterialX since we are not rendering that scene. + We also rename the stage to match the hierarchy of the top_layer scene which is + hardcoded in some tests.''' + cmds.file(new=True, force=True) + testFile = testUtils.getTestScene("MaterialX", "MtlxValueTypes.usda") + shapeNode,shapeStage = mayaUtils.createProxyFromFile(testFile) + cmds.rename(shapeNode, "proxyShape1") + cmds.rename("|"+shapeNode.split("|")[1], "transform1") + + def assertMatrixAlmostEqual(self, ufeMatrix, usdMatrix): + testUtils.assertMatrixAlmostEqual( + self, ufeMatrix.matrix, usdMatrix) + def assertVectorAlmostEqual(self, ufeVector, usdVector): testUtils.assertVectorAlmostEqual( self, ufeVector.vector, usdVector) @@ -160,8 +176,17 @@ def runUndoRedoUsingMayaSetAttr(self, attr, newVal, decimalPlaces=None): setAttrPath = self.getMayaAttrStr(attr) if isinstance(newVal, (ufe.Vector3i, ufe.Vector3f, ufe.Vector3d)): cmds.setAttr(setAttrPath, newVal.x(), newVal.y(), newVal.z()) + elif isinstance(newVal, ufe.Vector2f): + cmds.setAttr(setAttrPath, newVal.x(), newVal.y()) + elif isinstance(newVal, ufe.Vector4f): + cmds.setAttr(setAttrPath, newVal.x(), newVal.y(), newVal.z(), newVal.w()) elif isinstance(newVal, ufe.Color3f): cmds.setAttr(setAttrPath, newVal.r(), newVal.g(), newVal.b()) + elif isinstance(newVal, ufe.Color4f): + cmds.setAttr(setAttrPath, newVal.r(), newVal.g(), newVal.b(), newVal.a()) + elif isinstance(newVal, ufe.Matrix3d) or isinstance(newVal, ufe.Matrix4d): + # Flatten the matrix for Maya: + cmds.setAttr(setAttrPath, *[i for row in newVal.matrix for i in row]) else: cmds.setAttr(setAttrPath, newVal) @@ -190,15 +215,25 @@ def runMayaGetAttrTest(self, ufeAttr, decimalPlaces=None): self.assertEqual(ufeAttrType, cmds.getAttr(getAttrPath, type=True)) ufeVectorTypes = {ufe.Attribute.kColorFloat3 : ufe.Color3f, + ufe.Attribute.kColorFloat4 : ufe.Color4f, ufe.Attribute.kInt3 : ufe.Vector3i, + ufe.Attribute.kFloat2 : ufe.Vector2f, ufe.Attribute.kFloat3 : ufe.Vector3f, - ufe.Attribute.kDouble3 : ufe.Vector3d} + ufe.Attribute.kFloat4 : ufe.Vector4f, + ufe.Attribute.kDouble3 : ufe.Vector3d, + ufe.Attribute.kMatrix3d : ufe.Matrix3d, + ufe.Attribute.kMatrix4d : ufe.Matrix4d + } if ufeAttrType == ufe.Attribute.kGeneric: self.assertEqual(cmds.getAttr(getAttrPath), str(ufeAttr)) elif ufeAttrType in ufeVectorTypes: getAttrValue = cmds.getAttr(getAttrPath) - self.assertEqual(ufeVectorTypes[ufeAttrType](*getAttrValue), ufeAttr.get()) + # Pre Ufe 0.4.15: Maya might return the result as a string for colors. Fixed to always + # return a vector post 0.4.15. + if isinstance(getAttrValue, str): + getAttrValue = eval(getAttrValue) + self.assertEqual(ufeVectorTypes[ufeAttrType](getAttrValue), ufeAttr.get()) else: if decimalPlaces is not None: self.assertAlmostEqual(cmds.getAttr(getAttrPath), ufeAttr.get(), decimalPlaces) @@ -274,6 +309,42 @@ def testAttributeGeneric(self): # Run test using Maya's getAttr command. self.runMayaGetAttrTest(ufeAttr) + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4015', 'Test only available in UFE preview version 0.4.15 and greater') + def testAttributeFilename(self): + '''Test the Filename attribute type.''' + + AttributeTestCase.openMaterialXSamplerStage() + + # Use our engine method to run the bulk of the test (all the stuff from + # the Attribute base class). We use the emitColor attribute which is + # an ColorFloat3 type. + ufeAttr, usdAttr = self.runTestAttribute( + path='/TypeSampler/MaterialX/D_filename', + attrName='inputs:in', + ufeAttrClass=ufe.AttributeFilename, + ufeAttrType=ufe.Attribute.kFilename) + + # Now we test the Filename specific methods. + + # Compare the initial UFE value to that directly from USD. + self.assertEqual(ufeAttr.get(), usdAttr.Get()) + + # Change to 'blue.png' and verify the return in UFE. + ufeAttr.set("blue.png") + self.assertEqual(ufeAttr.get(), "blue.png") + + # Verify that the new UFE value matches what is directly in USD. + self.assertEqual(ufeAttr.get(), usdAttr.Get()) + + # Change back to 'red.png' using a command. + self.runUndoRedo(ufeAttr, "red.png") + + # Run test using Maya's setAttr command. + self.runUndoRedoUsingMayaSetAttr(ufeAttr, "green.png") + + # Run test using Maya's getAttr command. + self.runMayaGetAttrTest(ufeAttr) + def testAttributeEnumString(self): '''Test the EnumString attribute type.''' @@ -495,6 +566,7 @@ def testAttributeStringToken(self): # Run test using Maya's getAttr command. self.runMayaGetAttrTest(ufeAttr) + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') >= '4015', 'Test not available in UFE preview version 0.4.15 and greater') def testAttributeColorFloat3(self): '''Test the ColorFloat3 attribute type.''' @@ -534,12 +606,124 @@ def testAttributeColorFloat3(self): # Run test using Maya's getAttr command. self.runMayaGetAttrTest(ufeAttr) + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4015', 'Test only available in UFE preview version 0.4.15 and greater') + def testAttributeColorFloat3(self): + '''Test the ColorFloat3 attribute type.''' + + # Open top_layer.ma scene in testSamples + mayaUtils.openTopLayerScene() + + # Use our engine method to run the bulk of the test (all the stuff from + # the Attribute base class). We use the emitColor attribute which is + # an ColorFloat3 type. + ufeAttr, usdAttr = self.runTestAttribute( + path='/Room_set/Props/Ball_35/Looks/BallLook/Base', + attrName='emitColor', + ufeAttrClass=ufe.AttributeColorFloat3, + ufeAttrType=ufe.Attribute.kColorFloat3) + + # Now we test the ColorFloat3 specific methods. + + # Compare the initial UFE value to that directly from USD. + self.assertColorAlmostEqual(ufeAttr.get(), usdAttr.Get()) + + # Set the attribute in UFE with some random color values. + vec = ufe.Color3f(random.random(), random.random(), random.random()) + ufeAttr.set(vec) + + # Then make sure that new UFE value matches what it in USD. + self.assertColorAlmostEqual(ufeAttr.get(), usdAttr.Get()) + self.runUndoRedo(ufeAttr, + ufe.Color3f(vec.r()+1.0, vec.g()+2.0, vec.b()+3.0)) + + # Run test using Maya's setAttr command. + vec = ufeAttr.get() + self.runUndoRedoUsingMayaSetAttr(ufeAttr, + ufe.Color3f(vec.r()+1.0, vec.g()+2.0, vec.b()+3.0)) + + # Run test using Maya's getAttr command. + self.runMayaGetAttrTest(ufeAttr) + + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4015', 'Test only available in UFE preview version 0.4.15 and greater') + def testAttributeColorFloat4(self): + '''Test the ColorFloat4 attribute type.''' + + AttributeTestCase.openMaterialXSamplerStage() + + # Use our engine method to run the bulk of the test (all the stuff from + # the Attribute base class). We use the emitColor attribute which is + # an ColorFloat3 type. + ufeAttr, usdAttr = self.runTestAttribute( + path='/TypeSampler/MaterialX/TXT', + attrName='inputs:default', + ufeAttrClass=ufe.AttributeColorFloat4, + ufeAttrType=ufe.Attribute.kColorFloat4) + + # Now we test the ColorFloat4 specific methods. + + # Compare the initial UFE value to that directly from USD. + self.assertColorAlmostEqual(ufeAttr.get(), usdAttr.Get()) + + # Set the attribute in UFE with some random color values. + vec = ufe.Color4f(random.random(), random.random(), random.random(), random.random()) + ufeAttr.set(vec) + + # Then make sure that new UFE value matches what it in USD. + self.assertColorAlmostEqual(ufeAttr.get(), usdAttr.Get()) + self.runUndoRedo(ufeAttr, + ufe.Color4f(vec.r()+1.0, vec.g()+2.0, vec.b()+3.0, vec.a()+4.0)) + + # Run test using Maya's setAttr command. + vec = ufeAttr.get() + self.runUndoRedoUsingMayaSetAttr(ufeAttr, + ufe.Color4f(vec.r()+1.0, vec.g()+2.0, vec.b()+3.0, vec.a()+4.0)) + + # Run test using Maya's getAttr command. + self.runMayaGetAttrTest(ufeAttr) + def _testAttributeInt3(self): '''Test the Int3 attribute type.''' # I could not find an int3 attribute to test with. pass + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4015', 'Test only available in UFE preview version 0.4.15 and greater') + def testAttributeFloat2(self): + '''Test the Float2 attribute type.''' + + AttributeTestCase.openMaterialXSamplerStage() + + # Use our engine method to run the bulk of the test (all the stuff from + # the Attribute base class). We use the bumpNormal attribute which is + # an Float2 type. + ufeAttr, usdAttr = self.runTestAttribute( + path='/TypeSampler/MaterialX/D_vector2', + attrName='inputs:in', + ufeAttrClass=ufe.AttributeFloat2, + ufeAttrType=ufe.Attribute.kFloat2) + + # Now we test the Float2 specific methods. + + # Compare the initial UFE value to that directly from USD. + self.assertVectorAlmostEqual(ufeAttr.get(), usdAttr.Get()) + + # Set the attribute in UFE with some random values. + vec = ufe.Vector2f(random.random(), random.random()) + ufeAttr.set(vec) + + # Then make sure that new UFE value matches what it in USD. + self.assertVectorAlmostEqual(ufeAttr.get(), usdAttr.Get()) + self.runUndoRedo(ufeAttr, + ufe.Vector2f(vec.x()+1.0, vec.y()+2.0)) + + # Run test using Maya's setAttr command. + vec = ufeAttr.get() + self.runUndoRedoUsingMayaSetAttr(ufeAttr, + ufe.Vector2f(vec.x()+1.0, vec.y()+2.0)) + + # Run test using Maya's getAttr command. + self.runMayaGetAttrTest(ufeAttr) + def testAttributeFloat3(self): '''Test the Float3 attribute type.''' @@ -566,7 +750,6 @@ def testAttributeFloat3(self): # Then make sure that new UFE value matches what it in USD. self.assertVectorAlmostEqual(ufeAttr.get(), usdAttr.Get()) - self.runUndoRedo(ufeAttr, ufe.Vector3f(vec.x()+1.0, vec.y()+2.0, vec.z()+3.0)) @@ -578,6 +761,46 @@ def testAttributeFloat3(self): # Run test using Maya's getAttr command. self.runMayaGetAttrTest(ufeAttr) + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4015', 'Test only available in UFE preview version 0.4.15 and greater') + def testAttributeFloat4(self): + '''Test the Float4 attribute type.''' + + AttributeTestCase.openMaterialXSamplerStage() + + # Use our engine method to run the bulk of the test (all the stuff from + # the Attribute base class). We use the bumpNormal attribute which is + # an Float4 type. + ufeAttr, usdAttr = self.runTestAttribute( + path='/TypeSampler/MaterialX/D_vector4', + attrName='inputs:in', + ufeAttrClass=ufe.AttributeFloat4, + ufeAttrType=ufe.Attribute.kFloat4) + + # Now we test the Float4 specific methods. + + # Compare the initial UFE value to that directly from USD. + self.assertVectorAlmostEqual(ufeAttr.get(), usdAttr.Get()) + + # Set the attribute in UFE with some random values. + vec = ufe.Vector4f(random.random(), random.random(), + random.random(), random.random()) + ufeAttr.set(vec) + + # Then make sure that new UFE value matches what it in USD. + self.assertVectorAlmostEqual(ufeAttr.get(), usdAttr.Get()) + self.runUndoRedo(ufeAttr, + ufe.Vector4f(vec.x()+1.0, vec.y()+2.0, + vec.z()+3.0, vec.w()+4.0)) + + # Run test using Maya's setAttr command. + vec = ufeAttr.get() + self.runUndoRedoUsingMayaSetAttr(ufeAttr, + ufe.Vector4f(vec.x()+1.0, vec.y()+2.0, + vec.z()+3.0, vec.w()+4.0)) + + # Run test using Maya's getAttr command. + self.runMayaGetAttrTest(ufeAttr) + def testAttributeDouble3(self): '''Test the Double3 attribute type.''' @@ -614,6 +837,80 @@ def testAttributeDouble3(self): # Run test using Maya's getAttr command. self.runMayaGetAttrTest(ufeAttr) + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4015', 'Test only available in UFE preview version 0.4.15 and greater') + def testAttributeMatrix3d(self): + '''Test the Matrix3d attribute type.''' + + AttributeTestCase.openMaterialXSamplerStage() + + # Use our engine method to run the bulk of the test (all the stuff from + # the Attribute base class). We use the bumpNormal attribute which is + # an Matrix3d type. + ufeAttr, usdAttr = self.runTestAttribute( + path='/TypeSampler/MaterialX/D_matrix33', + attrName='inputs:in', + ufeAttrClass=ufe.AttributeMatrix3d, + ufeAttrType=ufe.Attribute.kMatrix3d) + + # Now we test the Matrix3d specific methods. + + # Compare the initial UFE value to that directly from USD. + self.assertMatrixAlmostEqual(ufeAttr.get(), usdAttr.Get()) + + # Set the attribute in UFE with some random values. + mat = [[random.random() for i in range(3)] for j in range(3)] + ufeAttr.set(ufe.Matrix3d(mat)) + + # Then make sure that new UFE value matches what it in USD. + self.assertMatrixAlmostEqual(ufeAttr.get(), usdAttr.Get()) + self.runUndoRedo(ufeAttr, + ufe.Matrix3d([[mat[i][j] + mat[i][j] for j in range(3)] for i in range(3)])) + + # Run test using Maya's setAttr command. + mat = ufeAttr.get().matrix + self.runUndoRedoUsingMayaSetAttr(ufeAttr, + ufe.Matrix3d([[mat[i][j] + mat[i][j] for j in range(3)] for i in range(3)])) + + # Run test using Maya's getAttr command. + self.runMayaGetAttrTest(ufeAttr) + + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4015', 'Test only available in UFE preview version 0.4.15 and greater') + def testAttributeMatrix4d(self): + '''Test the Matrix4d attribute type.''' + + AttributeTestCase.openMaterialXSamplerStage() + + # Use our engine method to run the bulk of the test (all the stuff from + # the Attribute base class). We use the bumpNormal attribute which is + # an Matrix4d type. + ufeAttr, usdAttr = self.runTestAttribute( + path='/TypeSampler/MaterialX/D_matrix44', + attrName='inputs:in', + ufeAttrClass=ufe.AttributeMatrix4d, + ufeAttrType=ufe.Attribute.kMatrix4d) + + # Now we test the Matrix4d specific methods. + + # Compare the initial UFE value to that directly from USD. + self.assertMatrixAlmostEqual(ufeAttr.get(), usdAttr.Get()) + + # Set the attribute in UFE with some random values. + mat = [[random.random() for i in range(4)] for j in range(4)] + ufeAttr.set(ufe.Matrix4d(mat)) + + # Then make sure that new UFE value matches what it in USD. + self.assertMatrixAlmostEqual(ufeAttr.get(), usdAttr.Get()) + self.runUndoRedo(ufeAttr, + ufe.Matrix4d([[mat[i][j] + mat[i][j] for j in range(4)] for i in range(4)])) + + # Run test using Maya's setAttr command. + mat = ufeAttr.get().matrix + self.runUndoRedoUsingMayaSetAttr(ufeAttr, + ufe.Matrix4d([[mat[i][j] + mat[i][j] for j in range(4)] for i in range(4)])) + + # Run test using Maya's getAttr command. + self.runMayaGetAttrTest(ufeAttr) + def testObservation(self): ''' Test Attributes observation interface. diff --git a/test/lib/ufe/testShaderNodeDef.py b/test/lib/ufe/testShaderNodeDef.py index e44dbdd71c..5d417dd3cf 100644 --- a/test/lib/ufe/testShaderNodeDef.py +++ b/test/lib/ufe/testShaderNodeDef.py @@ -94,6 +94,7 @@ def testDefinitions(self): self.assertTrue(mtlxDef in nodeDefTypes) @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4001', 'nodeDefHandler is only available in UFE preview version 0.4.1 and greater') + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') >= '4015', 'filename and float2 are no longer generic starting with Ufe 0.4.15') def testDefinitionByType(self): type = "ND_image_color3" nodeDefHandler = self.getNodeDefHandler() @@ -137,6 +138,50 @@ def testDefinitionByType(self): self.assertEqual(outputs[0].name(), "out") self.assertEqual(outputs[0].type(), "ColorFloat3") + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4015', 'filename and float2 are no longer generic starting with Ufe 0.4.15') + def testDefinitionByType(self): + type = "ND_image_color3" + nodeDefHandler = self.getNodeDefHandler() + nodeDef = nodeDefHandler.definition(type) + self.assertIsNotNone(nodeDef) + inputs = nodeDef.inputs() + outputs = nodeDef.outputs() + self.assertEqual(nodeDef.type(), type) + self.assertEqual(len(inputs), 10) + self.assertEqual(inputs[0].name(), "file") + self.assertEqual(inputs[0].type(), "Filename") + self.assertEqual(inputs[0].defaultValue(), "") + self.assertEqual(inputs[1].name(), "layer") + self.assertEqual(inputs[1].type(), "String") + self.assertEqual(inputs[1].defaultValue(), "") + self.assertEqual(inputs[2].name(), "default") + self.assertEqual(inputs[2].type(), "ColorFloat3") + self.assertEqual(inputs[2].defaultValue(), "(0, 0, 0)") + self.assertEqual(inputs[3].name(), "texcoord") + 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].defaultValue(), "periodic") + self.assertEqual(inputs[5].name(), "vaddressmode") + 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].defaultValue(), "linear") + self.assertEqual(inputs[7].name(), "framerange") + self.assertEqual(inputs[7].type(), "String") + self.assertEqual(inputs[7].defaultValue(), "") + self.assertEqual(inputs[8].name(), "frameoffset") + 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].defaultValue(), "constant") + self.assertEqual(len(outputs), 1) + self.assertEqual(outputs[0].name(), "out") + self.assertEqual(outputs[0].type(), "ColorFloat3") + @unittest.skipIf(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '4010', 'Improvements to nodeDef only available in UFE preview version 0.4.8 and greater') def testClassificationsAndMetadata(self): type = "ND_image_color3" diff --git a/test/testSamples/MaterialX/MtlxValueTypes.usda b/test/testSamples/MaterialX/MtlxValueTypes.usda new file mode 100644 index 0000000000..9350c7a02f --- /dev/null +++ b/test/testSamples/MaterialX/MtlxValueTypes.usda @@ -0,0 +1,184 @@ +#usda 1.0 +( + defaultPrim = "TypeSampler" + metersPerUnit = 0.01 + upAxis = "Y" +) + +def Material "TypeSampler" +{ + def NodeGraph "UsdPreviewSurface" + { + def Shader "PS" + { + uniform token info:id = "UsdPreviewSurface" + color3f inputs:diffuseColor = (0.1, 0.2, 0.3) + float inputs:ior = 1.5 + int inputs:useSpecularWorkflow = 1 + normal3f inputs:normal = (0.4, 0.5, 0.6) + token outputs:displacement + token outputs:surface + } + + def Shader "TXT" + { + uniform token info:id = "UsdUVTexture" + float4 inputs:fallback = (0.7, 0.8, 0.9, 0.1) + asset inputs:file = @grid16.png@ + float2 inputs:st = (0.2, 0.3) + token inputs:wrapS = "repeat" + float3 outputs:rgb + } + + def Shader "R_string" + { + uniform token info:id = "UsdPrimvarReader_string" + string inputs:fallback = "testString" + string outputs:result + } + + def Shader "R_float3" + { + uniform token info:id = "UsdPrimvarReader_float3" + float3 inputs:fallback = (0.3, 0.4, 0.5) + float3 outputs:result + } + + def Shader "R_normal" + { + uniform token info:id = "UsdPrimvarReader_normal" + normal3f inputs:fallback = (0.4, 0.5, 0.6) + normal3f outputs:result + } + + def Shader "R_point" + { + uniform token info:id = "UsdPrimvarReader_point" + point3f inputs:fallback = (0.5, 0.6, 0.7) + point3f outputs:result + } + + def Shader "R_vector" + { + uniform token info:id = "UsdPrimvarReader_vector" + vector3f inputs:fallback = (0.6, 0.7, 0.8) + vector3f outputs:result + } + + def Shader "R_matrix" + { + uniform token info:id = "UsdPrimvarReader_matrix" + matrix4d inputs:fallback = ( (0.1, 0.3, 0.5, 0.7), (0.9, 0.8, 0.4, 0.2), (0.1, 0.2, 0.3, 0.4), (0.5, 0.4, 0.6, 0.3) ) + matrix4d outputs:result + } + } + + def NodeGraph "MaterialX" + { + def Shader "SS" + { + uniform token info:id = "ND_standard_surface_surfaceshader" + color3f inputs:base_color = (0.2, 0.4, 0.6) + float inputs:specular_roughness = 0.4 + float3 inputs:normal = (0.1, 0.2, 0.3) + token outputs:surface + } + + def Shader "TXT" + { + uniform token info:id = "ND_image_color4" + + asset inputs:file = @grid16.png@ + string inputs:filtertype = "cubic" + float2 inputs:texcoord = (0.5, 0.6) + color4f inputs:default = (0.7, 0.6, 0.5, 0.4) + int inputs:frameoffset = 12 + color4f outputs:out + } + + def Shader "D_float" + { + uniform token info:id = "ND_dot_float" + float inputs:in = 12.0 + float outputs:out + } + + def Shader "D_color3" + { + uniform token info:id = "ND_dot_color3" + color3f inputs:in = (0.1, 0.2, 0.3) + color3f outputs:out + } + + def Shader "D_color4" + { + uniform token info:id = "ND_dot_color4" + color4f inputs:in = (0.2, 0.3, 0.4, 0.5) + color4f outputs:out + } + + def Shader "D_vector2" + { + uniform token info:id = "ND_dot_vector2" + float2 inputs:in = (0.3, 0.4) + float2 outputs:out + } + + def Shader "D_vector3" + { + uniform token info:id = "ND_dot_vector3" + float3 inputs:in = (0.4, 0.5, 0.6) + float3 outputs:out + } + + def Shader "D_vector4" + { + uniform token info:id = "ND_dot_vector4" + float4 inputs:in = (0.5, 0.6, 0.7, 0.8) + float4 outputs:out + } + + def Shader "D_boolean" + { + uniform token info:id = "ND_dot_boolean" + bool inputs:in = true + bool outputs:out + } + + def Shader "D_integer" + { + uniform token info:id = "ND_dot_integer" + int inputs:in = 42 + int outputs:out + } + + def Shader "D_matrix33" + { + uniform token info:id = "ND_dot_matrix33" + matrix3d inputs:in = ( (0.3, 0.5, 0.7), (0.1, 0.2, 0.4), (0.5, 0.4, 0.6) ) + matrix3d outputs:out + } + + def Shader "D_matrix44" + { + uniform token info:id = "ND_dot_matrix44" + matrix4d inputs:in = ( (0.1, 0.3, 0.5, 0.7), (0.9, 0.8, 0.4, 0.2), (0.1, 0.2, 0.3, 0.4), (0.5, 0.4, 0.6, 0.3) ) + matrix4d outputs:out + } + + def Shader "D_string" + { + uniform token info:id = "ND_dot_string" + string inputs:in = "testString" + string outputs:out + } + + def Shader "D_filename" + { + uniform token info:id = "ND_dot_filename" + asset inputs:in = @grid16.png@ + asset outputs:out + } + } +} + diff --git a/test/testUtils/testUtils.py b/test/testUtils/testUtils.py index def28bb89d..1c14b7ec79 100644 --- a/test/testUtils/testUtils.py +++ b/test/testUtils/testUtils.py @@ -26,6 +26,11 @@ def stripPrefix(input_str, prefix): return input_str[len(prefix):] return input_str +def assertMatrixAlmostEqual(testCase, ma, mb, places=7): + for ra, rb in zip(ma, mb): + for a, b in zip(ra, rb): + testCase.assertAlmostEqual(a, b, places) + def assertVectorAlmostEqual(testCase, a, b, places=7): for va, vb in zip(a, b): testCase.assertAlmostEqual(va, vb, places) From 2bda5dc23eec926a73b587cc5815d19b06518839 Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Wed, 18 May 2022 17:23:14 -0400 Subject: [PATCH 2/4] Make testAttribute compatible with earlier Ufe --- test/lib/ufe/testAttribute.py | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/test/lib/ufe/testAttribute.py b/test/lib/ufe/testAttribute.py index 1dece005ae..0a6c83b058 100644 --- a/test/lib/ufe/testAttribute.py +++ b/test/lib/ufe/testAttribute.py @@ -33,6 +33,7 @@ import ufe +import ast import os import random import unittest @@ -174,17 +175,11 @@ def runUndoRedoUsingMayaSetAttr(self, attr, newVal, decimalPlaces=None): assert oldVal != newVal, "Undo / redo testing requires setting a value different from the current value" setAttrPath = self.getMayaAttrStr(attr) - if isinstance(newVal, (ufe.Vector3i, ufe.Vector3f, ufe.Vector3d)): - cmds.setAttr(setAttrPath, newVal.x(), newVal.y(), newVal.z()) - elif isinstance(newVal, ufe.Vector2f): - cmds.setAttr(setAttrPath, newVal.x(), newVal.y()) - elif isinstance(newVal, ufe.Vector4f): - cmds.setAttr(setAttrPath, newVal.x(), newVal.y(), newVal.z(), newVal.w()) - elif isinstance(newVal, ufe.Color3f): - cmds.setAttr(setAttrPath, newVal.r(), newVal.g(), newVal.b()) - elif isinstance(newVal, ufe.Color4f): - cmds.setAttr(setAttrPath, newVal.r(), newVal.g(), newVal.b(), newVal.a()) - elif isinstance(newVal, ufe.Matrix3d) or isinstance(newVal, ufe.Matrix4d): + if hasattr(newVal, "vector"): + cmds.setAttr(setAttrPath, *newVal.vector) + elif hasattr(newVal, "color"): + cmds.setAttr(setAttrPath, *newVal.color) + elif hasattr(newVal, "matrix"): # Flatten the matrix for Maya: cmds.setAttr(setAttrPath, *[i for row in newVal.matrix for i in row]) else: @@ -215,16 +210,20 @@ def runMayaGetAttrTest(self, ufeAttr, decimalPlaces=None): self.assertEqual(ufeAttrType, cmds.getAttr(getAttrPath, type=True)) ufeVectorTypes = {ufe.Attribute.kColorFloat3 : ufe.Color3f, - ufe.Attribute.kColorFloat4 : ufe.Color4f, ufe.Attribute.kInt3 : ufe.Vector3i, - ufe.Attribute.kFloat2 : ufe.Vector2f, ufe.Attribute.kFloat3 : ufe.Vector3f, - ufe.Attribute.kFloat4 : ufe.Vector4f, - ufe.Attribute.kDouble3 : ufe.Vector3d, - ufe.Attribute.kMatrix3d : ufe.Matrix3d, - ufe.Attribute.kMatrix4d : ufe.Matrix4d + ufe.Attribute.kDouble3 : ufe.Vector3d } + if hasattr(ufe.Attribute, "kColorFloat4"): + ufeVectorTypes.update({ + ufe.Attribute.kColorFloat4 : ufe.Color4f, + ufe.Attribute.kFloat2 : ufe.Vector2f, + ufe.Attribute.kFloat4 : ufe.Vector4f, + ufe.Attribute.kMatrix3d : ufe.Matrix3d, + ufe.Attribute.kMatrix4d : ufe.Matrix4d + }) + if ufeAttrType == ufe.Attribute.kGeneric: self.assertEqual(cmds.getAttr(getAttrPath), str(ufeAttr)) elif ufeAttrType in ufeVectorTypes: @@ -232,7 +231,7 @@ def runMayaGetAttrTest(self, ufeAttr, decimalPlaces=None): # Pre Ufe 0.4.15: Maya might return the result as a string for colors. Fixed to always # return a vector post 0.4.15. if isinstance(getAttrValue, str): - getAttrValue = eval(getAttrValue) + getAttrValue = ast.literal_eval(getAttrValue) self.assertEqual(ufeVectorTypes[ufeAttrType](getAttrValue), ufeAttr.get()) else: if decimalPlaces is not None: From ce3af81e5c4d4fc69c6b62932852b0ee6934813f Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Thu, 19 May 2022 09:20:18 -0400 Subject: [PATCH 3/4] Make attribute test compatible with all Ufe versions --- test/lib/ufe/testAttribute.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/lib/ufe/testAttribute.py b/test/lib/ufe/testAttribute.py index 0a6c83b058..03b2df584e 100644 --- a/test/lib/ufe/testAttribute.py +++ b/test/lib/ufe/testAttribute.py @@ -232,7 +232,12 @@ def runMayaGetAttrTest(self, ufeAttr, decimalPlaces=None): # return a vector post 0.4.15. if isinstance(getAttrValue, str): getAttrValue = ast.literal_eval(getAttrValue) - self.assertEqual(ufeVectorTypes[ufeAttrType](getAttrValue), ufeAttr.get()) + if hasattr(ufe.Attribute, "kColorFloat4"): + # Ufe post 0.4.15 can init vector/matrix types with sequences directly: + self.assertEqual(ufeVectorTypes[ufeAttrType](getAttrValue), ufeAttr.get()) + else: + # Before 0.4.15 we need to splat the value: + self.assertEqual(ufeVectorTypes[ufeAttrType](*getAttrValue), ufeAttr.get()) else: if decimalPlaces is not None: self.assertAlmostEqual(cmds.getAttr(getAttrPath), ufeAttr.get(), decimalPlaces) From 9d327523d941a33fe5b6f0bfb8aa41da43d1aabc Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Thu, 19 May 2022 14:06:15 -0400 Subject: [PATCH 4/4] Responding to review comment. --- lib/mayaUsd/ufe/UsdAttribute.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/mayaUsd/ufe/UsdAttribute.h b/lib/mayaUsd/ufe/UsdAttribute.h index 38189029e6..ed61791804 100644 --- a/lib/mayaUsd/ufe/UsdAttribute.h +++ b/lib/mayaUsd/ufe/UsdAttribute.h @@ -351,10 +351,9 @@ class UsdAttributeMatrix3d : public TypedUsdAttribute using TypedUsdAttribute::TypedUsdAttribute; - //! Create a UsdAttributeDouble3. static UsdAttributeMatrix3d::Ptr create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); -}; // UsdAttributeMatrix3d +}; //! \brief Interface for USD Matrix4d (double) attributes. class UsdAttributeMatrix4d : public TypedUsdAttribute @@ -364,10 +363,9 @@ class UsdAttributeMatrix4d : public TypedUsdAttribute using TypedUsdAttribute::TypedUsdAttribute; - //! Create a UsdAttributeDouble4. static UsdAttributeMatrix4d::Ptr create(const UsdSceneItem::Ptr& item, const PXR_NS::UsdAttribute& usdAttr); -}; // UsdAttributeMatrix4d +}; #endif } // namespace ufe } // namespace MAYAUSD_NS_DEF