示例#1
0
    def setUp(self):
        # Load plugins
        self.assertTrue(self.pluginsLoaded)

        # Load a file that has the same scene in both the Maya Dag
        # hierarchy and the USD hierarchy.
        mayaUtils.openTestScene("parentCmd", "simpleSceneMayaPlusUSD_TRS.ma")

        # Create multiple scene items.  We will alternate between selecting a
        # Maya item and a USD item, 3 items each data model, one item at a
        # time, so we select 6 different items, one at a time.
        shapeSegment = mayaUtils.createUfePathSegment(
            "|mayaUsdProxy1|mayaUsdProxyShape1")
        ufeNames = ["cubeXform", "cylinderXform", "sphereXform"]
        mayaNames = ["pCube1", "pCylinder1", "pSphere1"]
        usdPaths = []
        for n in ["/" + o for o in ufeNames]:
            usdPaths.append(
                ufe.Path([shapeSegment,
                          usdUtils.createUfePathSegment(n)]))
        mayaPaths = []
        for n in ["|" + o for o in mayaNames]:
            mayaPaths.append(ufe.Path(mayaUtils.createUfePathSegment(n)))

        # Create a list of paths by alternating USD objects and Maya objects
        # Flatten zipped tuples using list comprehension double loop.
        zipped = zip(usdPaths, mayaPaths)
        paths = [j for i in zipped for j in i]

        # Create items for all paths.
        self.items = [ufe.Hierarchy.createItem(p) for p in paths]

        # Clear selection to start off
        cmds.select(clear=True)
示例#2
0
    def testRenameRestrictionVariant(self):

        '''Renaming prims inside a variantSet is not allowed.'''

        cmds.file(new=True, force=True)

        # open Variant.ma scene in testSamples
        mayaUtils.openVariantSetScene()

        # stage
        mayaPathSegment = mayaUtils.createUfePathSegment('|Variant_usd|Variant_usdShape')
        stage = mayaUsd.ufe.getStage(str(mayaPathSegment))

        # first check that we have a VariantSets
        objectPrim = stage.GetPrimAtPath('/objects')
        self.assertTrue(objectPrim.HasVariantSets())

        # Geom
        usdPathSegment = usdUtils.createUfePathSegment('/objects/Geom')
        geomPath = ufe.Path([mayaPathSegment, usdPathSegment])
        geomItem = ufe.Hierarchy.createItem(geomPath)
        geomPrim = mayaUsd.ufe.ufePathToPrim(ufe.PathString.string(geomPath))

        # Small_Potato
        smallPotatoUsdPathSegment = usdUtils.createUfePathSegment('/objects/Geom/Small_Potato')
        smallPotatoPath = ufe.Path([mayaPathSegment, smallPotatoUsdPathSegment])
        smallPotatoItem = ufe.Hierarchy.createItem(smallPotatoPath)
        smallPotatoPrim = mayaUsd.ufe.ufePathToPrim(ufe.PathString.string(smallPotatoPath))

        # add Geom to selection list
        ufe.GlobalSelection.get().append(geomItem)

        # get prim spec for Geom prim
        primspecGeom = stage.GetEditTarget().GetPrimSpecForScenePath(geomPrim.GetPath());

        # primSpec is expected to be None
        self.assertIsNone(primspecGeom)

        # rename "/objects/Geom" to "/objects/Geom_something"
        # expect the exception happens
        with self.assertRaises(RuntimeError):
            cmds.rename("Geom_something")

        # clear selection
        cmds.select(clear=True)

        # add Small_Potato to selection list 
        ufe.GlobalSelection.get().append(smallPotatoItem)

        # get prim spec for Small_Potato prim
        primspecSmallPotato = stage.GetEditTarget().GetPrimSpecForScenePath(smallPotatoPrim.GetPath());

        # primSpec is expected to be None
        self.assertIsNone(primspecSmallPotato)

        # rename "/objects/Geom/Small_Potato" to "/objects/Geom/Small_Potato_something"
        # expect the exception happens
        with self.assertRaises(RuntimeError):
            cmds.rename("Small_Potato_something")
示例#3
0
    def testAlreadyChild(self):
        '''Parenting an object to its current parent is a no-op.'''

        with OpenFileCtx("simpleHierarchy.ma"):
            shapeSegment = mayaUtils.createUfePathSegment(
                "|mayaUsdProxy1|mayaUsdProxyShape1")
            spherePath = ufe.Path(
                [shapeSegment,
                 usdUtils.createUfePathSegment("/pCylinder1/pCube1/pSphere1")])
            sphereItem = ufe.Hierarchy.createItem(spherePath)
            cylinderShapePath = ufe.Path(
                [shapeSegment,
                 usdUtils.createUfePathSegment("/pCylinder1/pCylinderShape1")])
            cylinderShapeItem = ufe.Hierarchy.createItem(cylinderShapePath)
            parentPath = ufe.Path(
                [shapeSegment, usdUtils.createUfePathSegment("/pCylinder1")])
            parentItem = ufe.Hierarchy.createItem(parentPath)

            parent = ufe.Hierarchy.hierarchy(parentItem)
            childrenPre = parent.children()

            # get the USD stage
            stage = mayaUsd.ufe.getStage(str(shapeSegment))

            # check GetLayerStack behavior
            self.assertEqual(stage.GetEditTarget().GetLayer(), stage.GetRootLayer())

            # The sphere is not a child of the cylinder
            self.assertNotIn("pSphere1", childrenNames(childrenPre))

            # The cylinder shape is a child of the cylinder
            self.assertIn("pCylinderShape1", childrenNames(childrenPre))

            # Parent the sphere and the cylinder shape to the cylinder.  This
            # is a no-op for the cylinder shape, as it's already a child of the
            # cylinder, and the sphere is parented to the cylinder.
            cmds.parent(ufe.PathString.string(spherePath),
                        ufe.PathString.string(cylinderShapePath),
                        ufe.PathString.string(parentPath))

            children = parent.children()
            self.assertEqual(len(childrenPre)+1, len(children))
            self.assertIn("pSphere1", childrenNames(children))
            self.assertIn("pCylinderShape1", childrenNames(children))

            # Undo / redo
            cmds.undo()

            children = parent.children()
            self.assertEqual(len(childrenPre), len(children))
            self.assertNotIn("pSphere1", childrenNames(children))
            self.assertIn("pCylinderShape1", childrenNames(children))

            cmds.redo()

            children = parent.children()
            self.assertEqual(len(childrenPre)+1, len(children))
            self.assertIn("pSphere1", childrenNames(children))
            self.assertIn("pCylinderShape1", childrenNames(children))
