Example #1
0
    def testDoOp(self):

        # Change visibility, undo / redo.
        cmd = self.contextOps.doOpCmd(['Toggle Visibility'])
        self.assertIsNotNone(cmd)

        attrs = ufe.Attributes.attributes(self.ball35Item)
        self.assertIsNotNone(attrs)
        visibility = attrs.attribute(UsdGeom.Tokens.visibility)
        self.assertIsNotNone(visibility)

        # Initially, Ball_35 has inherited visibility.
        self.assertEqual(visibility.get(), UsdGeom.Tokens.inherited)

        ufeCmd.execute(cmd)

        self.assertEqual(visibility.get(), UsdGeom.Tokens.invisible)

        cmds.undo()

        self.assertEqual(visibility.get(), UsdGeom.Tokens.inherited)

        cmds.redo()

        self.assertEqual(visibility.get(), UsdGeom.Tokens.invisible)

        cmds.undo()

        # Change variant in variant set.
        def shadingVariant():
            contextItems = self.contextOps.getItems(
                ['Variant Sets', 'shadingVariant'])

            for c in contextItems:
                if c.checked:
                    return c.item

        self.assertEqual(shadingVariant(), 'Ball_8')

        cmd = self.contextOps.doOpCmd(
            ['Variant Sets', 'shadingVariant', 'Cue'])
        self.assertIsNotNone(cmd)

        ufeCmd.execute(cmd)

        self.assertEqual(shadingVariant(), 'Cue')

        cmds.undo()

        self.assertEqual(shadingVariant(), 'Ball_8')

        cmds.redo()

        self.assertEqual(shadingVariant(), 'Cue')

        cmds.undo()
Example #2
0
    def runUndoRedo(self, attr, newVal, decimalPlaces=None):
        oldVal = attr.get()
        assert oldVal != newVal, "Undo / redo testing requires setting a value different from the current value"

        ufeCmd.execute(attr.setCmd(newVal))

        if decimalPlaces is not None:
            self.assertAlmostEqual(attr.get(), newVal, decimalPlaces)
            newVal = attr.get()
        else:
            self.assertEqual(attr.get(), newVal)

        cmds.undo()
        self.assertEqual(attr.get(), oldVal)
        cmds.redo()
        self.assertEqual(attr.get(), newVal)
Example #3
0
    def testZAttrChangeRedoAfterPrimCreateRedo(self):
        '''Redo attribute change after redo of prim creation.'''
        cmds.file(new=True, force=True)

        # Create a capsule, change one of its attributes.
        import mayaUsd_createStageWithNewLayer
        proxyShape = mayaUsd_createStageWithNewLayer.createStageWithNewLayer()
        proxyShapePath = ufe.PathString.path(proxyShape)
        proxyShapeItem = ufe.Hierarchy.createItem(proxyShapePath)
        proxyShapeContextOps = ufe.ContextOps.contextOps(proxyShapeItem)
        cmd = proxyShapeContextOps.doOpCmd(['Add New Prim', 'Capsule'])
        ufeCmd.execute(cmd)

        capsulePath = ufe.PathString.path('%s,/Capsule1' % proxyShape)
        capsuleItem = ufe.Hierarchy.createItem(capsulePath)

        # Create the attributes interface for the item.
        attrs = ufe.Attributes.attributes(capsuleItem)
        self.assertIsNotNone(attrs)
        self.assertTrue(attrs.hasAttribute('radius'))
        radiusAttr = attrs.attribute('radius')

        oldRadius = radiusAttr.get()

        ufeCmd.execute(radiusAttr.setCmd(2))

        newRadius = radiusAttr.get()

        self.assertEqual(newRadius, 2)
        self.assertNotEqual(oldRadius, newRadius)

        # Undo 2x: undo attr change and prim creation.
        cmds.undo()
        cmds.undo()

        # Redo 2x: prim creation, attr change.
        cmds.redo()
        cmds.redo()

        # Re-create item, as its underlying prim was re-created.
        capsuleItem = ufe.Hierarchy.createItem(capsulePath)
        attrs = ufe.Attributes.attributes(capsuleItem)
        radiusAttr = attrs.attribute('radius')

        self.assertEqual(radiusAttr.get(), newRadius)
