diff --git a/lib/usdUfe/ufe/StagesSubject.cpp b/lib/usdUfe/ufe/StagesSubject.cpp index 6d774792f3..0b333ef17b 100644 --- a/lib/usdUfe/ufe/StagesSubject.cpp +++ b/lib/usdUfe/ufe/StagesSubject.cpp @@ -528,6 +528,24 @@ void StagesSubject::stageChanged( Ufe::SceneItem::Ptr sceneItem = Ufe::Hierarchy::createItem(ufePath); if (!sceneItem || InAddOrDeleteOperation::inAddOrDeleteOperation()) { sendObjectDestroyed(ufePath); + + // If we are not in an add or delete operation, and a prim is + // removed, we need to trigger a subtree invalidation. This is + // necessary in order to prevent stale items from being kept in + // the global selection set. + if (!InAddOrDeleteOperation::inAddOrDeleteOperation()) { + auto parentPath = changedPath.GetParentPath(); + const auto parentUfePath = parentPath == SdfPath::AbsoluteRootPath() + ? stagePath(sender) + : stagePath(sender) + + Ufe::PathSegment( + parentPath.GetString(), UsdUfe::getUsdRunTimeId(), '/'); + + auto parentItem = Ufe::Hierarchy::createItem(parentUfePath); + if (parentItem) { + sendSubtreeInvalidate(parentItem); + } + } } else { sendSubtreeInvalidate(sceneItem); } diff --git a/test/lib/ufe/testSelection.py b/test/lib/ufe/testSelection.py index 085839d466..2132e068b7 100644 --- a/test/lib/ufe/testSelection.py +++ b/test/lib/ufe/testSelection.py @@ -307,7 +307,7 @@ def testMayaSelectAddFirst(self): for sel, expected in zip(globalSn, reversedItems): self.assertEqual(sel, expected) - @unittest.skipUnless(mayaUtils.mayaMajorVersion() >= 2023, 'Requires Maya fixes only avaiable in Maya 2023 or greater.') + @unittest.skipUnless(mayaUtils.mayaMajorVersion() >= 2023, 'Requires Maya fixes only available in Maya 2023 or greater.') def testMayaSelectMuteLayer(self): '''Stale selection items must be removed on mute layer.''' @@ -382,6 +382,37 @@ def testMayaSelectMuteLayer(self): self.assertTrue(sn.empty()) + @unittest.skipUnless(mayaUtils.mayaMajorVersion() >= 2023, 'Requires Maya fixes only available in Maya 2023 or greater.') + def testMayaSelectRemoveSelectedPrim(self): + '''Stale selection items must be removed when a prim is deleted''' + + # Create new stage + import mayaUsd_createStageWithNewLayer + proxyShapePathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer() + proxyShapePath = ufe.PathString.path(proxyShapePathStr) + proxyShapeItem = ufe.Hierarchy.createItem(proxyShapePath) + proxyShapeContextOps = ufe.ContextOps.contextOps(proxyShapeItem) + stage = mayaUsd.lib.GetPrim(proxyShapePathStr).GetStage() + + # Create a prim that we will delete + proxyShapeContextOps.doOp(['Add New Prim', 'Capsule']) + + capsulePathStr = '%s,/Capsule1' % proxyShapePathStr + capsulePath = ufe.PathString.path(capsulePathStr) + capsuleItem = ufe.Hierarchy.createItem(capsulePath) + + # Select the prim. When the prim is removed from the stage the prim + # should be removed from the global selection + sn = ufe.GlobalSelection.get() + sn.clear() + sn.append(capsuleItem) + self.assertTrue(sn.contains(capsulePath)) + + stage.RemovePrim("/Capsule1") + + # Should be nothing on the selection list. + self.assertTrue(sn.empty()) + @unittest.skipUnless(mayaUtils.mayaMajorVersion() >= 2023, 'Requires Maya fixes only available in Maya 2023 or greater.') def testMayaSelectSwitchVariant(self): '''Stale selection items must be removed on variant switch.'''