From 9cdbf386d70df48f0bab1921f33a67d0c1eb90bd Mon Sep 17 00:00:00 2001 From: deboisj Date: Wed, 9 Aug 2023 09:06:58 -0400 Subject: [PATCH 1/3] Compute the effective visibility to decide on visibility toggle label and operation. --- lib/usdUfe/ufe/UsdContextOps.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/usdUfe/ufe/UsdContextOps.cpp b/lib/usdUfe/ufe/UsdContextOps.cpp index 0fa7380a5a..038384f598 100644 --- a/lib/usdUfe/ufe/UsdContextOps.cpp +++ b/lib/usdUfe/ufe/UsdContextOps.cpp @@ -295,10 +295,13 @@ Ufe::ContextOps::Items UsdContextOps::getItems(const Ufe::ContextOps::ItemPath& if (object3dHndlr) { auto object3d = object3dHndlr->object3d(sceneItem()); if (object3d) { - auto visibility = object3d->visibility(); - const auto l = visibility ? std::string(kUSDMakeInvisibleLabel) - : std::string(kUSDMakeVisibleLabel); - items.emplace_back(kUSDToggleVisibilityItem, l); + // Don't actually use UsdObject3d::visibility() - it looks at the authored visibility + // attribute. Instead, compute the effective visibility to decide on the label to use. + const auto imageable = UsdGeomImageable(prim()); + const auto visibility = imageable.ComputeVisibility() != UsdGeomTokens->invisible; + const auto label = visibility ? std::string(kUSDMakeInvisibleLabel) + : std::string(kUSDMakeVisibleLabel); + items.emplace_back(kUSDToggleVisibilityItem, label); } } // Prim active state: @@ -433,7 +436,11 @@ Ufe::UndoableCommand::Ptr UsdContextOps::doOpCmd(const ItemPath& itemPath) auto object3d = UsdObject3d::create(fItem); if (!TF_VERIFY(object3d)) return nullptr; - auto current = object3d->visibility(); + // Don't use UsdObject3d::visibility() - it looks at the authored visibility + // attribute. Instead, compute the effective visibility, which is what we want + // to toggle. + const auto imageable = UsdGeomImageable(prim()); + const auto current = imageable.ComputeVisibility() != UsdGeomTokens->invisible; return object3d->setVisibleCmd(!current); } // Visibility else if (itemPath[0] == kUSDToggleActiveStateItem) { From 3ece34138b9b6b5d05b9748a705a148a00b00238 Mon Sep 17 00:00:00 2001 From: deboisj Date: Wed, 9 Aug 2023 10:19:36 -0400 Subject: [PATCH 2/3] Expose isRootChild as DCC function. --- lib/usdUfe/ufe/Global.cpp | 2 ++ lib/usdUfe/ufe/Global.h | 1 + lib/usdUfe/ufe/Utils.cpp | 35 ++++++++++++++++++++++++----------- lib/usdUfe/ufe/Utils.h | 14 ++++++++++++++ 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/usdUfe/ufe/Global.cpp b/lib/usdUfe/ufe/Global.cpp index c691292ff1..d3d85e1d68 100644 --- a/lib/usdUfe/ufe/Global.cpp +++ b/lib/usdUfe/ufe/Global.cpp @@ -75,6 +75,8 @@ Ufe::Rtid initialize( UsdUfe::setIsAttributeLockedFn(dccFunctions.isAttributeLockedFn); if (dccFunctions.saveStageLoadRulesFn) UsdUfe::setSaveStageLoadRulesFn(dccFunctions.saveStageLoadRulesFn); + if (dccFunctions.isRootChildFn) + UsdUfe::setIsRootChildFn(dccFunctions.isRootChildFn); // Create a default stages subject if none is provided. if (nullptr == ss) { diff --git a/lib/usdUfe/ufe/Global.h b/lib/usdUfe/ufe/Global.h index 73fd2bb381..d42b4f4f43 100644 --- a/lib/usdUfe/ufe/Global.h +++ b/lib/usdUfe/ufe/Global.h @@ -46,6 +46,7 @@ struct USDUFE_PUBLIC DCCFunctions // Optional: default values will be used if no function is supplied. IsAttributeLockedFn isAttributeLockedFn = nullptr; SaveStageLoadRulesFn saveStageLoadRulesFn = nullptr; + IsRootChildFn isRootChildFn = nullptr; }; /*! Ufe runtime handlers used to initialize the plugin. diff --git a/lib/usdUfe/ufe/Utils.cpp b/lib/usdUfe/ufe/Utils.cpp index 56cacf308b..f1588c3aee 100644 --- a/lib/usdUfe/ufe/Utils.cpp +++ b/lib/usdUfe/ufe/Utils.cpp @@ -90,6 +90,7 @@ UsdUfe::UfePathToPrimFn gUfePathToPrimFn = nullptr; UsdUfe::TimeAccessorFn gTimeAccessorFn = nullptr; UsdUfe::IsAttributeLockedFn gIsAttributeLockedFn = nullptr; UsdUfe::SaveStageLoadRulesFn gSaveStageLoadRulesFn = nullptr; +UsdUfe::IsRootChildFn gIsRootChildFn = nullptr; } // anonymous namespace @@ -231,6 +232,29 @@ void saveStageLoadRules(const PXR_NS::UsdStageRefPtr& stage) gSaveStageLoadRulesFn(stage); } +void setIsRootChildFn(IsRootChildFn fn) +{ + // This function is allowed to be null in which case, the default implementation + // is used (isRootChildDefault()). + gIsRootChildFn = fn; +} + +bool isRootChild(const Ufe::Path& path) +{ + return gIsRootChildFn ? gIsRootChildFn(path) : isRootChildDefault(path); +} + +bool isRootChildDefault(const Ufe::Path& path) +{ + // When called we make the assumption that we are given a valid + // path and we are only testing whether or not we are a root child. + auto segments = path.getSegments(); + if (segments.size() != 2) { + TF_RUNTIME_ERROR(kIllegalUFEPath, path.string().c_str()); + } + return (segments[1].size() == 1); +} + int ufePathToInstanceIndex(const Ufe::Path& path, UsdPrim* prim) { int instanceIndex = UsdImagingDelegate::ALL_INSTANCES; @@ -254,17 +278,6 @@ int ufePathToInstanceIndex(const Ufe::Path& path, UsdPrim* prim) return instanceIndex; } -bool isRootChild(const Ufe::Path& path) -{ - // When called we make the assumption that we are given a valid - // path and we are only testing whether or not we are a root child. - auto segments = path.getSegments(); - if (segments.size() != 2) { - TF_RUNTIME_ERROR(kIllegalUFEPath, path.string().c_str()); - } - return (segments[1].size() == 1); -} - std::string uniqueName(const TfToken::HashSet& existingNames, std::string srcName) { // Compiled regular expression to find a numerical suffix to a path component. diff --git a/lib/usdUfe/ufe/Utils.h b/lib/usdUfe/ufe/Utils.h index f656ceac47..eb0f856040 100644 --- a/lib/usdUfe/ufe/Utils.h +++ b/lib/usdUfe/ufe/Utils.h @@ -44,6 +44,7 @@ typedef PXR_NS::UsdPrim (*UfePathToPrimFn)(const Ufe::Path&); typedef PXR_NS::UsdTimeCode (*TimeAccessorFn)(const Ufe::Path&); typedef bool (*IsAttributeLockedFn)(const PXR_NS::UsdAttribute& attr, std::string* errMsg); typedef void (*SaveStageLoadRulesFn)(const PXR_NS::UsdStageRefPtr&); +typedef bool (*IsRootChildFn)(const Ufe::Path& path); //------------------------------------------------------------------------------ // Helper functions @@ -137,9 +138,22 @@ void saveStageLoadRules(const PXR_NS::UsdStageRefPtr& stage); USDUFE_PUBLIC int ufePathToInstanceIndex(const Ufe::Path& path, PXR_NS::UsdPrim* prim = nullptr); +//! Set the DCC specific "isRootChild" test function. +//! Use of this function is optional, if one is not supplied then +//! a default implementation of isRootChild is used.. +USDUFE_PUBLIC +void setIsRootChildFn(IsRootChildFn fn); + +//! Returns true if the path corresponds to an item at the root of a runtime. +//! Implementation can be set by the DCC. USDUFE_PUBLIC bool isRootChild(const Ufe::Path& path); +//! Default isRootChild() implementation. Assumes 2 segments. Will report a root child +//! if the second segment has a single component. +USDUFE_PUBLIC +bool isRootChildDefault(const Ufe::Path& path); + //! Split the source name into a base name and a numerical suffix (set to //! 1 if absent). Increment the numerical suffix until name is unique. USDUFE_PUBLIC From 669c5eb5c5b8c8578bef4f5fc0d0ae15209fa7d1 Mon Sep 17 00:00:00 2001 From: deboisj Date: Wed, 9 Aug 2023 11:01:23 -0400 Subject: [PATCH 3/3] Linter. --- lib/usdUfe/ufe/Global.h | 2 +- lib/usdUfe/ufe/UsdContextOps.cpp | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/usdUfe/ufe/Global.h b/lib/usdUfe/ufe/Global.h index d42b4f4f43..a0126ba731 100644 --- a/lib/usdUfe/ufe/Global.h +++ b/lib/usdUfe/ufe/Global.h @@ -46,7 +46,7 @@ struct USDUFE_PUBLIC DCCFunctions // Optional: default values will be used if no function is supplied. IsAttributeLockedFn isAttributeLockedFn = nullptr; SaveStageLoadRulesFn saveStageLoadRulesFn = nullptr; - IsRootChildFn isRootChildFn = nullptr; + IsRootChildFn isRootChildFn = nullptr; }; /*! Ufe runtime handlers used to initialize the plugin. diff --git a/lib/usdUfe/ufe/UsdContextOps.cpp b/lib/usdUfe/ufe/UsdContextOps.cpp index 038384f598..6fa8dbc65a 100644 --- a/lib/usdUfe/ufe/UsdContextOps.cpp +++ b/lib/usdUfe/ufe/UsdContextOps.cpp @@ -295,12 +295,14 @@ Ufe::ContextOps::Items UsdContextOps::getItems(const Ufe::ContextOps::ItemPath& if (object3dHndlr) { auto object3d = object3dHndlr->object3d(sceneItem()); if (object3d) { - // Don't actually use UsdObject3d::visibility() - it looks at the authored visibility - // attribute. Instead, compute the effective visibility to decide on the label to use. + // Don't actually use UsdObject3d::visibility() - it looks at the authored + // visibility attribute. Instead, compute the effective visibility to decide on + // the label to use. const auto imageable = UsdGeomImageable(prim()); - const auto visibility = imageable.ComputeVisibility() != UsdGeomTokens->invisible; + const auto visibility + = imageable.ComputeVisibility() != UsdGeomTokens->invisible; const auto label = visibility ? std::string(kUSDMakeInvisibleLabel) - : std::string(kUSDMakeVisibleLabel); + : std::string(kUSDMakeVisibleLabel); items.emplace_back(kUSDToggleVisibilityItem, label); } }