Skip to content

Commit

Permalink
Select prim without data source must not crash. (#194)
Browse files Browse the repository at this point in the history
  • Loading branch information
ppt-adsk authored Oct 28, 2024
1 parent b2639ec commit d8c2707
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 3 deletions.
11 changes: 8 additions & 3 deletions lib/flowViewport/sceneIndex/fvpSelectionSceneIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class _PrimSource : public HdContainerDataSource

TfTokenVector GetNames() override
{
TfTokenVector names = _inputSource->GetNames();
TfTokenVector names = _inputSource ? _inputSource->GetNames() : TfTokenVector();
if (_selection->IsFullySelected(_primPath)) {
names.push_back(HdSelectionsSchemaTokens->selections);
}
Expand All @@ -89,7 +89,7 @@ class _PrimSource : public HdContainerDataSource
return _selection->GetVectorDataSource(_primPath);
}

return _inputSource->Get(name);
return _inputSource ? _inputSource->Get(name) : nullptr;
}

private:
Expand Down Expand Up @@ -132,7 +132,12 @@ SelectionSceneIndex::GetPrim(const SdfPath &primPath) const
.Msg("SelectionSceneIndex::GetPrim() called.\n");

HdSceneIndexPrim result = GetInputSceneIndex()->GetPrim(primPath);
if (!result.dataSource) {
// An empty data source can be taken to mean an invalid prim, but it can
// also be an ancestor in a path to an actual prim (see
// https://forum.aousd.org/t/representation-of-invalid-hdsceneindexprim/833/2
// ). Such an ancestor prim can be selected, even if typeless, so add
// a selection data source in such a case.
if (!result.dataSource && !_selection->IsFullySelected(primPath)) {
return result;
}

Expand Down
1 change: 1 addition & 0 deletions test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ set(INTERACTIVE_TEST_SCRIPT_FILES
testNamespaces.py
testVisibility.py
testRendererSwitching.py
testSelectPrimWithoutDataSource.py
testStageAddPrim.py
testTransforms.py
testRefinement.py
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 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 maya.cmds as cmds

import fixturesUtils
import mtohUtils
import testUtils
import usdUtils

class TestSelectPrimWithoutDataSource(mtohUtils.MayaHydraBaseTestCase):
# MayaHydraBaseTestCase.setUpClass requirement.
_file = __file__

def test_selectPrimWithoutDataSource(self):

# Importing mayaUsd or mayaUsd.lib at module scope produces an "unbound
# local" error on use, so import in local scope. May be tied to
# point at which mayaUsd plugin gets loaded into Maya.
import mayaUsd.lib

# Prims without a data source are sometimes used to flag illegal prim
# return values, but such prims can also be legitimately used as parent
# prims for children prims that do have data sources. As such a prim
# without a data source must be selectable.

# Read in a scene that creates a legal Hydra parent prim without a data
# source.
usdScenePath = testUtils.getTestScene('testSelectPrimWithoutDataSource', 'root.usda')

self.proxyShapePathStr = usdUtils.createStageFromFile(usdScenePath)

stage = mayaUsd.lib.GetPrim(self.proxyShapePathStr).GetStage()

self.assertIsNotNone(stage)

# Initially select the proxy shape.
cmds.select('|root|rootShape')
cmds.refresh()

# Switch selection to a USD prim that generates a Hydra prim without
# a data source, but with children. This must not crash.
cmds.select('|root|rootShape,/root/refAssetB')
cmds.refresh()

if __name__ == '__main__':
fixturesUtils.runTests(globals())
25 changes: 25 additions & 0 deletions test/testSamples/testSelectPrimWithoutDataSource/cube.usda
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#usda 1.0
(
defaultPrim = "cube"
)

def Xform "cube" (
prepend apiSchemas = ["GeomModelAPI"]
kind = "component"
)
{
uniform bool model:applyDrawMode = 1
asset model:cardTextureXNeg = @./red20x20.png@
asset model:cardTextureXPos = @./red20x20.png@
asset model:cardTextureYNeg = @./red20x20.png@
asset model:cardTextureYPos = @./red20x20.png@
asset model:cardTextureZNeg = @./red20x20.png@
asset model:cardTextureZPos = @./red20x20.png@

def Mesh "cubeMesh"
{
int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
int[] faceVertexIndices = [0, 1, 3, 2, 2, 3, 5, 4, 4, 5, 7, 6, 6, 7, 1, 0, 1, 7, 5, 3, 6, 0, 2, 4]
point3f[] points = [(-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (-0.5, 0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, 0.5, -0.5), (0.5, 0.5, -0.5), (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5)]
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions test/testSamples/testSelectPrimWithoutDataSource/root.usda
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#usda 1.0
(
defaultPrim = "root"
)

def Xform "root" (
kind = "assembly"
)
{
def Xform "refAssetA" (
references = @./cube.usda@
kind = "group"
)
{
double3 xformOp:rotateXYZ = (-90, 0, 0)
double3 xformOp:translate = (-5, 0, 0)
uniform token[] xformOpOrder = ["xformOp:rotateXYZ", "xformOp:translate"]
}
def Xform "refAssetB" (
references = @./cube.usda@
kind = "group"
)
{
uniform token model:drawMode = "cards"
double3 xformOp:rotateXYZ = (-90, 0, 0)
double3 xformOp:translate = (5, 0, 0)
uniform token[] xformOpOrder = ["xformOp:rotateXYZ", "xformOp:translate"]
}
}

0 comments on commit d8c2707

Please sign in to comment.