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 testSamples
        mayaUtils.openAppleBiteScene()

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

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|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")
示例#2
0
        def checkParentDone():
            # The xform now has the capsule as its child.
            xformChildren = xformHier.children()
            self.assertEqual(len(xformChildren), 1)
            self.assertIn('Capsule1', childrenNames(xformChildren))

            # Confirm that the capsule has not moved in world space.  Must
            # re-create the prim and its scene item, as its path has changed.
            capsulePath = ufe.Path([
                proxyShapePathSegment,
                usdUtils.createUfePathSegment('/Xform1/Capsule1')
            ])
            capsulePrim = mayaUsd.ufe.ufePathToPrim(
                ufe.PathString.string(capsulePath))
            capsuleXformable = UsdGeom.Xformable(capsulePrim)
            capsuleItem = ufe.Hierarchy.createItem(capsulePath)
            capsuleT3d = ufe.Transform3d.transform3d(capsuleItem)
            capsuleWorld = capsuleT3d.inclusiveMatrix()
            assertVectorAlmostEqual(self, capsuleWorldPre,
                                    matrixToList(capsuleWorld))

            # The capsule's transform ops now have Maya fallback stack ops.  A
            # scale fallback op is added, even though it's uniform unit.
            self.assertEqual(
                capsuleXformable.GetXformOpOrderAttr().Get(),
                Vt.TokenArray(
                    ("xformOp:translate", "xformOp:rotateXYZ",
                     "xformOp:rotateX", "xformOp:translate:maya_fallback",
                     "xformOp:rotateXYZ:maya_fallback",
                     "xformOp:scale:maya_fallback")))
示例#3
0
    def testMoveUSD(self):
        '''Move USD object, read through the Transform3d interface.'''

        # Select Ball_35 to move it.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|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)
示例#4
0
        def checkParentDone():
            # The xform now has the capsule as its child.
            xformChildren = xformHier.children()
            self.assertEqual(len(xformChildren), 1)
            self.assertIn('Capsule1', childrenNames(xformChildren))

            # Confirm that the capsule has not moved in world space.  Must
            # re-create the prim and its scene item, as its path has changed.
            capsulePath = ufe.Path([
                proxyShapePathSegment,
                usdUtils.createUfePathSegment('/Xform1/Capsule1')
            ])
            capsulePrim = mayaUsd.ufe.ufePathToPrim(
                ufe.PathString.string(capsulePath))
            capsuleXformable = UsdGeom.Xformable(capsulePrim)
            capsuleItem = ufe.Hierarchy.createItem(capsulePath)
            capsuleT3d = ufe.Transform3d.transform3d(capsuleItem)
            capsuleWorld = capsuleT3d.inclusiveMatrix()
            assertVectorAlmostEqual(self,
                                    capsuleWorldPre,
                                    matrixToList(capsuleWorld),
                                    places=6)
            # Using setMatrixCmd() on a common transform API prim will set
            # translate, rotate, and scale.
            self.assertEqual(
                capsuleXformable.GetXformOpOrderAttr().Get(),
                Vt.TokenArray(("xformOp:translate", "xformOp:translate:pivot",
                               "xformOp:rotateXYZ", "xformOp:scale",
                               "!invert!xformOp:translate:pivot")))
示例#5
0
    def testMultiSelectMoveUSD(self):
        '''Move multiple USD objects, read through Transform3d interface.'''

        # Select multiple balls to move them.
        proxyShapePathSegment = mayaUtils.createUfePathSegment(
            "|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 testRenameRestrictionSameLayerDef(self):
        '''Restrict renaming USD node. Cannot rename a prim defined on another layer.'''

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|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)
示例#7
0
    def testRotateScalePivotCompensationAfterExport(self):
        '''Rotate and scale pivots must match after export.'''

        cmds.file(new=True, force=True)
        mayaSphere = cmds.polySphere()[0]

        cmds.rotate(0, 0, -45, r=True, os=True, fo=True)
        cmds.scale(4, 3, 2, r=True)
        cmds.move(-2, -3, -4, "pSphere1.rotatePivot", r=True)
        cmds.move(7, 6, 5, "pSphere1.scalePivot", r=True)

        # Export out, reference back in using proxy shape.
        usdFilePath = os.path.abspath('UsdExportMayaXformStack.usda')
        cmds.mayaUSDExport(file=usdFilePath)

        # Reference it back in.
        proxyShape = cmds.createNode('mayaUsdProxyShape')
        cmds.setAttr('mayaUsdProxyShape1.filePath', usdFilePath, type='string')

        # MAYA-101766: awkward plug access for non-interactive stage loading.
        outStageData = nameToPlug('mayaUsdProxyShape1.outStageData')
        outStageData.asMDataHandle()

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

        spherePathSegment = usdUtils.createUfePathSegment('/pSphere1')
        spherePath = ufe.Path([proxyShapePathSegment, spherePathSegment])
        sphereItem = ufe.Hierarchy.createItem(spherePath)
        usdSphereT3d = ufe.Transform3d.transform3d(sphereItem)

        # If the Transform3d interface can't handle rotate or scale pivot
        # compensation, skip this test.
        if usdSphereT3d.translateRotatePivotCmd() is None or \
           usdSphereT3d.translateScalePivotCmd() is None:
            raise unittest.SkipTest(
                "Rotate or scale pivot compensation unsupported.")

        # Maya object and its exported USD object twin should have the
        # same pivots and pivot compensations.
        checkPivotsAndCompensations(self, "pSphere1", usdSphereT3d)

        sn = ufe.GlobalSelection.get()
        sn.clear()
        sn.append(sphereItem)

        # Move only the rotate pivot.
        cmds.move(-1, -2, -3, r=True, urp=True)
        cmds.move(-1, -2, -3, "pSphere1.rotatePivot", r=True)

        checkPivotsAndCompensations(self, "pSphere1", usdSphereT3d)

        # Move only the scale pivot.
        cmds.move(-4, -3, -2, r=True, usp=True)
        cmds.move(-4, -3, -2, "pSphere1.scalePivot", r=True)

        checkPivotsAndCompensations(self, "pSphere1", usdSphereT3d)
