From b426e29c30d772792114a7ad1bae86279498f121 Mon Sep 17 00:00:00 2001 From: Sean Donnelly <23455376+seando-adsk@users.noreply.github.com> Date: Mon, 11 Jan 2021 14:21:30 -0500 Subject: [PATCH 1/4] MAYA-106780 - Editing USD should mark scene as dirty * Added catch-all condition in response to USD stage changes. If no UFE notif is sent, but we were given paths, send a UFE subtreeInvalidate notif. --- lib/mayaUsd/ufe/StagesSubject.cpp | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/lib/mayaUsd/ufe/StagesSubject.cpp b/lib/mayaUsd/ufe/StagesSubject.cpp index 3c48b3706a..a27f82d722 100644 --- a/lib/mayaUsd/ufe/StagesSubject.cpp +++ b/lib/mayaUsd/ufe/StagesSubject.cpp @@ -192,6 +192,9 @@ void StagesSubject::stageChanged( if (stagePath(sender).empty()) return; +#ifdef UFE_V2_FEATURES_AVAILABLE + bool anyUfeV2NotifSent = false; +#endif auto stage = notice.GetStage(); for (const auto& changedPath : notice.GetResyncedPaths()) { // When visibility is toggled for the first time or you add a xformop we enter @@ -234,6 +237,7 @@ void StagesSubject::stageChanged( if (prim.IsActive()) { #ifdef UFE_V2_FEATURES_AVAILABLE Ufe::Scene::instance().notify(Ufe::ObjectAdd(sceneItem)); + anyUfeV2NotifSent = true; #else auto notification = Ufe::ObjectAdd(sceneItem); Ufe::Scene::notifyObjectAdd(notification); @@ -241,6 +245,7 @@ void StagesSubject::stageChanged( } else { #ifdef UFE_V2_FEATURES_AVAILABLE Ufe::Scene::instance().notify(Ufe::ObjectPostDelete(sceneItem)); + anyUfeV2NotifSent = true; #else auto notification = Ufe::ObjectPostDelete(sceneItem); Ufe::Scene::notifyObjectDelete(notification); @@ -253,6 +258,7 @@ void StagesSubject::stageChanged( // - Resyncs imply entire subtree invalidation of all descendant prims and // properties. So we send the UFE subtree invalidate notif. Ufe::Scene::instance().notify(Ufe::SubtreeInvalidate(sceneItem)); + anyUfeV2NotifSent = true; } #endif } @@ -264,6 +270,7 @@ void StagesSubject::stageChanged( } else { Ufe::Scene::instance().notify(Ufe::SubtreeInvalidate(sceneItem)); } + anyUfeV2NotifSent = true; } #endif } @@ -281,6 +288,7 @@ void StagesSubject::stageChanged( pendingAttributeChangedNotifications[ufePath] = changedPath.GetName(); } else { Ufe::Attributes::notify(ufePath, changedPath.GetName()); + anyUfeV2NotifSent = true; } } @@ -288,6 +296,7 @@ void StagesSubject::stageChanged( if (changedPath.GetNameToken() == UsdGeomTokens->visibility) { Ufe::VisibilityChanged vis(ufePath); Ufe::Object3d::notify(vis); + anyUfeV2NotifSent = true; } #endif @@ -296,9 +305,37 @@ void StagesSubject::stageChanged( const TfToken nameToken = changedPath.GetNameToken(); if (nameToken == UsdGeomTokens->xformOpOrder || UsdGeomXformOp::IsXformOp(nameToken)) { Ufe::Transform3d::notify(ufePath); +#ifdef UFE_V2_FEATURES_AVAILABLE + anyUfeV2NotifSent = true; +#endif + } + } + } + +#ifdef UFE_V2_FEATURES_AVAILABLE + // If we get here and didn't send any UFE notif, but yet have paths + // then we'll send a catch-all subtree invalidate notification. + if (!anyUfeV2NotifSent) { + SdfPathVector allPaths = (SdfPathVector)notice.GetResyncedPaths(); + allPaths.insert( + allPaths.end(), + notice.GetChangedInfoOnlyPaths().begin(), + notice.GetChangedInfoOnlyPaths().end()); + SdfPath::RemoveDescendentPaths(&allPaths); + for (const auto& changedPath : allPaths) { + Ufe::Path ufePath; + if (changedPath == SdfPath::AbsoluteRootPath()) { + ufePath = stagePath(sender); + } else { + const std::string& usdPrimPathStr = changedPath.GetPrimPath().GetString(); + ufePath = stagePath(sender) + Ufe::PathSegment(usdPrimPathStr, g_USDRtid, '/'); } + + auto sceneItem = Ufe::Hierarchy::createItem(ufePath); + Ufe::Scene::instance().notify(Ufe::SubtreeInvalidate(sceneItem)); } } +#endif } #if UFE_PREVIEW_VERSION_NUM >= 2025 From 27a69bfeff650309841b4381510470f3e4a1efff Mon Sep 17 00:00:00 2001 From: Sean Donnelly <23455376+seando-adsk@users.noreply.github.com> Date: Tue, 12 Jan 2021 16:35:29 -0500 Subject: [PATCH 2/4] MAYA-106780 - Editing USD should mark scene as dirty * Reworked to send ufe attribute value changed for the ChangedInfoOnlyPaths (instead of subtreeInvalidate). --- lib/mayaUsd/ufe/StagesSubject.cpp | 66 +++++++++++++++++-------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/lib/mayaUsd/ufe/StagesSubject.cpp b/lib/mayaUsd/ufe/StagesSubject.cpp index a27f82d722..f696fa641d 100644 --- a/lib/mayaUsd/ufe/StagesSubject.cpp +++ b/lib/mayaUsd/ufe/StagesSubject.cpp @@ -192,9 +192,6 @@ void StagesSubject::stageChanged( if (stagePath(sender).empty()) return; -#ifdef UFE_V2_FEATURES_AVAILABLE - bool anyUfeV2NotifSent = false; -#endif auto stage = notice.GetStage(); for (const auto& changedPath : notice.GetResyncedPaths()) { // When visibility is toggled for the first time or you add a xformop we enter @@ -237,7 +234,6 @@ void StagesSubject::stageChanged( if (prim.IsActive()) { #ifdef UFE_V2_FEATURES_AVAILABLE Ufe::Scene::instance().notify(Ufe::ObjectAdd(sceneItem)); - anyUfeV2NotifSent = true; #else auto notification = Ufe::ObjectAdd(sceneItem); Ufe::Scene::notifyObjectAdd(notification); @@ -245,7 +241,6 @@ void StagesSubject::stageChanged( } else { #ifdef UFE_V2_FEATURES_AVAILABLE Ufe::Scene::instance().notify(Ufe::ObjectPostDelete(sceneItem)); - anyUfeV2NotifSent = true; #else auto notification = Ufe::ObjectPostDelete(sceneItem); Ufe::Scene::notifyObjectDelete(notification); @@ -258,7 +253,6 @@ void StagesSubject::stageChanged( // - Resyncs imply entire subtree invalidation of all descendant prims and // properties. So we send the UFE subtree invalidate notif. Ufe::Scene::instance().notify(Ufe::SubtreeInvalidate(sceneItem)); - anyUfeV2NotifSent = true; } #endif } @@ -270,7 +264,6 @@ void StagesSubject::stageChanged( } else { Ufe::Scene::instance().notify(Ufe::SubtreeInvalidate(sceneItem)); } - anyUfeV2NotifSent = true; } #endif } @@ -280,6 +273,8 @@ void StagesSubject::stageChanged( auto ufePath = stagePath(sender) + Ufe::PathSegment(usdPrimPathStr, g_USDRtid, '/'); #ifdef UFE_V2_FEATURES_AVAILABLE + bool sendValueChangedFallback = true; + // isPrimPropertyPath() does not consider relational attributes // isPropertyPath() does consider relational attributes // isRelationalAttributePath() considers only relational attributes @@ -287,16 +282,21 @@ void StagesSubject::stageChanged( if (inAttributeChangedNotificationGuard()) { pendingAttributeChangedNotifications[ufePath] = changedPath.GetName(); } else { +#if UFE_PREVIEW_VERSION_NUM >= 2036 + Ufe::AttributeValueChanged vc(ufePath, changedPath.GetName()); + Ufe::Attributes::notify(vc); +#else Ufe::Attributes::notify(ufePath, changedPath.GetName()); - anyUfeV2NotifSent = true; +#endif } + sendValueChangedFallback = false; } // Send a special message when visibility has changed. if (changedPath.GetNameToken() == UsdGeomTokens->visibility) { Ufe::VisibilityChanged vis(ufePath); Ufe::Object3d::notify(vis); - anyUfeV2NotifSent = true; + sendValueChangedFallback = false; } #endif @@ -306,36 +306,39 @@ void StagesSubject::stageChanged( if (nameToken == UsdGeomTokens->xformOpOrder || UsdGeomXformOp::IsXformOp(nameToken)) { Ufe::Transform3d::notify(ufePath); #ifdef UFE_V2_FEATURES_AVAILABLE - anyUfeV2NotifSent = true; + sendValueChangedFallback = false; #endif } } - } #ifdef UFE_V2_FEATURES_AVAILABLE - // If we get here and didn't send any UFE notif, but yet have paths - // then we'll send a catch-all subtree invalidate notification. - if (!anyUfeV2NotifSent) { - SdfPathVector allPaths = (SdfPathVector)notice.GetResyncedPaths(); - allPaths.insert( - allPaths.end(), - notice.GetChangedInfoOnlyPaths().begin(), - notice.GetChangedInfoOnlyPaths().end()); - SdfPath::RemoveDescendentPaths(&allPaths); - for (const auto& changedPath : allPaths) { - Ufe::Path ufePath; - if (changedPath == SdfPath::AbsoluteRootPath()) { - ufePath = stagePath(sender); + if (sendValueChangedFallback) { + // We didn't send any other UFE notif above, so send a UFE + // attribute value changed as a fallback notification. + if (inAttributeChangedNotificationGuard()) { + pendingAttributeChangedNotifications[ufePath] = changedPath.GetName(); } else { - const std::string& usdPrimPathStr = changedPath.GetPrimPath().GetString(); - ufePath = stagePath(sender) + Ufe::PathSegment(usdPrimPathStr, g_USDRtid, '/'); +#if UFE_PREVIEW_VERSION_NUM >= 2036 + Ufe::AttributeValueChanged vc(ufePath, changedPath.GetName()); + Ufe::Attributes::notify(vc); +#else + Ufe::Attributes::notify(ufePath, changedPath.GetName()); +#endif } - - auto sceneItem = Ufe::Hierarchy::createItem(ufePath); - Ufe::Scene::instance().notify(Ufe::SubtreeInvalidate(sceneItem)); } +#endif + } + +#ifdef UFE_V2_FEATURES_AVAILABLE +#if UFE_PREVIEW_VERSION_NUM >= 2036 + // Special case when we are notified, but no paths given. + if (notice.GetResyncedPaths().empty() && notice.GetChangedInfoOnlyPaths().empty()) { + auto ufePath = stagePath(sender); + Ufe::AttributeValueChanged vc(ufePath, "/"); + Ufe::Attributes::notify(vc); } #endif +#endif } #if UFE_PREVIEW_VERSION_NUM >= 2025 @@ -424,7 +427,12 @@ AttributeChangedNotificationGuard::~AttributeChangedNotificationGuard() } for (const auto& notificationInfo : pendingAttributeChangedNotifications) { +#if UFE_PREVIEW_VERSION_NUM >= 2036 + Ufe::AttributeValueChanged vc(notificationInfo.first, notificationInfo.second); + Ufe::Attributes::notify(vc); +#else Ufe::Attributes::notify(notificationInfo.first, notificationInfo.second); +#endif } pendingAttributeChangedNotifications.clear(); From 91bc45c63fd51a6d678d74036874fb2c3e4a7ddf Mon Sep 17 00:00:00 2001 From: Sean Donnelly <23455376+seando-adsk@users.noreply.github.com> Date: Wed, 13 Jan 2021 08:59:50 -0500 Subject: [PATCH 3/4] MAYA-106780 - Editing USD should mark scene as dirty * Oops forgot to commit test --- test/lib/ufe/testAttribute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/ufe/testAttribute.py b/test/lib/ufe/testAttribute.py index 62da8cd5fd..6f8eb56e91 100644 --- a/test/lib/ufe/testAttribute.py +++ b/test/lib/ufe/testAttribute.py @@ -32,7 +32,7 @@ def __init__(self): self._notifications = 0 def __call__(self, notification): - if isinstance(notification, ufe.AttributeChanged): + if isinstance(notification, ufe.AttributeValueChanged): self._notifications += 1 @property From a6bea325ffa67ad1ccee748de766930ff0a70fd7 Mon Sep 17 00:00:00 2001 From: Sean Donnelly <23455376+seando-adsk@users.noreply.github.com> Date: Wed, 13 Jan 2021 10:55:03 -0500 Subject: [PATCH 4/4] MAYA-106780 - Editing USD should mark scene as dirty * Fixed mistake in test for older UFE version. --- test/lib/ufe/testAttribute.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/lib/ufe/testAttribute.py b/test/lib/ufe/testAttribute.py index 6f8eb56e91..0dddf45b8d 100644 --- a/test/lib/ufe/testAttribute.py +++ b/test/lib/ufe/testAttribute.py @@ -16,6 +16,8 @@ # limitations under the License. # +import os + import usdUtils, mayaUtils, testUtils import ufe from pxr import UsdGeom @@ -32,8 +34,12 @@ def __init__(self): self._notifications = 0 def __call__(self, notification): - if isinstance(notification, ufe.AttributeValueChanged): - self._notifications += 1 + if(os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') >= '2036'): + if isinstance(notification, ufe.AttributeValueChanged): + self._notifications += 1 + else: + if isinstance(notification, ufe.AttributeChanged): + self._notifications += 1 @property def notifications(self):