示例#4
0
    def setUp(self):
        ''' Called initially to set up the maya test environment '''
        # Load plugins
        self.assertTrue(self.pluginsLoaded)

        # These tests requires no additional setup.
        if self._testMethodName in [
                'testAddNewPrim', 'testAddNewPrimWithDelete'
        ]:
            return

        # Open top_layer.ma scene in test-samples
        mayaUtils.openTopLayerScene()

        # Clear selection to start off.
        ufe.GlobalSelection.get().clear()

        # Select Ball_35.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|world|transform1|proxyShape1"),
            usdUtils.createUfePathSegment("/Room_set/Props/Ball_35")
        ])
        self.ball35Item = ufe.Hierarchy.createItem(ball35Path)
        self.ball35Prim = usdUtils.getPrimFromSceneItem(self.ball35Item)

        ufe.GlobalSelection.get().append(self.ball35Item)

        # Create a ContextOps interface for it.
        self.contextOps = ufe.ContextOps.contextOps(self.ball35Item)
    def testDrawModes(self):
        self._StartTest('DrawModes')
        cmds.modelEditor('modelPanel4', edit=True, grid=False)

        cmds.move(2, 2, 2, 'persp')
        cmds.rotate(-33, 45, 0, 'persp')
        self.assertSnapshotClose('%s_cross_all_positive.png' % self._testName)

        cmds.move(-2, -2, -2, 'persp')
        cmds.rotate(145, 45, 0, 'persp')
        self.assertSnapshotClose('%s_cross_all_negative.png' % self._testName)

        mayaPathSegment = mayaUtils.createUfePathSegment('|stage|stageShape')
        usdPathSegment = usdUtils.createUfePathSegment('/DrawModes')
        drawModesPath = ufe.Path([mayaPathSegment, usdPathSegment])
        drawModesItem = ufe.Hierarchy.createItem(drawModesPath)
        drawModesPrim = usdUtils.getPrimFromSceneItem(drawModesItem)
        cardGeomAttr = drawModesPrim.GetAttribute('model:cardGeometry')
        cardGeomAttr.Set('box')

        cmds.move(2, 2, 2, 'persp')
        cmds.rotate(-33, 45, 0, 'persp')
        self.assertSnapshotClose('%s_box_all_positive.png' % self._testName)

        cmds.move(-2, -2, -2, 'persp')
        cmds.rotate(145, 45, 0, 'persp')
        self.assertSnapshotClose('%s_box_all_negative.png' % self._testName)
示例#6
0
    def testMoveUSD(self):
        '''Move USD object, read through the Transform3d interface.'''

        # Select Ball_35 to move it.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|world|transform1|proxyShape1"), 
            usdUtils.createUfePathSegment("/Room_set/Props/Ball_35")])
        ball35Item = ufe.Hierarchy.createItem(ball35Path)

        ufe.GlobalSelection.get().append(ball35Item)

        # Create a Transform3d interface for it.
        transform3d = ufe.Transform3d.transform3d(ball35Item)

        # We compare the UFE translation with the USD run-time translation.  To
        # obtain the full translation of Ball_35, we need to add the USD
        # translation to the Maya proxy shape translation.
        proxyShapeXformObj = om.MSelectionList().add('transform1').getDagPath(0).node()
        proxyShapeXformFn = om.MFnTransform(proxyShapeXformObj)

        def ball35Translation():
            ball35Prim = usdUtils.getPrimFromSceneItem(ball35Item)
            return addVec(
                proxyShapeXformFn.translation(om.MSpace.kTransform),
                ball35Prim.GetAttribute('xformOp:translate').Get())

        # Set up the callables that will retrieve the translation.
        self.runTimeTranslation = ball35Translation
        self.ufeTranslation = partial(transform3dTranslation, transform3d)

        # Save the initial position to the memento list.
        expected = ball35Translation()

        self.runTestMove(expected)
示例#7
0
    def testScaleUSD(self):
        '''Scale USD object, read through the Transform3d interface.'''

        # Select Ball_35 to scale it.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|world|transform1|proxyShape1"), 
            usdUtils.createUfePathSegment("/Room_set/Props/Ball_35")])
        ball35Item = ufe.Hierarchy.createItem(ball35Path)

        ufe.GlobalSelection.get().append(ball35Item)

        # Create a Transform3d interface for it.
        transform3d = ufe.Transform3d.transform3d(ball35Item)

        # We compare the UFE scale with the USD run-time scale.  To
        # obtain the full scale of Ball_35, we need to add the USD
        # scale to the Maya proxy shape scale.
        proxyShapeXformObj = om.MSelectionList().add('transform1').getDagPath(0).node()
        proxyShapeXformFn = om.MFnTransform(proxyShapeXformObj)

        def ball35Scale():
            ball35Prim = usdUtils.getPrimFromSceneItem(ball35Item)
            if not ball35Prim.HasAttribute('xformOp:scale'):
                return proxyShapeXformFn.scale()
            else:
                return combineScales(proxyShapeXformFn.scale(), ball35Prim.GetAttribute('xformOp:scale').Get())
            
        # Set up the callables that will retrieve the scale.
        self.runTimeScale = ball35Scale
        self.ufeScale = partial(transform3dScale, transform3d)

        # Save the initial position to the memento list.
        expected = ball35Scale()

        self.runTestScale(expected)
示例#8
0
    def testRenameRestrictionSameLayerDef(self):
        '''Restrict renaming USD node. Cannot rename a prim defined on another layer.'''

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|world|transform1|proxyShape1')
        usdPathSegment = usdUtils.createUfePathSegment(
            '/Room_set/Props/Ball_35')
        ball35Path = ufe.Path([mayaPathSegment, usdPathSegment])
        ball35Item = ufe.Hierarchy.createItem(ball35Path)

        ufe.GlobalSelection.get().append(ball35Item)

        # get the USD stage
        stage = mayaUsd.ufe.getStage(str(mayaPathSegment))

        # check GetLayerStack behavior
        self.assertEqual(stage.GetLayerStack()[0], stage.GetSessionLayer())
        self.assertEqual(stage.GetEditTarget().GetLayer(),
                         stage.GetRootLayer())

        # expect the exception happens
        with self.assertRaises(RuntimeError):
            newName = 'Ball_35_Renamed'
            cmds.rename(newName)
