From 9bbe85dbe4648d6195179d3800a981033f9e8efe Mon Sep 17 00:00:00 2001 From: ppt-adsk Date: Tue, 12 Nov 2024 09:50:08 -0500 Subject: [PATCH] Fixed selection highlighting removed on Maya object by isolate select. (#198) --- .../sceneIndex/mayaHydraSceneIndex.cpp | 5 +- .../mayaUsd/render/mayaToHydra/CMakeLists.txt | 1 + .../render/mayaToHydra/cpp/CMakeLists.txt | 1 + ...tIsolateSelectMayaSelectionHighlighting.py | 181 ++++++++++++++++++ .../render/mayaToHydra/cpp/testPrimPath.cpp | 82 ++++++++ 5 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 test/lib/mayaUsd/render/mayaToHydra/cpp/testIsolateSelectMayaSelectionHighlighting.py create mode 100644 test/lib/mayaUsd/render/mayaToHydra/cpp/testPrimPath.cpp diff --git a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraSceneIndex.cpp b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraSceneIndex.cpp index 79ed62f64..af577d15f 100644 --- a/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraSceneIndex.cpp +++ b/lib/mayaHydra/hydraExtensions/sceneIndex/mayaHydraSceneIndex.cpp @@ -478,7 +478,10 @@ class MayaPathMapper : public Fvp::PathMapper Fvp::PrimSelections UfePathToPrimSelections(const Ufe::Path& appPath) const override { - return _piSi.UfePathToPrimSelectionsLit(appPath); + auto litPaths = _piSi.UfePathToPrimSelectionsLit(appPath); + auto unlitPaths = _piSi.UfePathToPrimSelections(appPath); + unlitPaths.insert(unlitPaths.end(), litPaths.begin(), litPaths.end()); + return unlitPaths; } private: diff --git a/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt b/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt index 68c7aa0ea..ffb908984 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt +++ b/test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt @@ -88,6 +88,7 @@ set(INTERACTIVE_TEST_SCRIPT_FILES if (MAYA_HAS_VIEW_SELECTED_OBJECT_API) list(APPEND INTERACTIVE_TEST_SCRIPT_FILES cpp/testIsolateSelect.py + cpp/testIsolateSelectMayaSelectionHighlighting.py cpp/testUsdNativeInstancingIsolateSelect.py cpp/testUsdPointInstancingIsolateSelect.py cpp/testUsdPointInstancingIsolateSelectBBox.py diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt b/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt index 0bfd7a13e..fd8022981 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${TARGET_NAME} testMayaUsdUfeItems.cpp testMergingSceneIndex.cpp testPathInterface.cpp + testPrimPath.cpp testSelectionSceneIndex.cpp testUtils.cpp testWireframeSelectionHighlightSceneIndex.cpp diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testIsolateSelectMayaSelectionHighlighting.py b/test/lib/mayaUsd/render/mayaToHydra/cpp/testIsolateSelectMayaSelectionHighlighting.py new file mode 100644 index 000000000..9cf521671 --- /dev/null +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testIsolateSelectMayaSelectionHighlighting.py @@ -0,0 +1,181 @@ +# 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 maya.cmds as cmds +import maya.mel as mel + +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 very similar to testIsolateSelect.py. See HYDRA-1245. + +class TestIsolateSelectMayaSelectionHighlighting(mtohUtils.MayaHydraBaseTestCase): + # MayaHydraBaseTestCase.setUpClass requirement. + _file = __file__ + + # Base class setUp() defines HdStorm as the renderer. + + _pluginsToLoad = ['mayaHydraCppTests'] + _pluginsToUnload = [] + + @classmethod + def setUpClass(cls): + super(TestIsolateSelectMayaSelectionHighlighting, 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(TestIsolateSelectMayaSelectionHighlighting, 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): + cmds.unloadPlugin(p) + + def setupScene(self): + + cmds.polyTorus() + cmds.polySphere() + cmds.move(2, 0, 0, r=True) + cmds.polyCube() + cmds.move(-2, 0, 0, r=True) + cmds.group('pSphere1', 'pCube1') + cmds.move(0, 0, 2, r=True) + + cmds.refresh() + + scene = [ + # Maya objects + '|pTorus1', + '|pTorus1|pTorusShape1', + '|group1', + '|group1|pSphere1', + '|group1|pSphere1|pSphereShape1', + '|group1|pCube1', + '|group1|pCube1|pCubeShape1'] + + 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 test_isolateSelectMayaSelectionHighlighting(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) + + # Now select Maya objects and check both object and selection + # highlighting visibility. + cmds.select('|pTorus1') + cmds.editor(modelPanel, edit=True, updateMainConnection=True) + cmds.isolateSelect(modelPanel, loadSelected=True) + + cmds.refresh() + + cmds.mayaHydraCppTest('/MayaHydraViewportRenderer/rprims/pTorus1', + f='TestPrimPath.isVisible'); + cmds.mayaHydraCppTest('/MayaHydraViewportRenderer/rprims/Lighted/pTorus1', + f='TestPrimPath.isVisible'); + cmds.mayaHydraCppTest('/MayaHydraViewportRenderer/rprims/Lighted/group1', + f='TestPrimPath.notVisible'); + + cmds.select('|group1') + cmds.editor(modelPanel, edit=True, updateMainConnection=True) + cmds.isolateSelect(modelPanel, loadSelected=True) + + cmds.refresh() + + # It appears that when selection is made once on a Maya object, its + # selection highlighting (its DormantPolyWire render item) is kept, but + # made invisible. We therefore cannot test for selection highlighting + # prim existence, and must rather test for invisibility. + cmds.mayaHydraCppTest('/MayaHydraViewportRenderer/rprims/pTorus1', + f='TestPrimPath.notVisible'); + cmds.mayaHydraCppTest('/MayaHydraViewportRenderer/rprims/Lighted/pTorus1', + f='TestPrimPath.notVisible'); + cmds.mayaHydraCppTest('/MayaHydraViewportRenderer/rprims/group1', + f='TestPrimPath.isVisible'); + cmds.mayaHydraCppTest('/MayaHydraViewportRenderer/rprims/Lighted/group1', + f='TestPrimPath.isVisible'); + + disableIsolateSelect(modelPanel) + +if __name__ == '__main__': + fixturesUtils.runTests(globals()) diff --git a/test/lib/mayaUsd/render/mayaToHydra/cpp/testPrimPath.cpp b/test/lib/mayaUsd/render/mayaToHydra/cpp/testPrimPath.cpp new file mode 100644 index 000000000..ccac84764 --- /dev/null +++ b/test/lib/mayaUsd/render/mayaToHydra/cpp/testPrimPath.cpp @@ -0,0 +1,82 @@ +// 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. +// + +#include "testUtils.h" + +#include + +PXR_NAMESPACE_USING_DIRECTIVE + +using namespace MayaHydra; + +TEST(TestPrimPath, isVisible) +{ + const auto& sceneIndices = GetTerminalSceneIndices(); + auto siRoot = sceneIndices.front(); + + auto [argc, argv] = getTestingArgs(); + ASSERT_EQ(argc, 1); + + // We receive the Hydra prim path directly. + const SdfPath primPath(argv[0]); + + ASSERT_TRUE(visibility(siRoot, primPath)); +} + +TEST(TestPrimPath, notVisible) +{ + const auto& sceneIndices = GetTerminalSceneIndices(); + auto siRoot = sceneIndices.front(); + + auto [argc, argv] = getTestingArgs(); + ASSERT_EQ(argc, 1); + + // We receive the Hydra prim path directly. + const SdfPath primPath(argv[0]); + + ASSERT_FALSE(visibility(siRoot, primPath)); +} + +TEST(TestPrimPath, exists) +{ + const auto& sceneIndices = GetTerminalSceneIndices(); + auto siRoot = sceneIndices.front(); + + auto [argc, argv] = getTestingArgs(); + ASSERT_EQ(argc, 1); + + // We receive the Hydra prim path directly. + const SdfPath primPath(argv[0]); + + const auto prim = siRoot->GetPrim(primPath); + // A prim that exists has a data source. + ASSERT_TRUE(prim.dataSource); +} + +TEST(TestPrimPath, doesNotExist) +{ + const auto& sceneIndices = GetTerminalSceneIndices(); + auto siRoot = sceneIndices.front(); + + auto [argc, argv] = getTestingArgs(); + ASSERT_EQ(argc, 1); + + // We receive the Hydra prim path directly. + const SdfPath primPath(argv[0]); + + const auto prim = siRoot->GetPrim(primPath); + // A prim that exists has a data source. + ASSERT_FALSE(prim.dataSource); +}