示例#8
0
 def hierarchyBefore():
     aPath = ufe.Path(
         [psPathSegment,
          usdUtils.createUfePathSegment('/A')])
     a = ufe.Hierarchy.createItem(aPath)
     bPath = aPath + ufe.PathComponent('B')
     b = ufe.Hierarchy.createItem(bPath)
     cPath = bPath + ufe.PathComponent('C')
     c = ufe.Hierarchy.createItem(cPath)
     ePath = dPath + ufe.PathComponent('E')
     e = ufe.Hierarchy.createItem(ePath)
     fPath = ePath + ufe.PathComponent('F')
     f = ufe.Hierarchy.createItem(fPath)
     gPath = ufe.Path(
         [psPathSegment,
          usdUtils.createUfePathSegment('/G')])
     g = ufe.Hierarchy.createItem(gPath)
     return [a, b, c, e, f, g]
示例#9
0
 def getItem(path):
     '''Get the UFE scene item and USD prim for an item under a USD path'''
     fullPath = ufe.Path([
         mayaUtils.createUfePathSegment("|transform1|proxyShape1"),
         usdUtils.createUfePathSegment(path)
     ])
     item = ufe.Hierarchy.createItem(fullPath)
     prim = mayaUsd.ufe.ufePathToPrim(ufe.PathString.string(fullPath))
     return item, prim
示例#10
0
 def hierarchyBefore():
     retVal = []
     aPath = ufe.Path(
         [psPathSegment,
          usdUtils.createUfePathSegment('/A')])
     retVal.append(ufe.Hierarchy.createItem(aPath))
     for i in range(4):
         aPath = aPath + ufe.PathComponent('A')
         retVal.append(ufe.Hierarchy.createItem(aPath))
     return retVal
示例#11
0
    def testRenameProxyShape(self):
        '''Rename proxy shape, UFE lookup should succeed.'''

        mayaSegment = mayaUtils.createUfePathSegment("|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("|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)
示例#12
0
    def testVisibility(self):
        '''Test the Object3d visibility methods.'''

        # Open top_layer.ma scene in testSamples
        mayaUtils.openTopLayerScene()

        # Get a scene item for Ball_35.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|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)
示例#13
0
    def testRenameSpecialCharacter(self):
        # open twoSpheres.ma scene in testSamples
        mayaUtils.openTwoSpheresScene()

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

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|usdSphereParent|usdSphereParentShape')
        usdPathSegment = usdUtils.createUfePathSegment('/sphereXform/sphere')
        basePath = ufe.Path([mayaPathSegment, usdPathSegment])
        usdSphereItem = ufe.Hierarchy.createItem(basePath)

        ufe.GlobalSelection.get().append(usdSphereItem)

        # 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 with special chars
        newNameWithSpecialChars = '!@#%$@$=sph^e.re_*()<>}021|'
        cmds.rename(newNameWithSpecialChars)

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

        # prim names are not allowed to have special characters except '_'
        regex = re.compile('[@!#$%^&*()<>?/\|}{~:]')
        self.assertFalse(regex.search(usdPrim.GetName()))

        # rename starting with digits.
        newNameStartingWithDigit = '09123Potato'
        self.assertFalse(Tf.IsValidIdentifier(newNameStartingWithDigit))
        cmds.rename(newNameStartingWithDigit)

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

        # prim names are not allowed to start with digits
        newValidName = Tf.MakeValidIdentifier(newNameStartingWithDigit)
        self.assertEqual(usdPrim.GetName(), newValidName)
示例#14
0
    def testComboMaya(self):
        '''Move, rotate, and scale Maya object, read through the Transform3d interface.'''
        # Give the sphere an initial position, rotation, scale, and select it.
        sphereObj = om.MSelectionList().add('pSphere1').getDagPath(0).node()
        sphereFn = om.MFnTransform(sphereObj)

        expectedTRS = None
        if (self.move in self.ops):
            expectedTRS = self.updateTRS(expectedTRS, self.move, [1, 2, 3])
            t = self.extractTRS(expectedTRS, self.move)
            sphereFn.setTranslation(om.MVector(t[0], t[1], t[2]),
                                    om.MSpace.kTransform)
        if (self.rotate in self.ops):
            expectedTRS = self.updateTRS(expectedTRS, self.rotate,
                                         [30, 60, 90])
            r = self.extractTRS(expectedTRS, self.rotate)
            sphereFn.setRotation(
                om.MEulerRotation(radians(r[0]), radians(r[1]), radians(r[2])),
                om.MSpace.kTransform)

        if (self.scale in self.ops):
            expectedTRS = self.updateTRS(expectedTRS, self.scale, [1, 2, 3])
            s = self.extractTRS(expectedTRS, self.scale)
            sphereFn.setScale(om.MVector(s[0], s[1], s[2]))

        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 retrieve the translation.
        self.runTimes[self.move] = partial(sphereFn.translation,
                                           om.MSpace.kTransform)
        self.ufes[self.move] = partial(transform3dTranslation, transform3d)

        # Set up the callables that will retrieve the rotation.
        self.runTimes[self.rotate] = partial(sphereFn.rotation,
                                             om.MSpace.kTransform)
        self.ufes[self.rotate] = partial(transform3dRotation, transform3d)

        # Set up the callables that will retrieve the scale.
        self.runTimes[self.scale] = partial(sphereFn.scale)
        self.ufes[self.scale] = partial(transform3dScale, transform3d)

        self.runTestCombo(expectedTRS)
