From f9c8e659839a81875fabea16db3db63631c5f105 Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Thu, 18 Jan 2024 14:21:04 -0500 Subject: [PATCH 1/2] LOOKDEVX-2403 - Allow creating custom types at nodegraph boundaries When creating NodeGraph/Material inputs and outputs, allow passing the native type as a string instead of "Generic" when creating a port that can only be wrapped in UFE as an UfeAttributeGeneric. This allows LookdevX to display the expected port type when promoting ports on inner nodes. --- lib/mayaUsd/ufe/UsdAttribute.cpp | 6 ++++++ lib/mayaUsd/ufe/UsdAttribute.h | 4 ++++ lib/mayaUsd/ufe/UsdAttributeHolder.cpp | 11 ++++++++++ lib/mayaUsd/ufe/UsdAttributes.cpp | 16 ++++++++++++-- test/lib/ufe/testConnections.py | 30 ++++++++++++++++++++++++-- 5 files changed, 63 insertions(+), 4 deletions(-) diff --git a/lib/mayaUsd/ufe/UsdAttribute.cpp b/lib/mayaUsd/ufe/UsdAttribute.cpp index 5c4348228d..d6c9ab7a83 100644 --- a/lib/mayaUsd/ufe/UsdAttribute.cpp +++ b/lib/mayaUsd/ufe/UsdAttribute.cpp @@ -477,6 +477,12 @@ UsdAttributeGeneric::create(const UsdSceneItem::Ptr& item, UsdAttributeHolder::U std::string UsdAttributeGeneric::nativeType() const { return UsdAttribute::nativeType(); } +const std::string& UsdAttributeGeneric::nativeSdrTypeMetadata() +{ + static const auto kMetadataName = std::string { "nativeSdrType" }; + return kMetadataName; +} + #ifdef UFE_V4_FEATURES_AVAILABLE //------------------------------------------------------------------------------ // UsdAttributeFilename: diff --git a/lib/mayaUsd/ufe/UsdAttribute.h b/lib/mayaUsd/ufe/UsdAttribute.h index 7e007e7d56..07153fc80c 100644 --- a/lib/mayaUsd/ufe/UsdAttribute.h +++ b/lib/mayaUsd/ufe/UsdAttribute.h @@ -192,6 +192,10 @@ class UsdAttributeGeneric // Ufe::AttributeGeneric overrides std::string nativeType() const override; + + // Metadata used when creating a dynamic attribute on NodeGraph/Material boundaries that + // remembers the native type of a generic shader property. + static const std::string& nativeSdrTypeMetadata(); }; // UsdAttributeGeneric #ifdef UFE_V4_FEATURES_AVAILABLE diff --git a/lib/mayaUsd/ufe/UsdAttributeHolder.cpp b/lib/mayaUsd/ufe/UsdAttributeHolder.cpp index 33aa9407eb..c227fe0926 100644 --- a/lib/mayaUsd/ufe/UsdAttributeHolder.cpp +++ b/lib/mayaUsd/ufe/UsdAttributeHolder.cpp @@ -141,6 +141,17 @@ std::string UsdAttributeHolder::defaultValue() const { return std::string(); } std::string UsdAttributeHolder::nativeType() const { + if (usdAttributeType() == SdfValueTypeNames->Token && PXR_NS::UsdShadeNodeGraph(usdPrim())) { + // We might have saved the Sdr native type as metadata: + if (PXR_NS::UsdShadeInput::IsInput(_usdAttr) + || PXR_NS::UsdShadeOutput::IsOutput(_usdAttr)) { + const auto metaValue = getMetadata(UsdAttributeGeneric::nativeSdrTypeMetadata()); + if (!metaValue.empty() && metaValue.isType()) { + return metaValue.get(); + } + } + } + return usdAttributeType().GetType().GetTypeName(); } diff --git a/lib/mayaUsd/ufe/UsdAttributes.cpp b/lib/mayaUsd/ufe/UsdAttributes.cpp index 2bb0829a1e..054f5ec8c9 100644 --- a/lib/mayaUsd/ufe/UsdAttributes.cpp +++ b/lib/mayaUsd/ufe/UsdAttributes.cpp @@ -373,9 +373,21 @@ Ufe::Attribute::Ptr UsdAttributes::doAddAttribute( } } // Fallback to creating a nodegraph output. - connectApi.CreateOutput(baseNameAndType.first, ufeTypeToUsd(type)); + auto usdType = ufeTypeToUsd(type); + auto output = connectApi.CreateOutput( + baseNameAndType.first, usdType ? usdType : SdfValueTypeNames->Token); + if (!usdType) { + output.SetSdrMetadataByKey( + TfToken(UsdAttributeGeneric::nativeSdrTypeMetadata()), type); + } } else if (baseNameAndType.second == PXR_NS::UsdShadeAttributeType::Input) { - connectApi.CreateInput(baseNameAndType.first, ufeTypeToUsd(type)); + auto usdType = ufeTypeToUsd(type); + auto input = connectApi.CreateInput( + baseNameAndType.first, usdType ? usdType : SdfValueTypeNames->Token); + if (!usdType) { + input.SetSdrMetadataByKey( + TfToken(UsdAttributeGeneric::nativeSdrTypeMetadata()), type); + } } } diff --git a/test/lib/ufe/testConnections.py b/test/lib/ufe/testConnections.py index edbaf8dc4f..d5ae0c9b3b 100644 --- a/test/lib/ufe/testConnections.py +++ b/test/lib/ufe/testConnections.py @@ -37,6 +37,7 @@ def __init__(self): self._removedNotifications = 0 self._valueChangedNotifications = 0 self._connectionChangedNotifications = 0 + self._metadataChangedNotifications = 0 self._unknownNotifications = 0 def __call__(self, notification): @@ -48,6 +49,8 @@ def __call__(self, notification): self._valueChangedNotifications += 1 elif isinstance(notification, ufe.AttributeConnectionChanged): self._connectionChangedNotifications += 1 + elif isinstance(notification, ufe.AttributeMetadataChanged): + self._metadataChangedNotifications += 1 else: self._unknownNotifications += 1 @@ -56,6 +59,7 @@ def assertNotificationCount(self, test, **counters): test.assertEqual(self._removedNotifications, counters.get("numRemoved", 0)) test.assertEqual(self._valueChangedNotifications, counters.get("numValue", 0)) test.assertEqual(self._connectionChangedNotifications, counters.get("numConnection", 0)) + test.assertEqual(self._metadataChangedNotifications, counters.get("numMetadata", 0)) test.assertEqual(self._unknownNotifications, 0) @@ -951,10 +955,32 @@ def testCreateNodeGraphAttributes(self): testObserver.assertNotificationCount(self, numAdded = 1) testAttrs.addAttribute("outputs:bar", ufe.Attribute.kFloat4) testObserver.assertNotificationCount(self, numAdded = 2) + + # Testing custom NodeGraph data types + testAttrs.addAttribute("inputs:edf", "EDF") + # The custom type is saved as metadata, which emits one value and one metadata changes + testObserver.assertNotificationCount(self, numAdded = 3, numValue=1, numMetadata=1) + customAttr = testAttrs.attribute("inputs:edf") + self.assertEqual(customAttr.type, "Generic") + # Make sure the custom shader type was remembered + self.assertEqual(customAttr.nativeType(), "EDF") + + # Same thing, on the output side + testAttrs.addAttribute("outputs:srf", "surfaceshader") + testObserver.assertNotificationCount(self, numAdded = 4, numValue=2, numMetadata=2) + customAttr = testAttrs.attribute("outputs:srf") + self.assertEqual(customAttr.type, "Generic") + self.assertEqual(customAttr.nativeType(), "surfaceshader") + testAttrs.removeAttribute("inputs:foo") - testObserver.assertNotificationCount(self, numAdded = 2, numRemoved = 1) + testObserver.assertNotificationCount(self, numAdded = 4, numRemoved = 1, numValue=2, numMetadata=2) testAttrs.removeAttribute("outputs:bar") - testObserver.assertNotificationCount(self, numAdded = 2, numRemoved = 2) + testObserver.assertNotificationCount(self, numAdded = 4, numRemoved = 2, numValue=2, numMetadata=2) + testAttrs.removeAttribute("inputs:edf") + testObserver.assertNotificationCount(self, numAdded = 4, numRemoved = 3, numValue=2, numMetadata=2) + testAttrs.removeAttribute("outputs:srf") + testObserver.assertNotificationCount(self, numAdded = 4, numRemoved = 4, numValue=2, numMetadata=2) + @unittest.skipUnless(ufeUtils.ufeFeatureSetVersion() >= 4, 'Test only available in UFE v4 or greater') def testCompoundDisplacementPassthrough(self): From 4cf8fd326fe5b39b1239e184eb64ffe8d24b1bb9 Mon Sep 17 00:00:00 2001 From: Jerry Gamache Date: Thu, 18 Jan 2024 17:12:24 -0500 Subject: [PATCH 2/2] Fix Maya 2022 builds --- lib/mayaUsd/ufe/UsdAttributeHolder.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/mayaUsd/ufe/UsdAttributeHolder.cpp b/lib/mayaUsd/ufe/UsdAttributeHolder.cpp index c227fe0926..d4f06a1077 100644 --- a/lib/mayaUsd/ufe/UsdAttributeHolder.cpp +++ b/lib/mayaUsd/ufe/UsdAttributeHolder.cpp @@ -141,6 +141,7 @@ std::string UsdAttributeHolder::defaultValue() const { return std::string(); } std::string UsdAttributeHolder::nativeType() const { +#ifdef UFE_V3_FEATURES_AVAILABLE if (usdAttributeType() == SdfValueTypeNames->Token && PXR_NS::UsdShadeNodeGraph(usdPrim())) { // We might have saved the Sdr native type as metadata: if (PXR_NS::UsdShadeInput::IsInput(_usdAttr) @@ -151,7 +152,7 @@ std::string UsdAttributeHolder::nativeType() const } } } - +#endif return usdAttributeType().GetType().GetTypeName(); }