Example #4
0
    def testAddNewPrimWithDelete(self):
        cmds.file(new=True, force=True)

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

        # Create a ContextOps interface for the proxy shape.
        proxyShapePath = ufe.Path(
            [mayaUtils.createUfePathSegment("|world|stage1|stageShape1")])
        proxyShapeItem = ufe.Hierarchy.createItem(proxyShapePath)
        contextOps = ufe.ContextOps.contextOps(proxyShapeItem)

        # Add a new Xform prim.
        cmd = contextOps.doOpCmd(['Add New Prim', 'Xform'])
        self.assertIsNotNone(cmd)
        ufeCmd.execute(cmd)

        # The proxy shape should now have a single UFE child item.
        proxyShapehier = ufe.Hierarchy.hierarchy(proxyShapeItem)
        self.assertTrue(proxyShapehier.hasChildren())
        self.assertEqual(len(proxyShapehier.children()), 1)

        # Using UFE, delete this new prim (which doesn't actually delete it but
        # instead makes it inactive).
        cmds.pickWalk(d='down')
        cmds.delete()

        # The proxy shape should now have no UFE child items (since we skip inactive).
        self.assertFalse(proxyShapehier.hasChildren())
        self.assertEqual(len(proxyShapehier.children()), 0)

        # Add another Xform prim (which should get a unique name taking into
        # account the prim we just made inactive).
        cmd = contextOps.doOpCmd(['Add New Prim', 'Xform'])
        self.assertIsNotNone(cmd)
        ufeCmd.execute(cmd)

        # The proxy shape should now have a single UFE child item.
        self.assertTrue(proxyShapehier.hasChildren())
        self.assertEqual(len(proxyShapehier.children()), 1)
Example #5
0
    def testUnload(self):
        mayaUtils.openTopLayerScene()

        propsPath = ufe.PathString.path(
            '|transform1|proxyShape1,/Room_set/Props')
        propsItem = ufe.Hierarchy.createItem(propsPath)
        propsHier = ufe.Hierarchy.hierarchy(propsItem)

        # Before unloading it should have 35 children (35 balls).
        self.assertTrue(propsHier.hasChildren())
        ball1Children = propsHier.children()
        self.assertEqual(len(ball1Children), 35)

        # Unload props
        contextOps = ufe.ContextOps.contextOps(propsItem)
        cmd = contextOps.doOpCmd(['Unload'])
        ufeCmd.execute(cmd)

        # After unloading, it should still have 35 children because
        # the children method returns unloaded prims by default.
        self.assertTrue(propsHier.hasChildren())
        ball1Children = propsHier.children()
        self.assertEqual(len(ball1Children), 35)
Example #6
0
    def testMayaSelectSwitchVariant(self):
        '''Stale selection items must be removed on variant switch.'''

        import mayaUsd_createStageWithNewLayer
        import maya.internal.ufeSupport.ufeCmdWrapper as ufeCmd

        # Create a scene with two variants.
        proxyShape = mayaUsd_createStageWithNewLayer.createStageWithNewLayer()
        stage = mayaUsd.lib.GetPrim(proxyShape).GetStage()
        top = stage.DefinePrim('/Xform1', 'Xform')
        vset = top.GetVariantSets().AddVariantSet('modelingVariant')
        vset.AddVariant('cube')
        vset.AddVariant('sphere')
        vset.SetVariantSelection('cube')
        with vset.GetVariantEditContext():
            stage.DefinePrim('/Xform1/Cube', 'Cube')
        vset.SetVariantSelection('sphere')
        with vset.GetVariantEditContext():
            stage.DefinePrim('/Xform1/Sphere', 'Sphere')

        # The sphere is the sole child of Xform1.  Get an attribute from it,
        # select it.
        xformPath = ufe.PathString.path('%s,/Xform1' % proxyShape)
        spherePath = ufe.PathString.path('%s,/Xform1/Sphere' % proxyShape)
        xformItem = ufe.Hierarchy.createItem(xformPath)
        sphereItem = ufe.Hierarchy.createItem(spherePath)

        xformHier = ufe.Hierarchy.hierarchy(xformItem)
        xformChildren = xformHier.children()
        self.assertEqual(len(xformChildren), 1)
        self.assertEqual(xformChildren[0].path(), spherePath)
        sphereAttrs = ufe.Attributes.attributes(sphereItem)
        sphereRadius = sphereAttrs.attribute('radius')
        self.assertEqual(sphereRadius.get(), 1)

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

        self.assertEqual(len(sn), 1)

        # Switch variants using a command: the cube is now the sole child of
        # Xform1, we can get an attribute from the cube.  The selection must
        # now be empty.
        xformCtxOps = ufe.ContextOps.contextOps(xformItem)
        cmd = xformCtxOps.doOpCmd(['Variant Sets', 'modelingVariant', 'cube'])
        ufeCmd.execute(cmd)

        cubePath = ufe.PathString.path('%s,/Xform1/Cube' % proxyShape)
        cubeItem = ufe.Hierarchy.createItem(cubePath)

        xformChildren = xformHier.children()
        self.assertEqual(len(xformChildren), 1)
        self.assertEqual(xformChildren[0].path(), cubePath)
        cubeAttrs = ufe.Attributes.attributes(cubeItem)
        cubeRadius = cubeAttrs.attribute('size')
        self.assertEqual(cubeRadius.get(), 2)

        self.assertTrue(sn.empty())

        # Undo: selection is restored, seletion item is valid.
        cmds.undo()

        self.assertEqual(len(sn), 1)
        sphereItem = sn.front()
        self.assertEqual(sphereItem.path(), spherePath)
        sphereAttrs = ufe.Attributes.attributes(sphereItem)
        sphereRadius = sphereAttrs.attribute('radius')
        self.assertEqual(sphereRadius.get(), 1)
        xformChildren = xformHier.children()
        self.assertEqual(len(xformChildren), 1)
        self.assertEqual(xformChildren[0].path(), spherePath)

        # Redo: selection is cleared.
        cmds.redo()

        self.assertTrue(sn.empty())
        xformChildren = xformHier.children()
        self.assertEqual(len(xformChildren), 1)
        self.assertEqual(xformChildren[0].path(), cubePath)

        # Undo: selection restored to sphere.
        cmds.undo()

        self.assertEqual(len(sn), 1)
        sphereItem = sn.front()
        self.assertEqual(sphereItem.path(), spherePath)

        # Now set the variant outside a Maya command.  Stale scene items must be
        # removed from the selection.
        vset.SetVariantSelection('cube')

        self.assertTrue(sn.empty())