示例#9
0
    def testRenameRestrictionOtherLayerOpinions(self):
        '''Restrict renaming USD node. Cannot rename a prim with definitions or opinions on other layers.'''

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|world|transform1|proxyShape1')
        usdPathSegment = usdUtils.createUfePathSegment(
            '/Room_set/Props/Ball_35')
        ball35Path = ufe.Path([mayaPathSegment, usdPathSegment])
        ball35Item = ufe.Hierarchy.createItem(ball35Path)

        ufe.GlobalSelection.get().append(ball35Item)

        # get the USD stage
        stage = mayaUsd.ufe.getStage(str(mayaPathSegment))

        # set the edit target to Assembly_room_set.usda
        stage.SetEditTarget(stage.GetLayerStack()[2])
        self.assertEqual(stage.GetEditTarget().GetLayer().GetDisplayName(),
                         "Assembly_room_set.usda")

        # expect the exception happens
        with self.assertRaises(RuntimeError):
            newName = 'Ball_35_Renamed'
            cmds.rename(newName)
示例#10
0
    def testRenameRestrictionHasSpecs(self):
        '''Restrict renaming USD node. Cannot rename a node that doesn't contribute to the final composed prim'''

        # open appleBite.ma scene in test-samples
        mayaUtils.openAppleBiteScene()

        # clear selection to start off
        cmds.select(clear=True)

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|world|Asset_flattened_instancing_and_class_removed_usd|Asset_flattened_instancing_and_class_removed_usdShape'
        )
        usdPathSegment = usdUtils.createUfePathSegment('/apple/payload/geo')
        geoPath = ufe.Path([mayaPathSegment, usdPathSegment])
        geoItem = ufe.Hierarchy.createItem(geoPath)

        ufe.GlobalSelection.get().append(geoItem)

        # get the USD stage
        stage = mayaUsd.ufe.getStage(str(mayaPathSegment))

        # rename "/apple/payload/geo" to "/apple/payload/geo_renamed"
        # expect the exception happens
        with self.assertRaises(RuntimeError):
            cmds.rename("geo_renamed")
示例#11
0
    def testMultiSelectMoveUSD(self):
        '''Move multiple USD objects, read through Transform3d interface.'''

        # Select multiple balls to move them.
        proxyShapePathSegment = mayaUtils.createUfePathSegment(
            "|world|transform1|proxyShape1")

        balls = ['Ball_33', 'Ball_34']
        ballPaths = [
            ufe.Path([
                proxyShapePathSegment,
                usdUtils.createUfePathSegment('/Room_set/Props/' + ball)
            ]) for ball in balls
        ]
        ballItems = [
            ufe.Hierarchy.createItem(ballPath) for ballPath in ballPaths
        ]

        for ballItem in ballItems:
            ufe.GlobalSelection.get().append(ballItem)

        # We compare the UFE translation with the USD run-time translation.  To
        # obtain the full translation of USD scene items, we need to add the USD
        # translation to the Maya proxy shape translation.
        proxyShapeXformObj = om.MSelectionList().add('transform1').getDagPath(
            0).node()
        proxyShapeXformFn = om.MFnTransform(proxyShapeXformObj)

        def usdSceneItemTranslation(item):
            prim = usdUtils.getPrimFromSceneItem(item)
            if not prim.HasAttribute('xformOp:translate'):
                return proxyShapeXformFn.translation(om.MSpace.kTransform)
            else:
                return addVec(
                    proxyShapeXformFn.translation(om.MSpace.kTransform),
                    prim.GetAttribute('xformOp:translate').Get())

        def ufeSceneItemTranslation(item):
            return transform3dTranslation(ufe.Transform3d.transform3d(item))

        # Set up the callables that will retrieve the translation.
        self.runTimeTranslation = usdSceneItemTranslation
        self.ufeTranslation = ufeSceneItemTranslation

        # Give the tail item in the selection an initial translation that
        # is different, to catch bugs where the relative translation
        # incorrectly squashes any existing translation.
        backItem = ballItems[-1]
        backT3d = ufe.Transform3d.transform3d(backItem)
        initialTranslation = [-10, -20, -30]
        backT3d.translate(*initialTranslation)
        assertVectorAlmostEqual(self, ufeSceneItemTranslation(backItem),
                                usdSceneItemTranslation(backItem))

        # Save the initial positions to the memento list.
        expected = [
            usdSceneItemTranslation(ballItem) for ballItem in ballItems
        ]

        self.runMultiSelectTestMove(ballItems, expected)
    def setUp(self):
        ''' Called initially to set up the maya test environment '''
        # Load plugins
        self.assertTrue(self.pluginsLoaded)

        # Open top_layer.ma scene in test-samples
        mayaUtils.openTopLayerScene()

        # Create a proxy shape with empty stage to start with.
        import mayaUsd_createStageWithNewLayer
        mayaUsd_createStageWithNewLayer.createStageWithNewLayer()

        # Clear selection to start off.
        ufe.GlobalSelection.get().clear()

        # Select Ball_35.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|world|transform1|proxyShape1"),
            usdUtils.createUfePathSegment("/Room_set/Props/Ball_35")
        ])
        self.ball35Item = ufe.Hierarchy.createItem(ball35Path)

        ufe.GlobalSelection.get().append(self.ball35Item)

        # Create a ContextOps interface for it.
        self.contextOps = ufe.ContextOps.contextOps(self.ball35Item)
示例#13
0
 def _GetUfePath(instanceIndex=-1):
     mayaSegment = mayaUtils.createUfePathSegment('|UsdProxy|UsdProxyShape')
     usdSegmentString = mayaUsdUfe.usdPathToUfePathSegment(
         '/PointInstancerGrid/PointInstancer', instanceIndex)
     usdSegment = usdUtils.createUfePathSegment(usdSegmentString)
     ufePath = ufe.Path([mayaSegment, usdSegment])
     return ufePath