示例#15
0
    def testEditRouter(self):
        '''Test edit router functionality.'''

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

        # Create the following hierarchy:
        #
        # ps
        #  |_ A
        #      |_ B
        #
        # We A and duplicate it.

        psPathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer()
        stage = mayaUsd.lib.GetPrim(psPathStr).GetStage()
        stage.DefinePrim('/A', 'Xform')
        stage.DefinePrim('/A/B', 'Xform')

        psPath = ufe.PathString.path(psPathStr)
        psPathSegment = psPath.segments[0]
        aPath = ufe.Path([psPathSegment, usdUtils.createUfePathSegment('/A')])
        a = ufe.Hierarchy.createItem(aPath)
        bPath = aPath + ufe.PathComponent('B')
        b = ufe.Hierarchy.createItem(bPath)

        # Add a sub-layer, where the parent edit should write to.
        subLayerId = cmds.mayaUsdLayerEditor(stage.GetRootLayer().identifier,
                                             edit=True,
                                             addAnonymous="aSubLayer")[0]

        mayaUsd.lib.registerEditRouter('duplicate', firstSubLayer)

        sn = ufe.GlobalSelection.get()
        sn.clear()
        sn.append(a)

        cmds.duplicate()

        sublayer01 = Sdf.Find(subLayerId)
        self.assertIsNotNone(sublayer01)
        self.assertIsNotNone(sublayer01.GetPrimAtPath('/A1/B'))
示例#16
0
    def testRenameNotifications(self):
        '''Rename a USD node and test for the UFE notifications.'''

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

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

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|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()

        # 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())
示例#17
0
    def testAnimatedBoundingBox(self):
        '''Test the Object3d bounding box interface for animated geometry.'''

        # Open sphereAnimatedRadiusProxyShape.ma scene in testSamples
        mayaUtils.openSphereAnimatedRadiusScene()

        # 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(
            '|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 range(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)
示例#18
0
    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)
        sphereFn.setTranslation(expected, om.MSpace.kTransform)
        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 retrieve the translation.
        self.runTimeTranslation = partial(sphereFn.translation,
                                          om.MSpace.kTransform)
        self.ufeTranslation = partial(transform3dTranslation, transform3d)

        self.runTestMove(expected)
示例#19
0
    def testRenameUniqueName(self):
        # open tree.ma scene in testSamples
        mayaUtils.openTreeScene()

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

        # select a USD object.
        mayaPathSegment = mayaUtils.createUfePathSegment(
            '|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"),
        ])
示例#20
0
            def checkParentDone():
                # The xform now has the capsule as its child.
                xformChildren = xformHier.children()
                self.assertEqual(len(xformChildren), 1)
                self.assertIn('Capsule1', childrenNames(xformChildren))

                # Confirm that the capsule has not moved in world space.  Must
                # re-create the prim and its scene item after path change.
                capsulePath = ufe.Path([
                    proxyShapePathSegment,
                    usdUtils.createUfePathSegment('/Xform1/Capsule1')
                ])
                capsulePrim = mayaUsd.ufe.ufePathToPrim(
                    ufe.PathString.string(capsulePath))
                capsuleXformable = UsdGeom.Xformable(capsulePrim)
                capsuleItem = ufe.Hierarchy.createItem(capsulePath)
                capsuleT3d = ufe.Transform3d.transform3d(capsuleItem)
                capsuleWorld = capsuleT3d.inclusiveMatrix()
                assertVectorAlmostEqual(self, capsuleWorldPre,
                                        matrixToList(capsuleWorld))

                # No change in the capsule's transform ops.
                self.assertEqual(capsuleXformable.GetXformOpOrderAttr().Get(),
                                 Vt.TokenArray(matrixOps))

                # Matrix ops that were not targeted did not change.
                for checkMatrixOp in matrixOps:
                    if checkMatrixOp == matrixOp:
                        continue
                    op = UsdGeom.XformOp(
                        capsulePrim.GetAttribute(checkMatrixOp))
                    self.assertEqual(
                        op.GetOpTransform(
                            mayaUsd.ufe.getTime(
                                ufe.PathString.string(capsulePath))),
                        matrixValues[checkMatrixOp])