Example #7
0
    def testAddNewPrim(self):
        cmds.file(new=True, force=True)

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

        # Create our UFE notification observer
        ufeObs = TestAddPrimObserver()
        if (os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '2021'):
            ufe.Scene.addObjectDeleteObserver(ufeObs)
            ufe.Scene.addObjectAddObserver(ufeObs)
        else:
            ufe.Scene.addObserver(ufeObs)

        # Create a ContextOps interface for the proxy shape.
        proxyShapePath = ufe.Path(
            [mayaUtils.createUfePathSegment("|world|stage1|stageShape1")])
        proxyShapeItem = ufe.Hierarchy.createItem(proxyShapePath)
        contextOps = ufe.ContextOps.contextOps(proxyShapeItem)

        # Add a new prim.
        cmd = contextOps.doOpCmd(['Add New Prim', 'Xform'])
        self.assertIsNotNone(cmd)
        ufeObs.reset()
        ufeCmd.execute(cmd)

        # Ensure we got the correct UFE notifs.
        self.assertEqual(ufeObs.nbAddNotif(), 1)
        self.assertEqual(ufeObs.nbDeleteNotif(), 0)

        # The proxy shape should now have a single UFE child item.
        proxyShapehier = ufe.Hierarchy.hierarchy(proxyShapeItem)
        self.assertTrue(proxyShapehier.hasChildren())
        self.assertEqual(len(proxyShapehier.children()), 1)

        # Add a new prim to the prim we just added.
        cmds.pickWalk(d='down')

        # Get the scene item from the UFE selection.
        snIter = iter(ufe.GlobalSelection.get())
        xformItem = next(snIter)

        # Create a ContextOps interface for it.
        contextOps = ufe.ContextOps.contextOps(xformItem)

        # Add a new prim.
        cmd = contextOps.doOpCmd(['Add New Prim', 'Xform'])
        self.assertIsNotNone(cmd)
        ufeObs.reset()
        ufeCmd.execute(cmd)

        # Ensure we got the correct UFE notifs.
        self.assertEqual(ufeObs.nbAddNotif(), 1)
        self.assertEqual(ufeObs.nbDeleteNotif(), 0)

        # The xform prim should now have a single UFE child item.
        xformHier = ufe.Hierarchy.hierarchy(xformItem)
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 1)

        # Add another prim
        cmd = contextOps.doOpCmd(['Add New Prim', 'Capsule'])
        self.assertIsNotNone(cmd)
        ufeObs.reset()
        ufeCmd.execute(cmd)

        # Ensure we got the correct UFE notifs.
        self.assertEqual(ufeObs.nbAddNotif(), 1)
        self.assertEqual(ufeObs.nbDeleteNotif(), 0)

        # The xform prim should now have two UFE child items.
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 2)

        # Undo will remove the new prim, meaning one less child.
        ufeObs.reset()
        cmds.undo()
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 1)

        # Ensure we got the correct UFE notifs.
        self.assertEqual(ufeObs.nbAddNotif(), 0)
        self.assertEqual(ufeObs.nbDeleteNotif(), 1)

        # Undo again will remove the first added prim, meaning no children.
        cmds.undo()
        self.assertFalse(xformHier.hasChildren())

        # Ensure we got the correct UFE notifs.
        self.assertEqual(ufeObs.nbAddNotif(), 0)
        self.assertEqual(ufeObs.nbDeleteNotif(), 2)

        cmds.redo()
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 1)

        # Ensure we got the correct UFE notifs.
        self.assertEqual(ufeObs.nbAddNotif(), 1)
        self.assertEqual(ufeObs.nbDeleteNotif(), 2)

        cmds.redo()
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 2)

        # Ensure we got the correct UFE notifs.
        self.assertEqual(ufeObs.nbAddNotif(), 2)
        self.assertEqual(ufeObs.nbDeleteNotif(), 2)