示例#14
0
    def testAttributes(self):
        '''Engine method to run attributes test.'''

        # Get a UFE scene item for one of the balls in the scene.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|world|transform1|proxyShape1"),
            usdUtils.createUfePathSegment("/Room_set/Props/Ball_35")
        ])
        ball35Item = ufe.Hierarchy.createItem(ball35Path)

        # Then create the attributes interface for that item.
        ball35Attrs = ufe.Attributes.attributes(ball35Item)
        self.assertIsNotNone(ball35Attrs)

        # Test that we get the same scene item back.
        self.assertEqual(ball35Item, ball35Attrs.sceneItem())

        # Verify that ball35 contains the visibility attribute.
        self.assertTrue(ball35Attrs.hasAttribute(UsdGeom.Tokens.visibility))

        # Verify the attribute type of 'visibility' which we know is a enum token.
        self.assertEqual(ball35Attrs.attributeType(UsdGeom.Tokens.visibility),
                         ufe.Attribute.kEnumString)

        # Get all the attribute names for this item.
        ball35AttrNames = ball35Attrs.attributeNames

        # Visibility should be in this list.
        self.assertIn(UsdGeom.Tokens.visibility, ball35AttrNames)
    def _testMoveMaya(self):
        '''Move Maya object, read through the Transform3d interface.'''

        # Give the sphere an initial position, and select it.
        expected = om.MVector(1, 2, 3)
        sphereObj = om.MSelectionList().add('pSphere1').getDagPath(0).node()
        sphereFn = om.MFnTransform(sphereObj)

        def setMayaTranslation(xlation):
            sphereFn.setTranslation(xlation, om.MSpace.kTransform)

        setMayaTranslation(expected)
        spherePath = ufe.Path(mayaUtils.createUfePathSegment("|pSphere1"))
        sphereItem = ufe.Hierarchy.createItem(spherePath)

        ufe.GlobalSelection.get().append(sphereItem)

        # Create a Transform3d interface for it.
        transform3d = ufe.Transform3d.transform3d(sphereItem)

        # Set up the callables that will set and get the translation.
        self.setRunTimeTranslation = setMayaTranslation
        self.getRunTimeTranslation = partial(sphereFn.translation,
                                             om.MSpace.kTransform)
        self.getUfeTranslation = partial(transform3dTranslation, transform3d)

        self.runTestMove()
    def testStaticUsdCamera(self):
        self._StartTest('TranslateRotate_vs_xform')

        mayaPathSegment = mayaUtils.createUfePathSegment('|stage|stageShape')
        #camera1 doesn't work correctly right now because of an xformOp:transform issue MAYA-110515
        #cam1UsdPathSegment = usdUtils.createUfePathSegment('cameras/cam1/camera1')
        #cmds.lookThru('|stage|stageShape,/cameras/cam1/camera1')
        #self.assertSnapshotClose('%s_cam1_unselected.png' % self._testName)

        cmds.lookThru('|stage|stageShape,/cameras/cam2/camera2')
        self.assertSnapshotClose('%s_cam2_unselected.png' % self._testName)

        # create a Ufe transform3d and move cam2 somewhere else and do a snapshot
        cam2UsdPathSegment = usdUtils.createUfePathSegment(
            '/cameras/cam2/camera2')
        cam2Path = ufe.Path([mayaPathSegment, cam2UsdPathSegment])
        cam2Item = ufe.Hierarchy.createItem(cam2Path)
        cam2Transform3d = ufe.Transform3d.transform3d(cam2Item)
        cam2Transform3d.translate(-1, 0, 0)
        self.assertSnapshotClose('%s_cam2_translated.png' % self._testName)

        # create a Ufe Camera and modify the near clip plane and do a snapshot
        # ufe.Camera is not in Ufe 2.0.0 MAYA-110675
        # set the clipping range using the USD API instead
        usdCamera = usdUtils.getPrimFromSceneItem(cam2Item)
        clippingAttr = usdCamera.GetAttribute('clippingRange')
        clippingRange = clippingAttr.Get()
        clippingAttr.Set(Gf.Vec2f(10, 5000))
        self.assertSnapshotClose('%s_cam2_insideNearClipPlane.png' %
                                 self._testName)
示例#17
0
    def testRenameUniqueName(self):
        # open tree.ma scene in test-samples
        mayaUtils.openTreeScene()

        # clear selection to start off
        cmds.select(clear=True)

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment('|world|Tree_usd|Tree_usdShape')
        usdPathSegment = usdUtils.createUfePathSegment('/TreeBase/trunk')
        trunkPath = ufe.Path([mayaPathSegment, usdPathSegment])
        trunkItem = ufe.Hierarchy.createItem(trunkPath)

        ufe.GlobalSelection.get().append(trunkItem)

        # get the USD stage
        stage = mayaUsd.ufe.getStage(str(mayaPathSegment))

        # by default edit target is set to the Rootlayer.
        self.assertEqual(stage.GetEditTarget().GetLayer(), stage.GetRootLayer())

        # rename `/TreeBase/trunk` to `/TreeBase/leavesXform`
        cmds.rename("leavesXform")

        # get the prim
        item = ufe.GlobalSelection.get().front()
        usdPrim = stage.GetPrimAtPath(str(item.path().segments[1]))
        self.assertTrue(usdPrim)

        # the new prim name is expected to be "leavesXform1"
        assert ([x for x in stage.Traverse()] == [stage.GetPrimAtPath("/TreeBase"), 
            stage.GetPrimAtPath("/TreeBase/leavesXform"), 
            stage.GetPrimAtPath("/TreeBase/leavesXform/leaves"),
            stage.GetPrimAtPath("/TreeBase/leavesXform1"),])
示例#18
0
    def testManipulatePointInstancePosition(self):
        # Create a UFE path to a PointInstancer prim with an instanceIndex on
        # the end. This path uniquely identifies a specific point instance.
        # We also pick one with a non-zero initial position.
        instanceIndex = 7

        ufePath = ufe.Path([
            mayaUtils.createUfePathSegment('|UsdProxy|UsdProxyShape'),
            usdUtils.createUfePathSegment(
                '/PointInstancerGrid/PointInstancer/%d' % instanceIndex)
        ])
        ufeItem = ufe.Hierarchy.createItem(ufePath)

        # Select the point instance scene item.
        globalSelection = ufe.GlobalSelection.get()
        globalSelection.append(ufeItem)

        # Get the PointInstancer prim for validating the values in USD.
        ufePathString = ufe.PathString.string(ufePath)
        prim = mayaUsdUfe.ufePathToPrim(ufePathString)
        pointInstancer = UsdGeom.PointInstancer(prim)
        self.assertTrue(pointInstancer)

        # The PointInstancer should have 14 authored positions initially.
        positionsAttr = pointInstancer.GetPositionsAttr()
        positions = positionsAttr.Get()
        self.assertEqual(len(positions), 14)

        # Validate the initial position before manipulating
        position = positions[instanceIndex]
        self.assertTrue(
            Gf.IsClose(position, Gf.Vec3f(-4.5, 1.5, 0.0), self.EPSILON))

        # Perfom a translate manipulation via the move command.
        cmds.move(1.0, 2.0, 3.0, objectSpace=True, relative=True)

        # Re-fetch the USD positions and check for the update.
        position = positionsAttr.Get()[instanceIndex]
        self.assertTrue(
            Gf.IsClose(position, Gf.Vec3f(-3.5, 3.5, 3.0), self.EPSILON))

        # Try another move.
        cmds.move(6.0, 5.0, 4.0, objectSpace=True, relative=True)

        # Re-fetch the USD positions and check for the update.
        position = positionsAttr.Get()[instanceIndex]
        self.assertTrue(
            Gf.IsClose(position, Gf.Vec3f(2.5, 8.5, 7.0), self.EPSILON))

        # Now undo, and re-check.
        cmds.undo()
        position = positionsAttr.Get()[instanceIndex]
        self.assertTrue(
            Gf.IsClose(position, Gf.Vec3f(-3.5, 3.5, 3.0), self.EPSILON))

        # And once more.
        cmds.undo()
        position = positionsAttr.Get()[instanceIndex]
        self.assertTrue(
            Gf.IsClose(position, Gf.Vec3f(-4.5, 1.5, 0.0), self.EPSILON))
