From 19990442267ef5aa89b4288a87d018772d2432b6 Mon Sep 17 00:00:00 2001 From: Pierre Tremblay Date: Wed, 6 Nov 2024 14:34:54 -0500 Subject: [PATCH] Moved isolate select scene index creation to avoid losing isolate selection. --- lib/mayaHydra/mayaPlugin/renderOverride.cpp | 30 ++-- .../mayaUsd/render/mayaToHydra/CMakeLists.txt | 1 + ...testUsdPointInstancingIsolateSelectBBox.py | 169 ++++++++++++++++++ 3 files changed, 186 insertions(+), 14 deletions(-) create mode 100644 test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancingIsolateSelectBBox.py diff --git a/lib/mayaHydra/mayaPlugin/renderOverride.cpp b/lib/mayaHydra/mayaPlugin/renderOverride.cpp index 09390f0cd..ac97df753 100644 --- a/lib/mayaHydra/mayaPlugin/renderOverride.cpp +++ b/lib/mayaHydra/mayaPlugin/renderOverride.cpp @@ -1096,6 +1096,22 @@ void MtohRenderOverride::_InitHydraResources(const MHWRender::MDrawContext& draw _dirtyLeadObjectSceneIndex = MAYAHYDRA_NS::MhDirtyLeadObjectSceneIndex::New(_inputSceneIndexOfFilteringSceneIndicesChain); _inputSceneIndexOfFilteringSceneIndicesChain = _dirtyLeadObjectSceneIndex; +#ifdef MAYA_HAS_VIEW_SELECTED_OBJECT_API + // _InitHydraResources() is always called from Render(), so + // getFrameContext() will be valid and non-null. + auto viewportId = getRenderingDestination(getFrameContext()); + + // Add isolate select scene index. + auto& perVpDataMgr = Fvp::ViewportDataMgr::Get(); + auto selection = perVpDataMgr.GetOrCreateIsolateSelection(viewportId); + auto isSi = Fvp::IsolateSelectSceneIndex::New( + viewportId, selection, _inputSceneIndexOfFilteringSceneIndicesChain); + // At time of writing we have a single selection scene index serving + // all viewports. + perVpDataMgr.SetIsolateSelectSceneIndex(isSi); + _inputSceneIndexOfFilteringSceneIndicesChain = isSi; +#endif + // Set the initial selection onto the selection scene index later. _needToReplaceSelection = true; @@ -1203,21 +1219,7 @@ void MtohRenderOverride::_CreateSceneIndicesChainAfterMergingSceneIndex(const MH { //This function is where happens the ordering of filtering scene indices that are after the merging scene index //We use as its input scene index : _inputSceneIndexOfFilteringSceneIndicesChain -#ifdef MAYA_HAS_VIEW_SELECTED_OBJECT_API - auto viewportId = getRenderingDestination(getFrameContext()); - - // Add isolate select scene index. - auto& perVpDataMgr = Fvp::ViewportDataMgr::Get(); - auto selection = perVpDataMgr.GetOrCreateIsolateSelection(viewportId); - auto isSi = Fvp::IsolateSelectSceneIndex::New( - viewportId, selection, _inputSceneIndexOfFilteringSceneIndicesChain); - // At time of writing we have a single selection scene index serving - // all viewports. - perVpDataMgr.SetIsolateSelectSceneIndex(isSi); - _lastFilteringSceneIndexBeforeCustomFiltering = isSi; -#else _lastFilteringSceneIndexBeforeCustomFiltering = _inputSceneIndexOfFilteringSceneIndicesChain; -#endif // Add display style scene index _lastFilteringSceneIndexBeforeCustomFiltering = _displayStyleSceneIndex = diff --git a/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt b/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt index 3b119028c..68c7aa0ea 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt +++ b/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt @@ -90,6 +90,7 @@ if (MAYA_HAS_VIEW_SELECTED_OBJECT_API) cpp/testIsolateSelect.py cpp/testUsdNativeInstancingIsolateSelect.py cpp/testUsdPointInstancingIsolateSelect.py + cpp/testUsdPointInstancingIsolateSelectBBox.py ) endif() diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancingIsolateSelectBBox.py b/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancingIsolateSelectBBox.py new file mode 100644 index 000000000..3c84bbecc --- /dev/null +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testUsdPointInstancingIsolateSelectBBox.py @@ -0,0 +1,169 @@ +# Copyright 2024 Autodesk +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import fixturesUtils +import mtohUtils +import mayaUsd +import mayaUsd_createStageWithNewLayer +import maya.cmds as cmds +import maya.mel as mel +import usdUtils +from pxr import UsdGeom +import testUtils + +def enableIsolateSelect(modelPanel): + # Surprisingly + # + # cmds.isolateSelect('modelPanel1', state=1) + # + # is insufficient to turn on isolate selection in a viewport, and we must + # use the MEL script used by the menu and Ctrl-1 hotkey. This is because + # the viewport uses the selectionConnection command to filter the selection + # it receives and create its isolate selection, and the the + # mainListConnection, lockMainConnection and unlockMainConnection flags of + # the editor command to suspend changes to its selection connection. See + # the documentation for more details. + cmds.setFocus(modelPanel) + mel.eval("enableIsolateSelect %s 1" % modelPanel) + +def disableIsolateSelect(modelPanel): + cmds.setFocus(modelPanel) + mel.eval("enableIsolateSelect %s 0" % modelPanel) + +# This test is identical to the one in testIsolateSelect.py, except for +# disabled tests. See HYDRA-1245. + +class TestUsdPointInstancingIsolateSelectBBox(mtohUtils.MayaHydraBaseTestCase): + # MayaHydraBaseTestCase.setUpClass requirement. + _file = __file__ + + # Base class setUp() defines HdStorm as the renderer. + + _pluginsToLoad = ['mayaHydraCppTests', 'mayaHydraFlowViewportAPILocator'] + _pluginsToUnload = [] + + @classmethod + def setUpClass(cls): + super(TestUsdPointInstancingIsolateSelectBBox, cls).setUpClass() + for p in cls._pluginsToLoad: + if not cmds.pluginInfo(p, q=True, loaded=True): + cls._pluginsToUnload.append(p) + cmds.loadPlugin(p, quiet=True) + + @classmethod + def tearDownClass(cls): + super(TestUsdPointInstancingIsolateSelectBBox, cls).tearDownClass() + # Clean out the scene to allow all plugins to unload cleanly. + cmds.file(new=True, force=True) + for p in reversed(cls._pluginsToUnload): + if p != 'mayaHydraFlowViewportAPILocator': + cmds.unloadPlugin(p) + + def setupScene(self): + self.proxyShapePathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer() + stage = mayaUsd.lib.GetPrim(self.proxyShapePathStr).GetStage() + + # Add in a point instancer and its point instances. + ref = stage.DefinePrim('/ref') + piScenePath = testUtils.getTestScene('testUsdPointInstances', 'pointInstancer.usda') + ref.GetReferences().AddReference(str(piScenePath)) + self.pointInstancerPath = self.proxyShapePathStr + ',/ref/CubePointInstancer' + + scene = [self.pointInstancerPath] + + # Point instances + for i in range(0, 14): + scene.append(self.pointInstancerPath + ('/%s' % i)) + + return scene + + def assertVisible(self, visible): + for v in visible: + self.trace("Testing %s for visibility\n" % v) + cmds.mayaHydraCppTest(v, f="TestHydraPrim.isVisible") + + def assertNotVisible(self, notVisible): + for nv in notVisible: + self.trace("Testing %s for invisibility\n" % nv) + cmds.mayaHydraCppTest(nv, f="TestHydraPrim.notVisible") + + def assertVisibility(self, visible, notVisible): + self.assertVisible(visible) + self.assertNotVisible(notVisible) + + def assertIsolateSelect(self, modelPanel, visible, scene): + cmds.select(*visible) + cmds.editor(modelPanel, edit=True, updateMainConnection=True) + cmds.isolateSelect(modelPanel, loadSelected=True) + + notVisible = scene.copy() + + for p in visible: + notVisible.remove(p) + + cmds.refresh() + + self.assertVisibility(visible, notVisible) + + def notVisible(self, scene, visible): + notVisible = scene.copy() + + for p in visible: + notVisible.remove(p) + + return notVisible + + def test_isolateSelectPointInstancing(self): + + scene = self.setupScene() + + cmds.select(clear=True) + + # Isolate select not turned on, everything visible. + visible = scene + notVisible = [] + + cmds.refresh() + + self.assertVisibility(visible, notVisible) + + # Turn isolate select on, nothing selected, nothing visible. + visible = [] + notVisible = scene + + modelPanel = 'modelPanel4' + enableIsolateSelect(modelPanel) + + cmds.refresh() + + self.assertVisibility(visible, notVisible) + + # Select various point instances. The instancer itself will be visible, + # everything else not visible. + visible = [ + self.pointInstancerPath, self.pointInstancerPath + '/0', + self.pointInstancerPath + '/3', self.pointInstancerPath + '/12'] + self.assertIsolateSelect(modelPanel, visible, scene) + + cmds.modelEditor(modelPanel, edit=True, displayAppearance='boundingBox') + + cmds.refresh() + + self.assertVisibility(visible, self.notVisible(scene, visible)) + + disableIsolateSelect(modelPanel) + +if __name__ == '__main__': + fixturesUtils.runTests(globals())