Example #8
0
 def executeContextCmd(ufeItem, subCmd):
     '''Execute a context-menu command, supports among other things Load and Unload.'''
     contextOps = ufe.ContextOps.contextOps(ufeItem)
     cmd = contextOps.doOpCmd([subCmd])
     self.assertIsNotNone(cmd)
     ufeCmd.execute(cmd)
Example #9
0
    def testUndoRedo(self):
        self._StartTest('capsule')

        mayaUtils.loadPlugin("ufeSupport")

        cmds.move(3, -3, 3, 'persp')
        cmds.rotate(60, 0, 45, 'persp')

        # modify the capsule's height, then undo and redo that operation and
        # make sure the viewport updates as expected.
        mayaPathSegment = mayaUtils.createUfePathSegment('|stage|stageShape')
        capsuleUsdPathSegment = usdUtils.createUfePathSegment('/Capsule1')
        capsulePath = ufe.Path([mayaPathSegment, capsuleUsdPathSegment])
        capsuleItem = ufe.Hierarchy.createItem(capsulePath)
        capsuleAttrs = ufe.Attributes.attributes(capsuleItem)
        heightAttr = capsuleAttrs.attribute('height')

        # get the undo queue into a clean state with nothing on the queue
        # and no open chunks

        # disable and flush the undo queue
        cmds.undoInfo(state=False)

        # the undo queue could still have some open chunks which were in the
        # process of being created when I turned the undo queue off. For example,
        # this test gets run from the mel "python" command (see test.cmake), and
        # that chunk is currently open.
        # If I try to query the current chunk string to see if something IS open,
        # it is always the command I used to try to query the current chunk name!
        # Experimentally, I found have that there are typically two open chunks.
        # So just close two chunks.
        cmds.undoInfo(closeChunk=True)
        cmds.undoInfo(closeChunk=True)
        # flush those truncated chunks if they are on the undo queue. They shouldn't
        # be, because I already disabled the undo queue, but I am paranoid.
        cmds.flushUndo()

        # Now run the actual test I want to run. Enable the undo queue for each command
        # that I want on the queue, and disable the undo queue again, without flushing,
        # immediately after.

        cmds.undoInfo(stateWithoutFlush=True)
        ufeCmd.execute(heightAttr.setCmd(3))
        cmds.undoInfo(stateWithoutFlush=False)
        
        self.assertSnapshotClose('%s_set_height.png' % self._testName)
        
        cmds.undoInfo(stateWithoutFlush=True)
        cmds.undo()
        cmds.undoInfo(stateWithoutFlush=False)
        
        self.assertSnapshotClose('%s_undo_set_height.png' % self._testName)
        
        cmds.undoInfo(stateWithoutFlush=True)
        cmds.redo()
        cmds.undoInfo(stateWithoutFlush=False)
        
        self.assertSnapshotClose('%s_redo_set_height.png' % self._testName)
        
        # Now the test is over, turn the undo queue back on incase this Maya session
        # gets re-used for more tests.
        cmds.undoInfo(stateWithoutFlush=True)