示例#19
0
    def testPurposeBoundingBox(self):
        '''Bounding box of prims with guide, proxy, and render purpose.'''
        # Create a scene with prims of purposes other than default: guide,
        # proxy, and render.  All must have a valid bounding box.  The bounding
        # box is conditional to the proxy shape on the UFE path to the prim
        # having that purpose enabled: if the purpose is disabled, the bounding
        # box is invalid.
        import mayaUsd_createStageWithNewLayer

        proxyShapePath = mayaUsd_createStageWithNewLayer.createStageWithNewLayer(
        )
        proxyShapePathSegment = mayaUtils.createUfePathSegment(proxyShapePath)
        stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage()
        usdPaths = ['/Cube1', '/Cube2', '/Cube3']
        prims = [stage.DefinePrim(path, 'Cube') for path in usdPaths]
        purposes = [
            UsdGeom.Tokens.proxy, UsdGeom.Tokens.guide, UsdGeom.Tokens.render
        ]
        for (prim, purpose) in zip(prims, purposes):
            imageable = UsdGeom.Imageable(prim)
            imageable.CreatePurposeAttr(purpose)

        # Create a UFE scene item for each prim, and get the bounding box using
        # the Object3d interface.
        for (prim, usdPath) in zip(prims, usdPaths):
            pathSegment = usdUtils.createUfePathSegment(usdPath)
            path = ufe.Path([proxyShapePathSegment, pathSegment])
            item = ufe.Hierarchy.createItem(path)
            object3d = ufe.Object3d.object3d(item)

            # First turn off proxy, guide, render purposes on the proxy shape.
            # The bounding box should be invalid.
            purposeAttribs = [
                'drawProxyPurpose', 'drawGuidePurpose', 'drawRenderPurpose'
            ]
            for purposeAttrib in purposeAttribs:
                cmds.setAttr(proxyShapePath + '.' + purposeAttrib, 0)

            bbox = object3d.boundingBox()

            self.assertTrue(bbox.empty())

            # Next, turn on each purpose in turn on the proxy shape.  The
            # bounding box should be valid only if the prim's purpose matches
            # the proxy shape purpose.
            imageable = UsdGeom.Imageable(prim)
            primPurpose = imageable.GetPurposeAttr().Get()
            for (purpose, purposeAttrib) in zip(purposes, purposeAttribs):
                cmds.setAttr(proxyShapePath + '.' + purposeAttrib, 1)

                bbox = object3d.boundingBox()

                if primPurpose == purpose:
                    assertVectorAlmostEqual(self, bbox.min.vector, [-1] * 3)
                    assertVectorAlmostEqual(self, bbox.max.vector, [1] * 3)
                else:
                    self.assertTrue(bbox.empty())

                cmds.setAttr(proxyShapePath + '.' + purposeAttrib, 0)
示例#20
0
    def _testMultiSelectRotateUSD(self):
        '''Rotate multiple USD objects, read through Transform3d interface.'''

        # Select multiple balls to rotate them.
        proxyShapePathSegment = mayaUtils.createUfePathSegment(
            "|world|transform1|proxyShape1")

        balls = ['Ball_33', 'Ball_34']
        ballPaths = [
            ufe.Path([proxyShapePathSegment, 
                      usdUtils.createUfePathSegment('/Room_set/Props/'+ball)])
            for ball in balls]
        ballItems = [ufe.Hierarchy.createItem(ballPath) 
                     for ballPath in ballPaths]

        for ballItem in ballItems:
            ufe.GlobalSelection.get().append(ballItem)

        # We compare the UFE rotation with the USD run-time rotation.  To
        # obtain the full rotation of USD scene items, we need to add the USD
        # rotation to the Maya proxy shape rotation.
        proxyShapeXformObj = om.MSelectionList().add('transform1').getDagPath(0).node()
        proxyShapeXformFn = om.MFnTransform(proxyShapeXformObj)

        def usdSceneItemRotation(item):
            prim = usdUtils.getPrimFromSceneItem(item)
            if not prim.HasAttribute('xformOp:rotateXYZ'):
                return proxyShapeXformFn.rotation(om.MSpace.kTransform)
            else:
                x,y,z = prim.GetAttribute('xformOp:rotateXYZ').Get()
                return  proxyShapeXformFn.rotation(om.MSpace.kTransform) + om.MEulerRotation(radians(x), radians(y), radians(z))

        def ufeSceneItemRotation(item):
            return transform3dRotation(ufe.Transform3d.transform3d(item))

        # Set up the callables that will retrieve the rotation.
        self.runTimeRotation = usdSceneItemRotation
        self.ufeRotation = ufeSceneItemRotation

        # Give the tail item in the selection an initial rotation that
        # is different, to catch bugs where the relative rotation
        # incorrectly squashes any existing rotation.
        backItem = ballItems[-1]
        backT3d = ufe.Transform3d.transform3d(backItem)
        initialRot = [-10, -20, -30]
        backT3d.rotate(*initialRot)
        assertVectorAlmostEqual(self, [radians(a) for a in initialRot], 
                                     usdSceneItemRotation(backItem))

        # Save the initial positions to the memento list.
        expected = [usdSceneItemRotation(ballItem) for ballItem in ballItems]

        # MAYA-96058: unfortunately, rotate command currently requires a rotate
        # manipulator to be created to update the UFE object.
        manipCtx = cmds.manipRotateContext()
        cmds.setToolTo(manipCtx)

        #Temporarily disabling undo redo until we fix it for PR 94
        self.runMultiSelectTestRotate(ballItems, expected)