示例#21
0
    def testGroupKind(self):
        """
        Tests that grouping maintains a contiguous model hierarchy when the
        parent of the group is in the model hierarchy.
        """
        mayaPathSegment = mayaUtils.createUfePathSegment(
            "|transform1|proxyShape1")

        usdSegmentBall3 = usdUtils.createUfePathSegment(
            "/Ball_set/Props/Ball_3")
        ball3Path = ufe.Path([mayaPathSegment, usdSegmentBall3])
        ball3Item = ufe.Hierarchy.createItem(ball3Path)

        usdSegmentBall5 = usdUtils.createUfePathSegment(
            "/Ball_set/Props/Ball_5")
        ball5Path = ufe.Path([mayaPathSegment, usdSegmentBall5])
        ball5Item = ufe.Hierarchy.createItem(ball5Path)

        usdSegmentProps = usdUtils.createUfePathSegment("/Ball_set/Props")
        propsPath = ufe.Path([mayaPathSegment, usdSegmentProps])
        propsItem = ufe.Hierarchy.createItem(propsPath)

        ufeSelection = ufe.GlobalSelection.get()
        ufeSelection.append(ball3Item)
        ufeSelection.append(ball5Item)

        groupName = "newGroup"
        cmds.group(name=groupName)

        newGroupPath = propsPath + ufe.PathComponent("%s1" % groupName)
        newGroupItem = ufe.Hierarchy.createItem(newGroupPath)
        newGroupPrim = usdUtils.getPrimFromSceneItem(newGroupItem)

        # The "Props" prim that was the parent of both "Ball" prims has
        # kind=group and is part of the model hierarchy, so the new group prim
        # should also have kind=group and be included in the model hierarchy.
        self.assertEqual(
            Usd.ModelAPI(newGroupPrim).GetKind(), Kind.Tokens.group)
        self.assertTrue(newGroupPrim.IsModel())

        cmds.undo()

        # Clear the kind metadata on the "Props" prim before testing again.
        propsPrim = usdUtils.getPrimFromSceneItem(propsItem)
        Usd.ModelAPI(propsPrim).SetKind("")
        self.assertFalse(propsPrim.IsModel())

        # Freshen the UFE scene items so they have valid handles to their
        # UsdPrims.
        ball3Item = ufe.Hierarchy.createItem(ball3Path)
        ball5Item = ufe.Hierarchy.createItem(ball5Path)

        ufeSelection.clear()
        ufeSelection.append(ball3Item)
        ufeSelection.append(ball5Item)

        cmds.group(name=groupName)

        newGroupItem = ufe.Hierarchy.createItem(newGroupPath)
        newGroupPrim = usdUtils.getPrimFromSceneItem(newGroupItem)

        # When the "Props" prim does not have an authored kind and is not part
        # of the model hierarchy, the new group prim should not have any kind
        # authored either.
        self.assertEqual(Usd.ModelAPI(newGroupPrim).GetKind(), "")
        self.assertFalse(newGroupPrim.IsModel())