Example #10
0
    def testObservation(self):
        '''Test Attributes observation interface.

        Test both global attribute observation and per-node attribute
        observation.
        '''

        # Create three observers, one for global attribute observation, and two
        # on different UFE items.
        proxyShapePathSegment = mayaUtils.createUfePathSegment(
            "|world|transform1|proxyShape1")
        path = ufe.Path([
            proxyShapePathSegment,
            usdUtils.createUfePathSegment('/Room_set/Props/Ball_34')
        ])
        ball34 = ufe.Hierarchy.createItem(path)
        path = ufe.Path([
            proxyShapePathSegment,
            usdUtils.createUfePathSegment('/Room_set/Props/Ball_35')
        ])
        ball35 = ufe.Hierarchy.createItem(path)

        (ball34Obs, ball35Obs, globalObs) = [TestObserver() for i in range(3)]

        # Maya registers a single global observer on startup.
        self.assertEqual(ufe.Attributes.nbObservers(), 1)

        # No item-specific observers.
        self.assertFalse(ufe.Attributes.hasObservers(ball34.path()))
        self.assertFalse(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 0)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 0)
        self.assertFalse(ufe.Attributes.hasObserver(ball34, ball34Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball35, ball35Obs))

        # No notifications yet.
        self.assertEqual(ball34Obs.notifications, 0)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 0)

        # Add a global observer.
        ufe.Attributes.addObserver(globalObs)

        self.assertEqual(ufe.Attributes.nbObservers(), 2)
        self.assertFalse(ufe.Attributes.hasObservers(ball34.path()))
        self.assertFalse(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 0)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 0)
        self.assertFalse(ufe.Attributes.hasObserver(ball34, ball34Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball35, ball35Obs))

        # Add item-specific observers.
        ufe.Attributes.addObserver(ball34, ball34Obs)

        self.assertEqual(ufe.Attributes.nbObservers(), 2)
        self.assertTrue(ufe.Attributes.hasObservers(ball34.path()))
        self.assertFalse(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 1)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 0)
        self.assertTrue(ufe.Attributes.hasObserver(ball34, ball34Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball34, ball35Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball35, ball35Obs))

        ufe.Attributes.addObserver(ball35, ball35Obs)

        self.assertTrue(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 1)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 1)
        self.assertTrue(ufe.Attributes.hasObserver(ball35, ball35Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball35, ball34Obs))

        # Make a change to ball34, global and ball34 observers change.
        ball34Attrs = ufe.Attributes.attributes(ball34)
        ball34XlateAttr = ball34Attrs.attribute('xformOp:translate')

        self.assertEqual(ball34Obs.notifications, 0)

        ufeCmd.execute(ball34XlateAttr.setCmd(ufe.Vector3d(1, 2, 3)))

        self.assertEqual(ball34Obs.notifications, 1)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 1)

        # Undo, redo
        cmds.undo()

        self.assertEqual(ball34Obs.notifications, 2)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 2)

        cmds.redo()

        self.assertEqual(ball34Obs.notifications, 3)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 3)

        # Make a change to ball35, global and ball35 observers change.
        ball35Attrs = ufe.Attributes.attributes(ball35)
        ball35XlateAttr = ball35Attrs.attribute('xformOp:translate')

        ufeCmd.execute(ball35XlateAttr.setCmd(ufe.Vector3d(1, 2, 3)))

        self.assertEqual(ball34Obs.notifications, 3)
        self.assertEqual(ball35Obs.notifications, 1)
        self.assertEqual(globalObs.notifications, 4)

        # Undo, redo
        cmds.undo()

        self.assertEqual(ball34Obs.notifications, 3)
        self.assertEqual(ball35Obs.notifications, 2)
        self.assertEqual(globalObs.notifications, 5)

        cmds.redo()

        self.assertEqual(ball34Obs.notifications, 3)
        self.assertEqual(ball35Obs.notifications, 3)
        self.assertEqual(globalObs.notifications, 6)

        # Test removeObserver.
        ufe.Attributes.removeObserver(ball34, ball34Obs)

        self.assertFalse(ufe.Attributes.hasObservers(ball34.path()))
        self.assertTrue(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 0)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 1)
        self.assertFalse(ufe.Attributes.hasObserver(ball34, ball34Obs))

        ufeCmd.execute(ball34XlateAttr.setCmd(ufe.Vector3d(4, 5, 6)))

        self.assertEqual(ball34Obs.notifications, 3)
        self.assertEqual(ball35Obs.notifications, 3)
        self.assertEqual(globalObs.notifications, 7)

        ufe.Attributes.removeObserver(globalObs)

        self.assertEqual(ufe.Attributes.nbObservers(), 1)

        ufeCmd.execute(ball34XlateAttr.setCmd(ufe.Vector3d(7, 8, 9)))

        self.assertEqual(ball34Obs.notifications, 3)
        self.assertEqual(ball35Obs.notifications, 3)
        self.assertEqual(globalObs.notifications, 7)