示例#21
0
    def testRename(self):
        # open tree.ma scene in test-samples
        mayaUtils.openTreeScene()

        # clear selection to start off
        cmds.select(clear=True)

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment('|world|Tree_usd|Tree_usdShape')
        usdPathSegment = usdUtils.createUfePathSegment('/TreeBase')
        treebasePath = ufe.Path([mayaPathSegment, usdPathSegment])
        treebaseItem = ufe.Hierarchy.createItem(treebasePath)

        ufe.GlobalSelection.get().append(treebaseItem)

        # get the USD stage
        stage = mayaUsd.ufe.getStage(str(mayaPathSegment))

        # by default edit target is set to the Rootlayer.
        self.assertEqual(stage.GetEditTarget().GetLayer(), stage.GetRootLayer())

        self.assertTrue(stage.GetRootLayer().GetPrimAtPath("/TreeBase"))

        # get default prim
        defaultPrim = stage.GetDefaultPrim()
        self.assertEqual(defaultPrim.GetName(), 'TreeBase')

        # TreeBase has two childern: leavesXform, trunk
        assert len(defaultPrim.GetChildren()) == 2

        # get prim spec for defaultPrim
        primspec = stage.GetEditTarget().GetPrimSpecForScenePath(defaultPrim.GetPath());

        # set primspec name
        primspec.name = "TreeBase_potato"

        # get the renamed prim
        renamedPrim = stage.GetPrimAtPath('/TreeBase_potato')

        # One must use the SdfLayer API for setting the defaultPrim when you rename the prim it identifies.
        stage.SetDefaultPrim(renamedPrim);

        # get defaultPrim again
        defaultPrim = stage.GetDefaultPrim()
        self.assertEqual(defaultPrim.GetName(), 'TreeBase_potato')

        # make sure we have a valid prims after the primspec rename 
        assert stage.GetPrimAtPath('/TreeBase_potato')
        assert stage.GetPrimAtPath('/TreeBase_potato/leavesXform')

        # prim should be called TreeBase_potato
        potatoPrim = stage.GetPrimAtPath('/TreeBase_potato')
        self.assertEqual(potatoPrim.GetName(), 'TreeBase_potato')

        # prim should be called leaves 
        leavesPrimSpec = stage.GetObjectAtPath('/TreeBase_potato/leavesXform/leaves')
        self.assertEqual(leavesPrimSpec.GetName(), 'leaves')
示例#22
0
    def testRename(self):
        '''Rename USD node.'''

        # Select a USD object.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|world|transform1|proxyShape1"),
            usdUtils.createUfePathSegment("/Room_set/Props/Ball_35")
        ])
        ball35Item = ufe.Hierarchy.createItem(ball35Path)
        ball35Hierarchy = ufe.Hierarchy.hierarchy(ball35Item)
        propsItem = ball35Hierarchy.parent()

        propsHierarchy = ufe.Hierarchy.hierarchy(propsItem)
        propsChildrenPre = propsHierarchy.children()

        ufe.GlobalSelection.get().append(ball35Item)

        newName = 'Ball_35_Renamed'
        cmds.rename(newName)

        # The renamed item is in the selection.
        snIter = iter(ufe.GlobalSelection.get())
        ball35RenItem = next(snIter)
        ball35RenName = str(ball35RenItem.path().back())

        self.assertEqual(ball35RenName, newName)

        # MAYA-92350: should not need to re-bind hierarchy interface objects
        # with their item.
        propsHierarchy = ufe.Hierarchy.hierarchy(propsItem)
        propsChildren = propsHierarchy.children()

        self.assertEqual(len(propsChildren), len(propsChildrenPre))
        self.assertIn(ball35RenItem, propsChildren)

        cmds.undo()

        def childrenNames(children):
            return [str(child.path().back()) for child in children]

        propsHierarchy = ufe.Hierarchy.hierarchy(propsItem)
        propsChildren = propsHierarchy.children()
        propsChildrenNames = childrenNames(propsChildren)

        self.assertNotIn(ball35RenName, propsChildrenNames)
        self.assertIn('Ball_35', propsChildrenNames)
        self.assertEqual(len(propsChildren), len(propsChildrenPre))

        cmds.redo()

        propsHierarchy = ufe.Hierarchy.hierarchy(propsItem)
        propsChildren = propsHierarchy.children()
        propsChildrenNames = childrenNames(propsChildren)

        self.assertIn(ball35RenName, propsChildrenNames)
        self.assertNotIn('Ball_35', propsChildrenNames)
        self.assertEqual(len(propsChildren), len(propsChildrenPre))
示例#23
0
    def testAnimatedBoundingBox(self):
        '''Test the Object3d bounding box interface for animated geometry.'''

        # Load up a scene with a sphere that has an animated radius, with
        # time connected to the proxy shape.
        filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                "test-samples", "sphereAnimatedRadius",
                                "sphereAnimatedRadiusProxyShape.ma")

        cmds.file(filePath, force=True, open=True)

        # The extents of the sphere are copied from the .usda file.
        expected = [[(-1.0000002, -1, -1.0000005), (1, 1, 1.0000001)],
                    [(-1.3086424, -1.308642, -1.3086426),
                     (1.308642, 1.308642, 1.3086421)],
                    [(-2.135803, -2.1358025, -2.1358035),
                     (2.1358025, 2.1358025, 2.1358027)],
                    [(-3.333334, -3.3333333, -3.333335),
                     (3.3333333, 3.3333333, 3.3333337)],
                    [(-4.7530875, -4.7530866, -4.753089),
                     (4.7530866, 4.7530866, 4.753087)],
                    [(-6.246915, -6.2469134, -6.2469163),
                     (6.2469134, 6.2469134, 6.2469144)],
                    [(-7.6666684, -7.6666665, -7.6666703),
                     (7.6666665, 7.6666665, 7.6666675)],
                    [(-8.8642, -8.864198, -8.864202),
                     (8.864198, 8.864198, 8.864199)],
                    [(-9.6913595, -9.691358, -9.691362),
                     (9.691358, 9.691358, 9.691359)],
                    [(-10.000002, -10, -10.000005), (10, 10, 10.000001)]]

        # Create an Object3d interface for USD sphere.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|world|transform1|proxyShape1')
        usdPathSegment = usdUtils.createUfePathSegment('/pSphere1')

        spherePath = ufe.Path([mayaPathSegment, usdPathSegment])
        sphereItem = ufe.Hierarchy.createItem(spherePath)

        object3d = ufe.Object3d.object3d(sphereItem)

        # Loop over frames 1 to 10, and compare the values returned to the
        # expected values.
        for frame in xrange(1, 11):
            cmds.currentTime(frame)

            ufeBBox = object3d.boundingBox()

            # Compare it to known extents.
            assertVectorAlmostEqual(self,
                                    ufeBBox.min.vector,
                                    expected[frame - 1][0],
                                    places=6)
            assertVectorAlmostEqual(self,
                                    ufeBBox.max.vector,
                                    expected[frame - 1][1],
                                    places=6)