示例#22
0
    def testComboUSD(self):
        '''Move, rotate, and scale USD object, read through the Transform3d interface.'''

        # Select Ball_35 to move, rotate, and scale it.
        ball35Path = ufe.Path([
            mayaUtils.createUfePathSegment("|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 ops with the USD run-time ops.  To
        # obtain the full ops of Ball_35, we need to add the USD
        # ops to the Maya proxy shape ops.
        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())

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

        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 translation.
        self.runTimes[self.move] = ball35Translation
        self.ufes[self.move] = partial(transform3dTranslation, transform3d)

        # Set up the callables that will retrieve the rotation.
        self.runTimes[self.rotate] = ball35Rotation
        self.ufes[self.rotate] = partial(transform3dRotation, transform3d)

        # Set up the callables that will retrieve the scale.
        self.runTimes[self.scale] = ball35Scale
        self.ufes[self.scale] = partial(transform3dScale, transform3d)

        # Save the initial position to the memento list.
        expectedTRS = None
        if (self.move in self.ops):
            v = ball35Translation()
            expectedTRS = self.updateTRS(expectedTRS, self.move,
                                         [v[0], v[1], v[2]])
        if (self.rotate in self.ops):
            r = ball35Rotation().asVector()
            expectedTRS = self.updateTRS(
                expectedTRS, self.rotate,
                [degrees(r[0]), degrees(r[1]),
                 degrees(r[2])])

        if (self.scale in self.ops):
            s = ball35Scale()
            expectedTRS = self.updateTRS(expectedTRS, self.scale,
                                         [s[0], s[1], s[2]])

        self.runTestCombo(expectedTRS)
示例#23
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)

        #######
        # Create a UFE scene item from the parent Xform of the sphere prim.
        parentPathSegment = usdUtils.createUfePathSegment('/parent')
        parentPath = ufe.Path([proxyShapePathSegment, parentPathSegment])
        parentItem = ufe.Hierarchy.createItem(parentPath)

        # Get its Object3d interface.
        parentObject3d = ufe.Object3d.object3d(parentItem)

        # Get its bounding box.
        parentUFEBBox = parentObject3d.boundingBox()

        # Compare it to sphere's extents.
        assertVectorEqual(self, ufeBBox.min.vector, parentUFEBBox.min.vector)
        assertVectorEqual(self, ufeBBox.max.vector, parentUFEBBox.max.vector)


        #######
        # Remove the test file.
        os.remove(usdFilePath)
示例#24
0
    def testRenameUndo(self):
        '''Rename USD node.'''

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

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

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

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

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

        # 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())

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

        # rename
        cylinderItemType = cylinderItem.nodeType()
        newName = 'pCylinder1_Renamed'
        cmds.rename(newName)

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

        self.assertEqual(pCylinder1RenName, newName)

        propsChildren = propsHierarchy.children()

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

        cmds.undo()
        self.assertEqual(cylinderItemType,
                         ufe.GlobalSelection.get().back().nodeType())

        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(pCylinder1RenName, propsChildrenNames)
        self.assertIn('pCylinder1', propsChildrenNames)
        self.assertEqual(len(propsChildren), len(propsChildrenPre))

        cmds.redo()
        self.assertEqual(cylinderItemType,
                         ufe.GlobalSelection.get().back().nodeType())

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

        self.assertIn(pCylinder1RenName, propsChildrenNames)
        self.assertNotIn('pCylinder1', propsChildrenNames)
        self.assertEqual(len(propsChildren), len(propsChildrenPre))
示例#25
0
    def testDuplicate(self):
        '''Duplicate Maya and USD objects.'''

        # Select two objects, one Maya, one USD.
        spherePath = ufe.Path(mayaUtils.createUfePathSegment("|pSphere1"))
        sphereItem = ufe.Hierarchy.createItem(spherePath)
        sphereHierarchy = ufe.Hierarchy.hierarchy(sphereItem)
        worldItem = sphereHierarchy.parent()

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

        worldHierarchy = ufe.Hierarchy.hierarchy(worldItem)
        worldChildrenPre = worldHierarchy.children()
        propsHierarchy = ufe.Hierarchy.hierarchy(propsItem)
        propsChildrenPre = propsHierarchy.children()

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

        # Set the edit target to the layer in which Ball_35 is defined (has a
        # primSpec, in USD terminology).  Otherwise, duplication will not find
        # a source primSpec to copy.  Layers are the (anonymous) session layer,
        # the root layer, then the Assembly_room_set sublayer.  Trying to find
        # the layer by name is not practical, as it requires the full path
        # name, which potentially differs per run-time environment.
        ball35Prim = usdUtils.getPrimFromSceneItem(ball35Item)
        stage = ball35Prim.GetStage()

        layer = stage.GetLayerStack()[2]
        stage.SetEditTarget(layer)

        cmds.duplicate()

        # The duplicate command doesn't return duplicated non-Maya UFE objects.
        # They are in the selection, in the same order as the sources.
        snIter = iter(ufe.GlobalSelection.get())
        sphereDupItem = next(snIter)
        sphereDupName = str(sphereDupItem.path().back())
        ball35DupItem = next(snIter)
        ball35DupName = str(ball35DupItem.path().back())

        worldChildren = worldHierarchy.children()
        propsChildren = propsHierarchy.children()

        self.assertEqual(len(worldChildren) - len(worldChildrenPre), 1)
        self.assertEqual(len(propsChildren) - len(propsChildrenPre), 1)

        self.assertIn(sphereDupItem, worldChildren)
        self.assertIn(ball35DupItem, propsChildren)

        cmds.undo()

        # The duplicated items should no longer appear in the child list of
        # their parents.

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

        worldHierarchy = ufe.Hierarchy.hierarchy(worldItem)
        worldChildren = worldHierarchy.children()
        propsHierarchy = ufe.Hierarchy.hierarchy(propsItem)
        propsChildren = propsHierarchy.children()

        worldChildrenNames = childrenNames(worldChildren)
        propsChildrenNames = childrenNames(propsChildren)

        self.assertNotIn(sphereDupName, worldChildrenNames)
        self.assertNotIn(ball35DupName, propsChildrenNames)

        # The duplicated items shoudl reappear after a redo
        cmds.redo()

        snIter = iter(ufe.GlobalSelection.get())
        sphereDupItem = next(snIter)
        ball35DupItem = next(snIter)

        worldChildren = worldHierarchy.children()
        propsChildren = propsHierarchy.children()

        self.assertEqual(len(worldChildren) - len(worldChildrenPre), 1)
        self.assertEqual(len(propsChildren) - len(propsChildrenPre), 1)

        self.assertIn(sphereDupItem, worldChildren)
        self.assertIn(ball35DupItem, propsChildren)

        cmds.undo()

        # The duplicated items should not be assigned to the name of a
        # deactivated USD item.

        cmds.select(clear=True)

        # Delete the even numbered props:
        evenPropsChildrenPre = propsChildrenPre[0:35:2]
        for propChild in evenPropsChildrenPre:
            ufe.GlobalSelection.get().append(propChild)
        cmds.delete()

        worldHierarchy = ufe.Hierarchy.hierarchy(worldItem)
        worldChildren = worldHierarchy.children()
        propsHierarchy = ufe.Hierarchy.hierarchy(propsItem)
        propsChildren = propsHierarchy.children()
        propsChildrenPostDel = propsHierarchy.children()

        # Duplicate Ball_1
        ufe.GlobalSelection.get().append(propsChildrenPostDel[0])

        cmds.duplicate()

        snIter = iter(ufe.GlobalSelection.get())
        ballDupItem = next(snIter)
        ballDupName = str(ballDupItem.path().back())

        self.assertNotIn(ballDupItem, propsChildrenPostDel)
        self.assertNotIn(ballDupName, propsChildrenNames)
        self.assertEqual(ballDupName, "Ball_36")

        cmds.undo()  # undo duplication
        cmds.undo()  # undo deletion
示例#26
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")
示例#27
0
    def testUsdGroup(self):
        '''Creation of USD group objects.'''

        mayaPathSegment = mayaUtils.createUfePathSegment(
            "|transform1|proxyShape1")

        usdSegmentBall5 = usdUtils.createUfePathSegment(
            "/Ball_set/Props/Ball_5")
        ball5Path = ufe.Path([mayaPathSegment, usdSegmentBall5])
        ball5Item = ufe.Hierarchy.createItem(ball5Path)

        usdSegmentBall3 = usdUtils.createUfePathSegment(
            "/Ball_set/Props/Ball_3")
        ball3Path = ufe.Path([mayaPathSegment, usdSegmentBall3])
        ball3Item = ufe.Hierarchy.createItem(ball3Path)

        usdSegmentProps = usdUtils.createUfePathSegment("/Ball_set/Props")
        parentPath = ufe.Path([mayaPathSegment, usdSegmentProps])
        parentItem = ufe.Hierarchy.createItem(parentPath)

        parentHierarchy = ufe.Hierarchy.hierarchy(parentItem)
        parentChildrenPre = parentHierarchy.children()
        self.assertEqual(len(parentChildrenPre), 6)

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

        # set the edit target to balls.usda
        layer = stage.GetLayerStack()[1]
        self.assertEqual("ballset.usda", layer.GetDisplayName())
        stage.SetEditTarget(layer)

        if (os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') > '3000'):

            globalSn = ufe.GlobalSelection.get()
            globalSn.append(ball5Item)
            globalSn.append(ball3Item)

            # group
            groupName = cmds.group(ufe.PathString.string(ball5Path),
                                   ufe.PathString.string(ball3Path),
                                   n="newGroup")
        else:
            newGroupName = ufe.PathComponent("newGroup")

            ufeSelectionList = ufe.Selection()
            ufeSelectionList.append(ball5Item)
            ufeSelectionList.append(ball3Item)

            groupCmd = parentHierarchy.createGroupCmd(ufeSelectionList,
                                                      newGroupName)
            groupCmd.execute()

        # Group object (a.k.a parent) will be added to selection list. This behavior matches the native Maya group command.
        globalSelection = ufe.GlobalSelection.get()

        groupPath = ufe.Path([
            mayaPathSegment,
            usdUtils.createUfePathSegment("/Ball_set/Props/newGroup1")
        ])
        self.assertEqual(globalSelection.front(),
                         ufe.Hierarchy.createItem(groupPath))

        # Group object (a.k.a parent) will be added to selection list. This behavior matches the native Maya group command.
        globalSelection = ufe.GlobalSelection.get()

        groupPath = ufe.Path([
            mayaPathSegment,
            usdUtils.createUfePathSegment("/Ball_set/Props/newGroup1")
        ])
        self.assertEqual(globalSelection.front(),
                         ufe.Hierarchy.createItem(groupPath))

        parentChildrenPost = parentHierarchy.children()
        self.assertEqual(len(parentChildrenPost), 5)

        # The command will now append a number 1 at the end to match the naming
        # convention in Maya.
        if (os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') > '3000'):
            newGroupPath = parentPath + ufe.PathComponent(groupName)
        else:
            newGroupPath = parentPath + ufe.PathComponent("newGroup1")

        # Make sure the new group item has the correct Usd type
        newGroupItem = ufe.Hierarchy.createItem(newGroupPath)
        newGroupPrim = usdUtils.getPrimFromSceneItem(newGroupItem)
        newGroupType = newGroupPrim.GetTypeName()
        self.assertEqual(newGroupType, 'Xform')

        childPaths = set([child.path() for child in parentChildrenPost])

        self.assertTrue(newGroupPath in childPaths)
        self.assertTrue(ball5Path not in childPaths)
        self.assertTrue(ball3Path not in childPaths)

        if (os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') > '3000'):
            cmds.undo()
        else:
            groupCmd.undo()

        # global selection should not be empty after undo.
        if (os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') > '3004'):
            self.assertEqual(len(globalSelection), 2)
        else:
            self.assertEqual(len(globalSelection), 1)

        parentChildrenUndo = parentHierarchy.children()
        self.assertEqual(len(parentChildrenUndo), 6)

        childPathsUndo = set([child.path() for child in parentChildrenUndo])
        self.assertTrue(newGroupPath not in childPathsUndo)
        self.assertTrue(ball5Path in childPathsUndo)
        self.assertTrue(ball3Path in childPathsUndo)

        if (os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') > '3000'):
            cmds.redo()
        else:
            groupCmd.redo()

        # global selection should still have the group path.
        self.assertEqual(globalSelection.front(),
                         ufe.Hierarchy.createItem(groupPath))

        parentChildrenRedo = parentHierarchy.children()
        self.assertEqual(len(parentChildrenRedo), 5)

        childPathsRedo = set([child.path() for child in parentChildrenRedo])
        self.assertTrue(newGroupPath in childPathsRedo)
        self.assertTrue(ball5Path not in childPathsRedo)
        self.assertTrue(ball3Path not in childPathsRedo)
示例#28
0
    def testGroupRestriction(self):
        ''' Verify group restriction. '''
        mayaPathSegment = mayaUtils.createUfePathSegment(
            "|transform1|proxyShape1")

        usdSegmentBall3 = usdUtils.createUfePathSegment(
            "/Ball_set/Props/Ball_3")
        ball3Path = ufe.Path([mayaPathSegment, usdSegmentBall3])
        ball3Item = ufe.Hierarchy.createItem(ball3Path)

        usdSegmentBall5 = usdUtils.createUfePathSegment(
            "/Ball_set/Props/Ball_5")
        ball5Path = ufe.Path([mayaPathSegment, usdSegmentBall5])
        ball5Item = ufe.Hierarchy.createItem(ball5Path)

        usdSegmentProps = usdUtils.createUfePathSegment("/Ball_set/Props")
        propsPath = ufe.Path([mayaPathSegment, usdSegmentProps])
        propsItem = ufe.Hierarchy.createItem(propsPath)

        ufeSelection = ufe.GlobalSelection.get()
        ufeSelection.append(ball3Item)
        ufeSelection.append(ball5Item)

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

        # set the edit target to the session layer
        stage.SetEditTarget(stage.GetSessionLayer())

        # expect the exception happens
        with self.assertRaises(RuntimeError):
            cmds.group(name="newGroup")

        # set the edit target to the root layer
        stage.SetEditTarget(stage.GetRootLayer())

        # create a sphere
        stage.DefinePrim('/Sphere1', 'Sphere')

        # select the Sphere
        spherePath = ufe.PathString.path(
            "{},/Sphere1".format("|transform1|proxyShape1"))
        sphereItem = ufe.Hierarchy.createItem(spherePath)
        ufeSelection = ufe.GlobalSelection.get()
        ufeSelection.clear()
        ufeSelection.append(sphereItem)

        # set the edit target to the session layer
        stage.SetEditTarget(stage.GetSessionLayer())

        # expect the exception happens.
        with self.assertRaises(RuntimeError):
            cmds.group(name="newGroup")

        # undo
        cmds.undo()

        # verify that group1 doesn't exist after the undo
        self.assertEqual([item for item in stage.Traverse()], [
            stage.GetPrimAtPath("/Ball_set"),
            stage.GetPrimAtPath("/Ball_set/Props"),
            stage.GetPrimAtPath("/Ball_set/Props/Ball_1"),
            stage.GetPrimAtPath("/Ball_set/Props/Ball_2"),
            stage.GetPrimAtPath("/Ball_set/Props/Ball_3"),
            stage.GetPrimAtPath("/Ball_set/Props/Ball_4"),
            stage.GetPrimAtPath("/Ball_set/Props/Ball_5"),
            stage.GetPrimAtPath("/Ball_set/Props/Ball_6"),
            stage.GetPrimAtPath("/Sphere1")
        ])
示例#29
0
    def testGroupHierarchyWithRenaming(self):
        '''Grouping a node and a descendant when all descendants share the same name'''
        # MAYA-113532: when grouping a node and its descendant sharing the same name, we need to
        # detect the name conflicts and rename as we reparent into the group.

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

        # Create the following hierarchy:
        #
        # ps
        #  |_ A
        #      |_ A
        #          |_ A
        #              |_ A
        #                  |_ A
        #
        # And group them all at the same level, which implies renaming.

        psPathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer()
        stage = mayaUsd.lib.GetPrim(psPathStr).GetStage()
        stage.DefinePrim('/A', 'Xform')
        stage.DefinePrim('/A/B', 'Cube')
        stage.DefinePrim('/A/A', 'Xform')
        stage.DefinePrim('/A/A/C', 'Cone')
        stage.DefinePrim('/A/A/A', 'Xform')
        stage.DefinePrim('/A/A/A/D', 'Sphere')
        stage.DefinePrim('/A/A/A/A', 'Xform')
        stage.DefinePrim('/A/A/A/A/E', 'Capsule')
        stage.DefinePrim('/A/A/A/A/A', 'Xform')
        stage.DefinePrim('/A/A/A/A/A/F', 'Cylinder')

        psPath = ufe.PathString.path(psPathStr)
        psPathSegment = psPath.segments[0]
        ps = ufe.Hierarchy.createItem(psPath)
        psHier = ufe.Hierarchy.hierarchy(ps)
        groupPath = ufe.Path(
            [psPathSegment,
             usdUtils.createUfePathSegment('/group1')])

        def hierarchyBefore():
            retVal = []
            aPath = ufe.Path(
                [psPathSegment,
                 usdUtils.createUfePathSegment('/A')])
            retVal.append(ufe.Hierarchy.createItem(aPath))
            for i in range(4):
                aPath = aPath + ufe.PathComponent('A')
                retVal.append(ufe.Hierarchy.createItem(aPath))
            return retVal

        a, aa, aaa, aaaa, aaaaa = hierarchyBefore()

        def checkBefore():
            # We care about 2 things:
            #  - All Xforms are named A
            #  - The non-xform stay in the right order:
            order = [("B", "Cube"), ("C", "Cone"), ("D", "Sphere"),
                     ("E", "Capsule"), ("F", "Cylinder")]
            psChildren = psHier.children()
            self.assertEqual(len(psChildren), 1)
            a = psChildren[0]
            for gprimName, gprimTypeName in order:
                aHier = ufe.Hierarchy.hierarchy(a)
                aChildren = aHier.children()
                if gprimName == "F":
                    self.assertEqual(len(aChildren), 1)
                else:
                    self.assertEqual(len(aChildren), 2)
                for child in aChildren:
                    prim = mayaUsd.ufe.ufePathToPrim(
                        ufe.PathString.string(child.path()))
                    if child.nodeName() == "A":
                        self.assertEqual(prim.GetTypeName(), "Xform")
                        a = child
                    else:
                        self.assertEqual(child.nodeName(), gprimName)
                        self.assertEqual(prim.GetTypeName(), gprimTypeName)

        def checkAfter():
            # We care about 2 things:
            #  - Group has 5 Xform children. Don't care about names: they will be unique.
            #  - Each child has a one of the non-xform prims.
            members = set([("B", "Cube"), ("C", "Cone"), ("D", "Sphere"),
                           ("E", "Capsule"), ("F", "Cylinder")])
            group = ufe.Hierarchy.createItem(groupPath)
            groupHier = ufe.Hierarchy.hierarchy(group)
            groupChildren = groupHier.children()
            self.assertEqual(len(groupChildren), 5)
            foundMembers = set()
            for child in groupChildren:
                prim = mayaUsd.ufe.ufePathToPrim(
                    ufe.PathString.string(child.path()))
                self.assertEqual(prim.GetTypeName(), "Xform")
                childHier = ufe.Hierarchy.hierarchy(child)
                childChildren = childHier.children()
                self.assertEqual(len(childChildren), 1)
                member = childChildren[0]
                prim = mayaUsd.ufe.ufePathToPrim(
                    ufe.PathString.string(member.path()))
                foundMembers.add((member.nodeName(), prim.GetTypeName()))
            self.assertEqual(members, foundMembers)

        sn = ufe.GlobalSelection.get()
        sn.clear()
        # We randomize the order a bit to make sure previously moved items do
        # not affect the next one.
        sn.append(a)
        sn.append(aaa)
        sn.append(aa)
        sn.append(aaaaa)
        sn.append(aaaa)

        cmds.group()
        checkAfter()
        cmds.undo()
        checkBefore()
        cmds.redo()
        checkAfter()
示例#30
0
    def testGroupHierarchy(self):
        '''Grouping a node and a descendant.'''
        # MAYA-112957: when grouping a node and its descendant, with the node
        # selected first, the descendant path becomes stale as soon as its
        # ancestor gets reparented.  The Maya parent command must deal with
        # this.  A similar test is done for parenting in testParentCmd.py

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

        # Create the following hierarchy:
        #
        # ps
        #  |_ A
        #      |_ B
        #          |_ C
        #  |_ D
        #      |_ E
        #          |_ F
        #
        #  |_ G
        #
        # We will select A, B, C, E, F and G, in order, and group.  This will
        # create a new group under ps, with A, B, C, E, F and G as children.

        psPathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer()
        stage = mayaUsd.lib.GetPrim(psPathStr).GetStage()
        stage.DefinePrim('/A', 'Xform')
        stage.DefinePrim('/A/B', 'Xform')
        stage.DefinePrim('/A/B/C', 'Xform')
        stage.DefinePrim('/D', 'Xform')
        stage.DefinePrim('/D/E', 'Xform')
        stage.DefinePrim('/D/E/F', 'Xform')
        stage.DefinePrim('/G', 'Xform')

        psPath = ufe.PathString.path(psPathStr)
        psPathSegment = psPath.segments[0]
        ps = ufe.Hierarchy.createItem(psPath)
        psHier = ufe.Hierarchy.hierarchy(ps)
        dPath = ufe.Path([psPathSegment, usdUtils.createUfePathSegment('/D')])
        d = ufe.Hierarchy.createItem(dPath)
        dHier = ufe.Hierarchy.hierarchy(d)
        groupPath = ufe.Path(
            [psPathSegment,
             usdUtils.createUfePathSegment('/group1')])

        def hierarchyBefore():
            aPath = ufe.Path(
                [psPathSegment,
                 usdUtils.createUfePathSegment('/A')])
            a = ufe.Hierarchy.createItem(aPath)
            bPath = aPath + ufe.PathComponent('B')
            b = ufe.Hierarchy.createItem(bPath)
            cPath = bPath + ufe.PathComponent('C')
            c = ufe.Hierarchy.createItem(cPath)
            ePath = dPath + ufe.PathComponent('E')
            e = ufe.Hierarchy.createItem(ePath)
            fPath = ePath + ufe.PathComponent('F')
            f = ufe.Hierarchy.createItem(fPath)
            gPath = ufe.Path(
                [psPathSegment,
                 usdUtils.createUfePathSegment('/G')])
            g = ufe.Hierarchy.createItem(gPath)
            return [a, b, c, e, f, g]

        def hierarchyAfter():
            return [
                ufe.Hierarchy.createItem(groupPath + ufe.PathComponent(pc))
                for pc in ['A', 'B', 'C', 'E', 'F', 'G']
            ]

        def checkBefore(a, b, c, e, f, g):
            psChildren = psHier.children()
            aHier = ufe.Hierarchy.hierarchy(a)
            bHier = ufe.Hierarchy.hierarchy(b)
            cHier = ufe.Hierarchy.hierarchy(c)
            eHier = ufe.Hierarchy.hierarchy(e)
            fHier = ufe.Hierarchy.hierarchy(f)
            gHier = ufe.Hierarchy.hierarchy(g)

            self.assertIn(a, psChildren)
            self.assertIn(d, psChildren)
            self.assertIn(g, psChildren)
            self.assertIn(b, aHier.children())
            self.assertIn(c, bHier.children())
            self.assertIn(e, dHier.children())
            self.assertIn(f, eHier.children())
            self.assertFalse(gHier.hasChildren())

        def checkAfter(a, b, c, e, f, g):
            psChildren = psHier.children()
            self.assertNotIn(a, psChildren)
            self.assertIn(d, psChildren)
            self.assertNotIn(g, psChildren)

            group = ufe.Hierarchy.createItem(groupPath)
            groupHier = ufe.Hierarchy.hierarchy(group)
            groupChildren = groupHier.children()

            for child in [a, b, c, e, f, g]:
                hier = ufe.Hierarchy.hierarchy(child)
                self.assertFalse(hier.hasChildren())
                self.assertIn(child, groupChildren)

        children = hierarchyBefore()
        checkBefore(*children)

        sn = ufe.GlobalSelection.get()
        sn.clear()
        for child in children:
            sn.append(child)

        cmds.group()

        children = hierarchyAfter()
        checkAfter(*children)

        cmds.undo()

        children = hierarchyBefore()
        checkBefore(*children)

        cmds.redo()

        children = hierarchyAfter()
        checkAfter(*children)