Example #11
0
    def testLoadAndUnload(self):
        '''
        Tests the working set management contextOps "Load", "Load with
        Descendants", and "Unload".
        '''
        proxyShapePathSegment = mayaUtils.createUfePathSegment(
            '|transform1|proxyShape1')

        propsPath = ufe.Path([
            proxyShapePathSegment,
            usdUtils.createUfePathSegment('/Room_set/Props')
        ])
        propsItem = ufe.Hierarchy.createItem(propsPath)
        ball1Path = ufe.Path([
            proxyShapePathSegment,
            usdUtils.createUfePathSegment('/Room_set/Props/Ball_1')
        ])
        ball1Item = ufe.Hierarchy.createItem(ball1Path)
        ball15Path = ufe.Path([
            proxyShapePathSegment,
            usdUtils.createUfePathSegment('/Room_set/Props/Ball_15')
        ])
        ball15Item = ufe.Hierarchy.createItem(ball15Path)

        def _validateLoadAndUnloadItems(hierItem, itemStrings):
            ALL_ITEM_STRINGS = set(['Load', 'Load with Descendants', 'Unload'])

            expectedItemStrings = set(itemStrings or [])
            expectedAbsentItemStrings = ALL_ITEM_STRINGS - expectedItemStrings

            contextOps = ufe.ContextOps.contextOps(hierItem)
            contextItems = contextOps.getItems([])
            contextItemStrings = [c.item for c in contextItems]

            for itemString in expectedItemStrings:
                self.assertIn(itemString, contextItemStrings)

            for itemString in expectedAbsentItemStrings:
                self.assertNotIn(itemString, contextItemStrings)

        # The stage is fully loaded, so all items should have "Unload" items.
        _validateLoadAndUnloadItems(propsItem, ['Unload'])
        _validateLoadAndUnloadItems(ball1Item, ['Unload'])
        _validateLoadAndUnloadItems(ball15Item, ['Unload'])

        # The mesh prim path under each Ball asset prim has nothing loadable at
        # or below it, so it should not have any load or unload items.
        ball15meshPath = ufe.Path([
            proxyShapePathSegment,
            usdUtils.createUfePathSegment('/Room_set/Props/Ball_15/mesh')
        ])
        ball15meshItem = ufe.Hierarchy.createItem(ball15meshPath)
        _validateLoadAndUnloadItems(ball15meshItem, [])

        # Unload Ball_1.
        contextOps = ufe.ContextOps.contextOps(ball1Item)
        cmd = contextOps.doOpCmd(['Unload'])
        self.assertIsNotNone(cmd)
        ufeCmd.execute(cmd)

        # Only Ball_1 should have been unloaded, and since it has a payload, it
        # should now have "Load" and "Load with Descendants" context items.
        # "Props" will now also have "Load with Descendants" because something
        # loadable below it is unloaded.
        _validateLoadAndUnloadItems(propsItem,
                                    ['Load with Descendants', 'Unload'])
        _validateLoadAndUnloadItems(ball1Item,
                                    ['Load', 'Load with Descendants'])
        _validateLoadAndUnloadItems(ball15Item, ['Unload'])

        cmds.undo()

        _validateLoadAndUnloadItems(propsItem, ['Unload'])
        _validateLoadAndUnloadItems(ball1Item, ['Unload'])
        _validateLoadAndUnloadItems(ball15Item, ['Unload'])

        # Unload Props.
        contextOps = ufe.ContextOps.contextOps(propsItem)
        cmd = contextOps.doOpCmd(['Unload'])
        self.assertIsNotNone(cmd)
        ufeCmd.execute(cmd)

        # The "Props" prim does not have a payload of its own, so it should
        # only have the "Load with Descendants" item. The Ball assets will also
        # have been unloaded.
        _validateLoadAndUnloadItems(propsItem, ['Load with Descendants'])
        _validateLoadAndUnloadItems(ball1Item,
                                    ['Load', 'Load with Descendants'])
        _validateLoadAndUnloadItems(ball15Item,
                                    ['Load', 'Load with Descendants'])

        cmds.undo()

        _validateLoadAndUnloadItems(propsItem, ['Unload'])
        _validateLoadAndUnloadItems(ball1Item, ['Unload'])
        _validateLoadAndUnloadItems(ball15Item, ['Unload'])

        cmds.redo()

        _validateLoadAndUnloadItems(propsItem, ['Load with Descendants'])
        _validateLoadAndUnloadItems(ball1Item,
                                    ['Load', 'Load with Descendants'])
        _validateLoadAndUnloadItems(ball15Item,
                                    ['Load', 'Load with Descendants'])

        # Load Props.
        contextOps = ufe.ContextOps.contextOps(propsItem)
        cmd = contextOps.doOpCmd(['Load with Descendants'])
        self.assertIsNotNone(cmd)
        ufeCmd.execute(cmd)

        _validateLoadAndUnloadItems(propsItem, ['Unload'])
        _validateLoadAndUnloadItems(ball1Item, ['Unload'])
        _validateLoadAndUnloadItems(ball15Item, ['Unload'])

        cmds.undo()

        _validateLoadAndUnloadItems(propsItem, ['Load with Descendants'])
        _validateLoadAndUnloadItems(ball1Item,
                                    ['Load', 'Load with Descendants'])
        _validateLoadAndUnloadItems(ball15Item,
                                    ['Load', 'Load with Descendants'])