示例#24
0
    def testTranslateLockedLayer(self):
        # create new stage
        cmds.file(new=True, force=True)

        # Open usdCylinder.ma scene in testSamples
        mayaUtils.openCylinderScene()

        # get the stage
        proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True)
        proxyShapePath = proxyShapes[0]
        stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage()

        # cylinder prim
        cylinderPrim = stage.GetPrimAtPath('/pCylinder1')
        self.assertIsNotNone(cylinderPrim)

        # create a sub-layer.
        rootLayer = stage.GetRootLayer()
        subLayerA = cmds.mayaUsdLayerEditor(rootLayer.identifier,
                                            edit=True,
                                            addAnonymous="LayerA")[0]

        # check to see the if the sublayers was added
        addedLayers = [subLayerA]
        self.assertEqual(rootLayer.subLayerPaths, addedLayers)

        # set the edit target to LayerA.
        cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerA)

        # set permission to edit to false
        layerA = Sdf.Find(subLayerA)
        layerA.SetPermissionToEdit(False)

        # Check that our helper function is returning the right thing
        self.assertFalse(mayaUsdUfe.isEditTargetLayerModifiable(stage))

        # Get translate attribute and make sure its empty
        translateAttr = cylinderPrim.GetAttribute('xformOp:translate')
        self.assertIsNotNone(translateAttr)

        tranlateBeforeEdit = translateAttr.Get()

        # create a transform3d and translate
        cylinderPath = ufe.Path([
            mayaUtils.createUfePathSegment("|mayaUsdTransform|shape"),
            usdUtils.createUfePathSegment("/pCylinder1")
        ])
        cylinderItem = ufe.Hierarchy.createItem(cylinderPath)

        cylinderT3d = ufe.Transform3d.transform3d(cylinderItem)
        if cylinderT3d is not None:
            cylinderT3d.translate(5.0, 6.0, 7.0)

        # check that the translate operation didn't change anything
        tranlateAfterEdit = translateAttr.Get()
        self.assertEqual(tranlateBeforeEdit, tranlateAfterEdit)
示例#25
0
    def testBoundingBox(self):
        '''Test the Object3d bounding box interface.'''

        # Create a simple USD scene.  Default sphere radius is 1, so extents
        # are from (-1, -1, -1) to (1, 1, 1).
        usdFilePath = cmds.internalVar(utd=1) + '/testObject3d.usda'
        stage = Usd.Stage.CreateNew(usdFilePath)
        xform = stage.DefinePrim('/parent', 'Xform')
        sphere = stage.DefinePrim('/parent/sphere', 'Sphere')
        extentAttr = sphere.GetAttribute('extent')
        extent = extentAttr.Get()

        assertVectorAlmostEqual(self, extent[0], [-1] * 3)
        assertVectorAlmostEqual(self, extent[1], [1] * 3)

        # Move the sphere.  Its UFE bounding box should not be affected by
        # transformation hierarchy.
        UsdGeom.XformCommonAPI(xform).SetTranslate((7, 8, 9))

        # Save out the file, and bring it back into Maya under a proxy shape.
        stage.GetRootLayer().Save()

        proxyShape = cmds.createNode('mayaUsdProxyShape')
        cmds.setAttr('mayaUsdProxyShape1.filePath', usdFilePath, type='string')

        # MAYA-101766: loading a stage is done by the proxy shape compute.
        # Because we're a script, no redraw is done, so need to pull explicitly
        # on the outStageData (and simply discard the returned data), to get
        # the proxy shape compute to run, and thus the stage to load.  This
        # should be improved.  Without a loaded stage, UFE item creation
        # fails.  PPT, 31-10-2019.
        outStageData = nameToPlug('mayaUsdProxyShape1.outStageData')
        outStageData.asMDataHandle()

        proxyShapeMayaPath = cmds.ls(proxyShape, long=True)[0]
        proxyShapePathSegment = mayaUtils.createUfePathSegment(
            proxyShapeMayaPath)

        # Create a UFE scene item from the sphere prim.
        spherePathSegment = usdUtils.createUfePathSegment('/parent/sphere')
        spherePath = ufe.Path([proxyShapePathSegment, spherePathSegment])
        sphereItem = ufe.Hierarchy.createItem(spherePath)

        # Get its Object3d interface.
        object3d = ufe.Object3d.object3d(sphereItem)

        # Get its bounding box.
        ufeBBox = object3d.boundingBox()

        # Compare it to known extents.
        assertVectorAlmostEqual(self, ufeBBox.min.vector, [-1] * 3)
        assertVectorAlmostEqual(self, ufeBBox.max.vector, [1] * 3)

        # Remove the test file.
        os.remove(usdFilePath)
示例#26
0
    def testRenameProxyShape(self):
        '''Rename proxy shape, UFE lookup should succeed.'''

        mayaSegment = mayaUtils.createUfePathSegment(
            "|world|transform1|proxyShape1")
        usdSegment = usdUtils.createUfePathSegment("/Room_set/Props/Ball_35")

        ball35Path = ufe.Path([mayaSegment, usdSegment])
        ball35PathStr = ','.join(
            [str(segment) for segment in ball35Path.segments])

        # Because of difference in Python binding systems (pybind11 for UFE,
        # Boost Python for mayaUsd and USD), need to pass in strings to
        # mayaUsd functions.  Multi-segment UFE paths need to have
        # comma-separated segments.
        def assertStageAndPrimAccess(proxyShapeSegment, primUfePathStr,
                                     primSegment):
            proxyShapePathStr = str(proxyShapeSegment)

            stage = mayaUsd.ufe.getStage(proxyShapePathStr)
            prim = mayaUsd.ufe.ufePathToPrim(primUfePathStr)
            stagePath = mayaUsd.ufe.stagePath(stage)

            self.assertIsNotNone(stage)
            self.assertEqual(stagePath, proxyShapePathStr)
            self.assertTrue(prim.IsValid())
            self.assertEqual(str(prim.GetPath()), str(primSegment))

        assertStageAndPrimAccess(mayaSegment, ball35PathStr, usdSegment)

        # Rename the proxy shape node itself.  Stage and prim access should
        # still be valid, with the new path.
        mayaSegment = mayaUtils.createUfePathSegment(
            "|world|transform1|potato")
        cmds.rename('|transform1|proxyShape1', 'potato')
        self.assertEqual(len(cmds.ls('potato')), 1)

        ball35Path = ufe.Path([mayaSegment, usdSegment])
        ball35PathStr = ','.join(
            [str(segment) for segment in ball35Path.segments])

        assertStageAndPrimAccess(mayaSegment, ball35PathStr, usdSegment)