Example #12
0
    def testDoOp(self):

        # Change visibility, undo / redo.
        cmd = self.contextOps.doOpCmd(['Toggle Visibility'])
        self.assertIsNotNone(cmd)

        attrs = ufe.Attributes.attributes(self.ball35Item)
        self.assertIsNotNone(attrs)
        visibility = attrs.attribute(UsdGeom.Tokens.visibility)
        self.assertIsNotNone(visibility)

        # Initially, Ball_35 has inherited visibility.
        self.assertEqual(visibility.get(), UsdGeom.Tokens.inherited)

        ufeCmd.execute(cmd)

        self.assertEqual(visibility.get(), UsdGeom.Tokens.invisible)

        cmds.undo()

        self.assertEqual(visibility.get(), UsdGeom.Tokens.inherited)

        cmds.redo()

        self.assertEqual(visibility.get(), UsdGeom.Tokens.invisible)

        cmds.undo()

        # Active / Deactivate Prim
        cmd = self.contextOps.doOpCmd(['Toggle Active State'])
        self.assertIsNotNone(cmd)

        # Initially, Ball_35 should be active.
        self.assertTrue(self.ball35Prim.IsActive())

        ufeCmd.execute(cmd)
        self.assertFalse(self.ball35Prim.IsActive())

        cmds.undo()
        self.assertTrue(self.ball35Prim.IsActive())

        cmds.redo()
        self.assertFalse(self.ball35Prim.IsActive())

        # Mark / Unmark Prim as Instanceable
        cmd = self.contextOps.doOpCmd(['Toggle Instanceable State'])
        self.assertIsNotNone(cmd)

        # Initially, Ball_35 should be not instanceable.
        self.assertFalse(self.ball35Prim.IsInstanceable())

        ufeCmd.execute(cmd)
        self.assertTrue(self.ball35Prim.IsInstanceable())

        cmds.undo()
        self.assertFalse(self.ball35Prim.IsInstanceable())

        cmds.redo()
        self.assertTrue(self.ball35Prim.IsInstanceable())

        # Change variant in variant set.
        def shadingVariant():
            contextItems = self.contextOps.getItems(
                ['Variant Sets', 'shadingVariant'])

            for c in contextItems:
                if c.checked:
                    return c.item

        self.assertEqual(shadingVariant(), 'Ball_8')

        cmd = self.contextOps.doOpCmd(
            ['Variant Sets', 'shadingVariant', 'Cue'])
        self.assertIsNotNone(cmd)

        ufeCmd.execute(cmd)

        self.assertEqual(shadingVariant(), 'Cue')

        cmds.undo()

        self.assertEqual(shadingVariant(), 'Ball_8')

        cmds.redo()

        self.assertEqual(shadingVariant(), 'Cue')

        cmds.undo()
    def testAddNewPrim(self):
        # Create a ContextOps interface for the proxy shape.
        proxyShapePath = ufe.Path(
            [mayaUtils.createUfePathSegment("|world|stage1|stageShape1")])
        proxyShapeItem = ufe.Hierarchy.createItem(proxyShapePath)
        contextOps = ufe.ContextOps.contextOps(proxyShapeItem)

        # Add a new prim.
        cmd = contextOps.doOpCmd(['Add New Prim', 'Xform'])
        self.assertIsNotNone(cmd)
        ufeCmd.execute(cmd)

        # The proxy shape should now have a single UFE child item.
        proxyShapehier = ufe.Hierarchy.hierarchy(proxyShapeItem)
        self.assertTrue(proxyShapehier.hasChildren())
        self.assertEqual(len(proxyShapehier.children()), 1)

        # Add a new prim to the prim we just added.
        cmds.pickWalk(d='down')

        # Get the scene item from the UFE selection.
        snIter = iter(ufe.GlobalSelection.get())
        xformItem = next(snIter)

        # Create a ContextOps interface for it.
        contextOps = ufe.ContextOps.contextOps(xformItem)

        # Add a new prim.
        cmd = contextOps.doOpCmd(['Add New Prim', 'Xform'])
        self.assertIsNotNone(cmd)
        ufeCmd.execute(cmd)

        # The xform prim should now have a single UFE child item.
        xformHier = ufe.Hierarchy.hierarchy(xformItem)
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 1)

        # Add another prim
        cmd = contextOps.doOpCmd(['Add New Prim', 'Capsule'])
        self.assertIsNotNone(cmd)
        ufeCmd.execute(cmd)

        # The xform prim should now have two UFE child items.
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 2)

        # Undo will remove the new prim, meaning one less child.
        cmds.undo()
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 1)

        # Undo again will remove the first added prim, meaning no children.
        cmds.undo()
        self.assertFalse(xformHier.hasChildren())

        cmds.redo()
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 1)

        cmds.redo()
        self.assertTrue(xformHier.hasChildren())
        self.assertEqual(len(xformHier.children()), 2)
Example #14
0
    def testObservation(self):
        '''
        Test Attributes observation interface.

        Test both global attribute observation and per-node attribute
        observation.
        '''

        # Start we a clean scene so we can get a consistent number of notifications
        cmds.file(new=True, force=True)
        mayaUtils.openTopLayerScene()

        # Create three observers, one for global attribute observation, and two
        # on different UFE items.
        proxyShapePathSegment = mayaUtils.createUfePathSegment(
            "|transform1|proxyShape1")
        path = ufe.Path([
            proxyShapePathSegment,
            usdUtils.createUfePathSegment('/Room_set/Props/Ball_34')
        ])
        ball34 = ufe.Hierarchy.createItem(path)
        path = ufe.Path([
            proxyShapePathSegment,
            usdUtils.createUfePathSegment('/Room_set/Props/Ball_35')
        ])
        ball35 = ufe.Hierarchy.createItem(path)

        (ball34Obs, ball35Obs, globalObs) = [TestObserver() for i in range(3)]

        # Maya registers a single global observer on startup.
        self.assertEqual(ufe.Attributes.nbObservers(), 1)

        # No item-specific observers.
        self.assertFalse(ufe.Attributes.hasObservers(ball34.path()))
        self.assertFalse(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 0)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 0)
        self.assertFalse(ufe.Attributes.hasObserver(ball34, ball34Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball35, ball35Obs))

        # No notifications yet.
        self.assertEqual(ball34Obs.notifications, 0)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 0)

        # Add a global observer.
        ufe.Attributes.addObserver(globalObs)

        self.assertEqual(ufe.Attributes.nbObservers(), 2)
        self.assertFalse(ufe.Attributes.hasObservers(ball34.path()))
        self.assertFalse(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 0)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 0)
        self.assertFalse(ufe.Attributes.hasObserver(ball34, ball34Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball35, ball35Obs))

        # Add item-specific observers.
        ufe.Attributes.addObserver(ball34, ball34Obs)

        self.assertEqual(ufe.Attributes.nbObservers(), 2)
        self.assertTrue(ufe.Attributes.hasObservers(ball34.path()))
        self.assertFalse(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 1)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 0)
        self.assertTrue(ufe.Attributes.hasObserver(ball34, ball34Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball34, ball35Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball35, ball35Obs))

        ufe.Attributes.addObserver(ball35, ball35Obs)

        self.assertTrue(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 1)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 1)
        self.assertTrue(ufe.Attributes.hasObserver(ball35, ball35Obs))
        self.assertFalse(ufe.Attributes.hasObserver(ball35, ball34Obs))

        # Make a change to ball34, global and ball34 observers change.
        ball34Attrs = ufe.Attributes.attributes(ball34)
        ball34XlateAttr = ball34Attrs.attribute('xformOp:translate')

        self.assertEqual(ball34Obs.notifications, 0)

        # The first modification adds a new spec to ball_34 & its ancestors
        # "Props" and "Room_set". Ufe should be filtering out those notifications
        # so the global observer should still only see one notification.
        ufeCmd.execute(ball34XlateAttr.setCmd(ufe.Vector3d(4, 4, 15)))
        self.assertEqual(ball34Obs.notifications, 1)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 1)

        # The second modification only sends one USD notification for "xformOps:translate"
        # because all the spec's already exist. Ufe should also see one notification.
        ufeCmd.execute(ball34XlateAttr.setCmd(ufe.Vector3d(4, 4, 20)))
        self.assertEqual(ball34Obs.notifications, 2)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 2)

        # Undo, redo
        cmds.undo()
        self.assertEqual(ball34Obs.notifications, 3)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 3)

        cmds.redo()
        self.assertEqual(ball34Obs.notifications, 4)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 4)

        # get ready to undo the first modification
        cmds.undo()
        self.assertEqual(ball34Obs.notifications, 5)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 5)

        # Undo-ing the modification which created the USD specs is a little
        # different in USD, but from Ufe we should just still see one notification.
        cmds.undo()
        self.assertEqual(ball34Obs.notifications, 6)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 6)

        cmds.redo()
        self.assertEqual(ball34Obs.notifications, 7)
        self.assertEqual(ball35Obs.notifications, 0)
        self.assertEqual(globalObs.notifications, 7)

        # Make a change to ball35, global and ball35 observers change.
        ball35Attrs = ufe.Attributes.attributes(ball35)
        ball35XlateAttr = ball35Attrs.attribute('xformOp:translate')

        # "xformOp:translate"
        ufeCmd.execute(ball35XlateAttr.setCmd(ufe.Vector3d(4, 8, 15)))
        self.assertEqual(ball34Obs.notifications, 7)
        self.assertEqual(ball35Obs.notifications, 1)
        self.assertEqual(globalObs.notifications, 8)

        # Undo, redo
        cmds.undo()
        self.assertEqual(ball34Obs.notifications, 7)
        self.assertEqual(ball35Obs.notifications, 2)
        self.assertEqual(globalObs.notifications, 9)

        cmds.redo()
        self.assertEqual(ball34Obs.notifications, 7)
        self.assertEqual(ball35Obs.notifications, 3)
        self.assertEqual(globalObs.notifications, 10)

        # Test removeObserver.
        ufe.Attributes.removeObserver(ball34, ball34Obs)

        self.assertFalse(ufe.Attributes.hasObservers(ball34.path()))
        self.assertTrue(ufe.Attributes.hasObservers(ball35.path()))
        self.assertEqual(ufe.Attributes.nbObservers(ball34), 0)
        self.assertEqual(ufe.Attributes.nbObservers(ball35), 1)
        self.assertFalse(ufe.Attributes.hasObserver(ball34, ball34Obs))

        ufeCmd.execute(ball34XlateAttr.setCmd(ufe.Vector3d(4, 4, 25)))

        self.assertEqual(ball34Obs.notifications, 7)
        self.assertEqual(ball35Obs.notifications, 3)
        self.assertEqual(globalObs.notifications, 11)

        ufe.Attributes.removeObserver(globalObs)

        self.assertEqual(ufe.Attributes.nbObservers(), 1)

        ufeCmd.execute(ball34XlateAttr.setCmd(ufe.Vector3d(7, 8, 9)))

        self.assertEqual(ball34Obs.notifications, 7)
        self.assertEqual(ball35Obs.notifications, 3)
        self.assertEqual(globalObs.notifications, 11)