示例#27
0
    def testUsdCamera(self):
        self._StartTest('TranslateRotate_vs_xform')
        mayaPathSegment = mayaUtils.createUfePathSegment('|stage|stageShape')
        cam2UsdPathSegment = usdUtils.createUfePathSegment(
            '/cameras/cam2/camera2')
        cam2Path = ufe.Path([mayaPathSegment, cam2UsdPathSegment])
        cam2Item = ufe.Hierarchy.createItem(cam2Path)

        cam2Camera = ufe.Camera.camera(cam2Item)
        cameraPrim = usdUtils.getPrimFromSceneItem(cam2Item)
        self._TestCameraAttributes(cam2Camera, cameraPrim)
示例#28
0
    def testRenameNotifications(self):
        '''Rename a USD node and test for the UFE notifications.'''

        # open usdCylinder.ma scene in test-samples
        mayaUtils.openCylinderScene()

        # clear selection to start off
        cmds.select(clear=True)

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|world|mayaUsdTransform|shape')
        usdPathSegment = usdUtils.createUfePathSegment('/pCylinder1')
        cylinderPath = ufe.Path([mayaPathSegment, usdPathSegment])
        cylinderItem = ufe.Hierarchy.createItem(cylinderPath)

        ufe.GlobalSelection.get().append(cylinderItem)

        # get the USD stage
        stage = mayaUsd.ufe.getStage(str(mayaPathSegment))

        # set the edit target to the root layer
        stage.SetEditTarget(stage.GetRootLayer())
        self.assertEqual(stage.GetEditTarget().GetLayer(),
                         stage.GetRootLayer())

        # Create our UFE notification observer
        ufeObs = TestObserver()

        if (os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '2021'):
            # We start off with no observers
            self.assertFalse(ufe.Scene.hasObjectAddObserver(ufeObs))
            self.assertFalse(ufe.Scene.hasObjectDeleteObserver(ufeObs))
            self.assertFalse(ufe.Scene.hasObjectPathChangeObserver(ufeObs))

            # Add the UFE observers we want to test
            ufe.Scene.addObjectAddObserver(ufeObs)
            ufe.Scene.addObjectDeleteObserver(ufeObs)
            ufe.Scene.addObjectPathChangeObserver(ufeObs)
        else:
            # We start off with no observers
            self.assertFalse(ufe.Scene.hasObserver(ufeObs))

            # Add the UFE observer we want to test
            ufe.Scene.addObserver(ufeObs)

        # rename
        newName = 'pCylinder1_Renamed'
        cmds.rename(newName)

        # After the rename we should have 1 rename notif and no unexepected notifs.
        self.assertEqual(ufeObs.notifications(), 1)
        self.assertFalse(ufeObs.receivedUnexpectedNotif())
示例#29
0
    def testMultiSelectScaleUSD(self):
        '''Scale multiple USD objects, read through Transform3d interface.'''

        # Select multiple balls to scale them.
        proxyShapePathSegment = mayaUtils.createUfePathSegment(
            "|world|transform1|proxyShape1")

        # Test passes for a single item.
        # balls = ['Ball_33']
        balls = ['Ball_33', 'Ball_34']
        ballPaths = [
            ufe.Path([proxyShapePathSegment, 
                      usdUtils.createUfePathSegment('/Room_set/Props/'+ball)])
            for ball in balls]
        ballItems = [ufe.Hierarchy.createItem(ballPath) 
                     for ballPath in ballPaths]

        for ballItem in ballItems:
            ufe.GlobalSelection.get().append(ballItem)

        # We compare the UFE scale with the USD run-time scale.  To
        # obtain the full scale of USD scene items, we need to add the USD
        # scale to the Maya proxy shape scale.
        proxyShapeXformObj = om.MSelectionList().add('transform1').getDagPath(0).node()
        proxyShapeXformFn = om.MFnTransform(proxyShapeXformObj)

        def usdSceneItemScale(item):
            prim = usdUtils.getPrimFromSceneItem(item)
            if not prim.HasAttribute('xformOp:scale'):
                return proxyShapeXformFn.scale()
            else:
                return combineScales(proxyShapeXformFn.scale(), prim.GetAttribute('xformOp:scale').Get())

        def ufeSceneItemScale(item):
            return transform3dScale(ufe.Transform3d.transform3d(item))

        # Set up the callables that will retrieve the scale.
        self.runTimeScale = usdSceneItemScale
        self.ufeScale = ufeSceneItemScale

        # Give the tail item in the selection an initial scale that
        # is different, to catch bugs where the relative scale
        # incorrectly squashes any existing scale.
        backItem = ballItems[-1]
        backT3d = ufe.Transform3d.transform3d(backItem)
        initialScale = [1.1, 2.2, 3.3]
        backT3d.scale(*initialScale)
        assertVectorAlmostEqual(self, initialScale, usdSceneItemScale(backItem), places=6)

        # Save the initial positions to the memento list.
        expected = [usdSceneItemScale(ballItem) for ballItem in ballItems]

        self.runMultiSelectTestScale(ballItems, expected, places=6)
示例#30
0
    def testVisibility(self):
        '''Test the Object3d visibility methods.'''

        # Open top_layer.ma scene in test-samples
        mayaUtils.openTopLayerScene()

        # Get a scene item for Ball_35.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|world|transform1|proxyShape1"),
            usdUtils.createUfePathSegment("/Room_set/Props/Ball_35")
        ])
        ball35Item = ufe.Hierarchy.createItem(ball35Path)

        # Create an Object3d interface for it.
        object3d = ufe.Object3d.object3d(ball35Item)

        visObs = TestObserver()

        # We start off with no visibility observers.
        self.assertFalse(ufe.Object3d.hasObserver(visObs))
        self.assertEqual(ufe.Object3d.nbObservers(), 0)

        # Set the observer for visibility changes.
        ufe.Object3d.addObserver(visObs)
        self.assertTrue(ufe.Object3d.hasObserver(visObs))
        self.assertEqual(ufe.Object3d.nbObservers(), 1)

        # No notifications yet.
        self.assertEqual(visObs.notifications(), 0)

        # Initially it should be visible.
        self.assertTrue(object3d.visibility())

        # Make it invisible.
        object3d.setVisibility(False)
        self.assertFalse(object3d.visibility())

        # We should have got 'one' notification.
        self.assertEqual(visObs.notifications(), 1)

        # Make it visible.
        object3d.setVisibility(True)
        self.assertTrue(object3d.visibility())

        # We should have got one more notification.
        self.assertEqual(visObs.notifications(), 2)

        # Remove the observer.
        ufe.Object3d.removeObserver(visObs)
        self.assertFalse(ufe.Object3d.hasObserver(visObs))
        self.assertEqual(ufe.Object3d.nbObservers(), 0)