def testMuteLayerImpl(addLayerFunc):
            def checkMuted(layer, stage):
                # Make sure the layer is muted inside the stage.
                self.assertTrue(stage.IsLayerMuted(layer.identifier))
                self.assertTrue(layer.identifier in stage.GetMutedLayers())
                # Make sure the stage does not used the muted layer
                self.assertFalse(layer in stage.GetLayerStack(False))
                self.assertFalse(layer in stage.GetUsedLayers(False))

            def checkUnMuted(layer, stage):
                self.assertFalse(stage.IsLayerMuted(layer.identifier))
                self.assertFalse(layer.identifier in stage.GetMutedLayers())
                self.assertTrue(layer in stage.GetLayerStack(False))
                self.assertTrue(layer in stage.GetUsedLayers(False))

            shapePath, stage = getCleanMayaStage()
            rootLayer = stage.GetRootLayer()

            layer = addLayerFunc(rootLayer)

            checkUnMuted(layer, stage)

            # Mute the layer
            cmds.mayaUsdLayerEditor(layer.identifier,
                                    edit=True,
                                    muteLayer=(True, shapePath))
            checkMuted(layer, stage)

            # undo mute
            cmds.undo()
            checkUnMuted(layer, stage)

            # redo mute
            cmds.redo()
            checkMuted(layer, stage)
    def _selectionTest(self, scene, objectA, objectB, proxyDagPath,
                       displayMode):

        globalSelection = ufe.GlobalSelection.get()
        globalSelection.clear()
        self.assertSnapshotClose('%sunselected_%s.png' % (scene, displayMode))

        # Select cube
        cmds.select(objectA)
        self.assertSnapshotClose('%sobjectA_%s.png' % (scene, displayMode))

        # Select cylinder
        cmds.select(objectB, add=True)
        self.assertSnapshotClose('%sobjectA_and_objectB_%s.png' %
                                 (scene, displayMode))

        # Undo, Redo
        cmds.undo()  # Undo remove capsule from isolate select
        self.assertSnapshotClose('%sundoObjectB_%s.png' % (scene, displayMode))
        cmds.redo()  # Redo remove capsule from isolate select
        self.assertSnapshotClose('%sredoObjectB_%s.png' % (scene, displayMode))

        # Proxy
        cmds.select(proxyDagPath)
        self.assertSnapshotClose('%sgatewayNode_%s.png' % (scene, displayMode))

        cmds.select(clear=True)
        self.assertSnapshotClose('%sclear_%s.png' % (scene, displayMode))
示例#3
0
    def test_docmd(self):
        r = [0, False]
        def do():
            r[0] += 1
        def undo():
            r[0] -= 1
            r[1] = False
        def redo():
            r[0] += 1
            r[1] = True
        self.assertSuccessful(docmd, do, undo)
        self.assertEqual(r[0], 1)
        cmds.undo()
        self.assertEqual(r[0], 0)
        cmds.redo()
        self.assertEqual(r[0], 1)
        cmds.undo()
        self.assertEqual(r[0], 0)

        self.assertSuccessful(docmd, do, undo, redo)
        self.assertEqual(r[0], 1)
        cmds.undo()
        self.assertEqual(r[0], 0)
        cmds.redo()
        self.assertEqual(r[0], 1)
        self.assertTrue(r[1])
        cmds.undo()
        self.assertEqual(r[0], 0)
        self.assertFalse(r[1])
示例#4
0
    def redoLast(self):
        if not self.redoStack:
            return
        result = None
        command = self.redoStack[-1]
        if command is None:
            return result

        exc_tb = None
        exc_type = None
        exc_value = None
        try:
            command.stats = base.CommandStats(command)
            cmds.redo()
        except errors.UserCancel:
            command.stats.finish(None)
            return
        except Exception:
            exc_type, exc_value, exc_tb = sys.exc_info()
            traceback.print_exception(exc_type, exc_value, exc_tb)
            raise
        finally:
            tb = None
            command = self.redoStack.pop()
            if exc_type and exc_value and exc_tb:
                tb = traceback.format_exception(exc_type, exc_value, exc_tb)
            elif command.isUndoable:
                self.undoStack.append(command)
            command.stats.finish(tb)

        return result
 def test_access_objectDeletedUndoRedo(self):
     node = MayaObject(MayaTest.SCENE['transform_1'])
     node.MObject
     node.MObjectHandle
     attr = MayaObject(MayaTest.SCENE['transform_1_attr_1'])
     attr.MObject
     attr.MObjectHandle
     mc.delete(MayaTest.SCENE['transform_1'])
     with self.assertRaises(InvalidMayaObjectError):
         node.MObject
     with self.assertRaises(InvalidMayaObjectError):
         node.MObjectHandle
     with self.assertRaises(InvalidMayaObjectError):
         attr.MObject
     with self.assertRaises(InvalidMayaObjectError):
         attr.MObjectHandle
     mc.undo()
     node.MObject
     node.MObjectHandle
     attr.MObject
     attr.MObjectHandle
     mc.redo()
     with self.assertRaises(InvalidMayaObjectError):
         node.MObject
     with self.assertRaises(InvalidMayaObjectError):
         node.MObjectHandle
     with self.assertRaises(InvalidMayaObjectError):
         attr.MObject
     with self.assertRaises(InvalidMayaObjectError):
         attr.MObjectHandle
     mc.undo()
示例#6
0
        def measurePlugConnection(msg, func, callNumberList):
            """Call func of named operation msg number of times as in callNumberList"""
            for numcons in callNumberList:
                undoObj = undo.StartUndo()

                starttime = time.time()
                for i in xrange(numcons):
                    func(i)
                elapsed = time.time() - starttime

                print >> sys.stderr, "%i %s in %f s ( %f / s )" % (
                    numcons, msg, elapsed, numcons / elapsed)

                del (undoObj)

                starttime = time.time()
                cmds.undo()
                undoelapsed = time.time() - starttime

                starttime = time.time()
                cmds.redo()
                redoelapsed = time.time() - starttime

                print >> sys.stderr, "UNDO / REDO Time = %f / %f ( %f * faster than initial creation )" % (
                    undoelapsed, redoelapsed,
                    elapsed / max(redoelapsed, 0.001))
示例#7
0
 def redoIt():
     """
     See docstring for undoIt() above. This is equivalent except for redoing
       instead of undoing.
     :return: `None`
     """
     m_cmds.redo()
    def testUndoRedo(self):
        """Tests that adaptors work with undo/redo."""
        cmds.file(new=True, force=True)
        cmds.group(name="group1", empty=True)
        adaptor = UsdMaya.Adaptor("group1")
        self.assertEqual(adaptor.GetAppliedSchemas(), [])

        # Do a single operation, then undo, then redo.
        adaptor.ApplySchema(UsdGeom.ModelAPI)
        self.assertEqual(adaptor.GetAppliedSchemas(), ["GeomModelAPI"])
        cmds.undo()
        self.assertEqual(adaptor.GetAppliedSchemas(), [])
        cmds.redo()
        self.assertEqual(adaptor.GetAppliedSchemas(), ["GeomModelAPI"])

        # Do a compound operation, then undo, then redo.
        cmds.undoInfo(openChunk=True)
        adaptor.ApplySchema(UsdGeom.MotionAPI).CreateAttribute(
                UsdGeom.Tokens.motionVelocityScale).Set(0.42)
        self.assertEqual(adaptor.GetAppliedSchemas(),
                ["GeomModelAPI", "MotionAPI"])
        self.assertAlmostEqual(adaptor.GetSchema(UsdGeom.MotionAPI).GetAttribute(
                UsdGeom.Tokens.motionVelocityScale).Get(), 0.42)
        cmds.undoInfo(closeChunk=True)
        cmds.undo()
        self.assertEqual(adaptor.GetAppliedSchemas(), ["GeomModelAPI"])
        self.assertFalse(adaptor.GetSchema(UsdGeom.MotionAPI).GetAttribute(
                UsdGeom.Tokens.motionVelocityScale))
        self.assertIsNone(adaptor.GetSchema(UsdGeom.MotionAPI).GetAttribute(
                UsdGeom.Tokens.motionVelocityScale).Get())
        cmds.redo()
        self.assertEqual(adaptor.GetAppliedSchemas(),
                ["GeomModelAPI", "MotionAPI"])
        self.assertAlmostEqual(adaptor.GetSchema(UsdGeom.MotionAPI).GetAttribute(
                UsdGeom.Tokens.motionVelocityScale).Get(), 0.42)
示例#9
0
    def testUnparentUSD(self):
        '''Unparent USD node.'''

        with OpenFileCtx("simpleHierarchy.ma"):
            # Unparent a USD node
            cubePathStr =  '|mayaUsdProxy1|mayaUsdProxyShape1,/pCylinder1/pCube1'
            cubePath = ufe.PathString.path(cubePathStr)
            cylinderItem = ufe.Hierarchy.createItem(ufe.PathString.path(
                '|mayaUsdProxy1|mayaUsdProxyShape1,/pCylinder1'))
            proxyShapeItem = ufe.Hierarchy.createItem(
                ufe.PathString.path('|mayaUsdProxy1|mayaUsdProxyShape1'))
            proxyShape = ufe.Hierarchy.hierarchy(proxyShapeItem)
            cylinder = ufe.Hierarchy.hierarchy(cylinderItem)

            def checkUnparent(done):
                proxyShapeChildren = proxyShape.children()
                cylinderChildren = cylinder.children()
                self.assertEqual(
                    'pCube1' in childrenNames(proxyShapeChildren), done)
                self.assertEqual(
                    'pCube1' in childrenNames(cylinderChildren), not done)

            checkUnparent(done=False)

            cmds.parent(cubePathStr, world=True)
            checkUnparent(done=True)
            
            cmds.undo()
            checkUnparent(done=False)

            cmds.redo()
            checkUnparent(done=True)
示例#10
0
    def testAlreadyChild(self):
        '''Parenting an object to its current parent is a no-op.'''

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

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

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

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

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

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

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

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

            # Undo / redo
            cmds.undo()

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

            cmds.redo()

            children = parent.children()
            self.assertEqual(len(childrenPre)+1, len(children))
            self.assertIn("pSphere1", childrenNames(children))
            self.assertIn("pCylinderShape1", childrenNames(children))
示例#11
0
文件: test_undo.py 项目: kthulhu/mrv
    def test_undoPerformance(self):
        import time
        iterations = 35
        maxdepth = 3
        totalops = 0

        all_elapsed = [list(), list()]

        for undoEnabled in range(2):

            undo = ""
            if not undoEnabled:
                undo = "Undo disabled"

            cmds.undoInfo(st=undoEnabled)

            # decorated !
            starttime = time.time()
            numops = TestUndoPerformance._recurseUndoDeco(
                iterations, 0, maxdepth)
            totalops += numops
            elapsed = time.time() - starttime
            all_elapsed[undoEnabled].append(elapsed)

            print >> sys.stderr, "UNDO: DECORATED %s: %i ops in %f s ( %f / s )" % (
                undo, numops, elapsed, numops / elapsed)

            starttime = time.time()
            numops = TestUndoPerformance._recurseUndo(iterations, 0, maxdepth)
            totalops += numops
            elapsed_deco = elapsed
            elapsed = time.time() - starttime
            all_elapsed[undoEnabled].append(elapsed)

            print >> sys.stderr, "UNDO: MANUAL %s: %i ops in %f s ( %f / s )" % (
                undo, numops, elapsed, numops / elapsed)
            starttime = time.time()

            print >> sys.stderr, "UNDO: DECORATED is %f %% faster than manually implemented functions !" % (
                100 - (elapsed_deco / elapsed) * 100)

            if undoEnabled:
                cmds.undo()
                cmds.undo()
                cmds.redo()
                cmds.redo()
                elapsed = time.time() - starttime

                print >> sys.stderr, "UNDO: CALL TIME: %i operations in %f s ( %f / s )" % (
                    totalops, elapsed, totalops / elapsed)
            #END if undo enabled
        # END for each undo queue state

        ratio = 100.0 - ((all_elapsed[0][0] / all_elapsed[1][0]) * 100)
        difference = all_elapsed[1][1] - all_elapsed[0][1]

        # RATIOS between enabled undo system and without
        print >> sys.stderr, "UNDO: RATIO UNDO QUEUE ON/OFF: %f s (on) vs %f s (off) = %f %% speedup on disabled queue ( difference [s] = %f )" % (
            all_elapsed[1][0], all_elapsed[0][0], ratio, difference)
示例#12
0
    def testDuplicateAsUsdUndoRedo(self):
        '''Duplicate a Maya transform hierarchy to USD and then undo and redo the command.'''

        # Create a hierarchy.  Because group1 is selected upon creation, group2
        # will be its parent.
        group1 = cmds.createNode('transform')
        group2 = cmds.group()
        self.assertEqual(cmds.listRelatives(group1, parent=True)[0], group2)

        cmds.setAttr(group1 + '.translate', 1, 2, 3)
        cmds.setAttr(group2 + '.translate', -4, -5, -6)

        # Create a stage to receive the USD duplicate.
        psPathStr = mayaUsd_createStageWithNewLayer.createStageWithNewLayer()
        
        # Duplicate Maya data as USD data.  As of 17-Nov-2021 no single-segment
        # path handler registered to UFE for Maya path strings, so use absolute
        # path.
        cmds.mayaUsdDuplicate(cmds.ls(group2, long=True)[0], psPathStr)

        def verifyDuplicate():
            # Maya hierarchy should be duplicated in USD.
            usdGroup2PathStr = psPathStr + ',/' + group2
            usdGroup1PathStr = usdGroup2PathStr + '/' + group1
            usdGroup2Path = ufe.PathString.path(usdGroup2PathStr)
            usdGroup1Path = ufe.PathString.path(usdGroup1PathStr)

            # group1 is the child of group2
            usdGroup1 = ufe.Hierarchy.createItem(usdGroup1Path)
            usdGroup2 = ufe.Hierarchy.createItem(usdGroup2Path)
            usdGroup1Hier = ufe.Hierarchy.hierarchy(usdGroup1)
            usdGroup2Hier = ufe.Hierarchy.hierarchy(usdGroup2)
            self.assertEqual(usdGroup2, usdGroup1Hier.parent())
            self.assertEqual(len(usdGroup2Hier.children()), 1)
            self.assertEqual(usdGroup1, usdGroup2Hier.children()[0])

            # Translations have been preserved.
            usdGroup1T3d = ufe.Transform3d.transform3d(usdGroup1)
            usdGroup2T3d = ufe.Transform3d.transform3d(usdGroup2)
            self.assertEqual([1, 2, 3], usdGroup1T3d.translation().vector)
            self.assertEqual([-4, -5, -6], usdGroup2T3d.translation().vector)

        verifyDuplicate()

        cmds.undo()

        def verifyDuplicateIsGone():
            # Maya hierarchy should no longer be duplicated in USD.
            usdGroup2PathStr = psPathStr + ',/' + group2
            usdGroup2Path = ufe.PathString.path(usdGroup2PathStr)
            usdGroup2 = ufe.Hierarchy.createItem(usdGroup2Path)
            self.assertIsNone(usdGroup2)

        verifyDuplicateIsGone()

        cmds.redo()

        verifyDuplicate()
示例#13
0
    def testRename(self):
        '''Rename USD node.'''

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

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

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

        newName = 'Ball_35_Renamed'
        cmds.rename(newName)

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

        self.assertEqual(ball35RenName, newName)

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

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

        cmds.undo()

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

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

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

        cmds.redo()

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

        self.assertIn(ball35RenName, propsChildrenNames)
        self.assertNotIn('Ball_35', propsChildrenNames)
        self.assertEqual(len(propsChildren), len(propsChildrenPre))
示例#14
0
    def testCenterPivotUndo(self):

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

        import mayaUsd_createStageWithNewLayer
        mayaUsd_createStageWithNewLayer.createStageWithNewLayer()
        proxyShapePath = ufe.PathString.path('|stage1|stageShape1')
        proxyShapeItem = ufe.Hierarchy.createItem(proxyShapePath)
        proxyShapeContextOps = ufe.ContextOps.contextOps(proxyShapeItem)
        proxyShapeContextOps.doOp(['Add New Prim', 'Capsule'])

        capsulePath = ufe.PathString.path('|stage1|stageShape1,/Capsule1')
        capsuleItem = ufe.Hierarchy.createItem(capsulePath)
        usdT3d = ufe.Transform3d.transform3d(capsuleItem)

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

        # center point is expected to be at [0.0, 0.0, 0.0]
        assertVectorAlmostEqual(self,
                                usdT3d.rotatePivot().vector, [0.0, 0.0, 0.0])
        assertVectorAlmostEqual(self,
                                usdT3d.scalePivot().vector, [0.0, 0.0, 0.0])

        # move the pivot location
        cmds.move(7, 2, 1, r=True, urp=True, usp=True)

        assertVectorAlmostEqual(self,
                                usdT3d.rotatePivot().vector, [7.0, 2.0, 1.0])
        assertVectorAlmostEqual(self,
                                usdT3d.scalePivot().vector, [7.0, 2.0, 1.0])

        # call center pivot command
        cmds.xform(cp=True)

        # center point is expected to be at [0.0, 0.0, 0.0]
        assertVectorAlmostEqual(self,
                                usdT3d.rotatePivot().vector, [0.0, 0.0, 0.0])
        assertVectorAlmostEqual(self,
                                usdT3d.scalePivot().vector, [0.0, 0.0, 0.0])

        # undo
        cmds.undo()

        assertVectorAlmostEqual(self,
                                usdT3d.rotatePivot().vector, [7.0, 2.0, 1.0])
        assertVectorAlmostEqual(self,
                                usdT3d.scalePivot().vector, [7.0, 2.0, 1.0])

        # redo
        cmds.redo()

        assertVectorAlmostEqual(self,
                                usdT3d.rotatePivot().vector, [0.0, 0.0, 0.0])
        assertVectorAlmostEqual(self,
                                usdT3d.scalePivot().vector, [0.0, 0.0, 0.0])
示例#15
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()
示例#16
0
    def testUnparentMultiStage(self):
        '''Unparent USD nodes in more than one stage.'''

        with OpenFileCtx("simpleHierarchy.ma"):
            # An early version of this test imported the same file into the
            # opened file.  Layers are then shared between the stages, because
            # they come from the same USD file, causing changes done below one
            # proxy shape to be seen in the other.  Import from another file.
            filePath = mayaUtils.getTestScene("parentCmd", "simpleSceneUSD_TRS.ma")
            cmds.file(filePath, i=True)

            # Unparent a USD node in each stage.  Unparenting Lambert node is
            # nonsensical, but demonstrates the functionality.
            cubePathStr1 = '|mayaUsdProxy1|mayaUsdProxyShape1,/pCylinder1/pCube1'
            lambertPathStr2 = '|simpleSceneUSD_TRS_mayaUsdProxy1|simpleSceneUSD_TRS_mayaUsdProxyShape1,/initialShadingGroup/initialShadingGroup_lambert'

            cylinderItem1 = ufe.Hierarchy.createItem(ufe.PathString.path(
                '|mayaUsdProxy1|mayaUsdProxyShape1,/pCylinder1'))
            shadingGroupItem2 = ufe.Hierarchy.createItem(
                ufe.PathString.path('|simpleSceneUSD_TRS_mayaUsdProxy1|simpleSceneUSD_TRS_mayaUsdProxyShape1,/initialShadingGroup'))
            proxyShapeItem1 = ufe.Hierarchy.createItem(ufe.PathString.path(
                '|mayaUsdProxy1|mayaUsdProxyShape1'))
            proxyShapeItem2 = ufe.Hierarchy.createItem(ufe.PathString.path(
                '|simpleSceneUSD_TRS_mayaUsdProxy1|simpleSceneUSD_TRS_mayaUsdProxyShape1'))
            cylinder1 = ufe.Hierarchy.hierarchy(cylinderItem1)
            shadingGroup2 = ufe.Hierarchy.hierarchy(shadingGroupItem2)
            proxyShape1 = ufe.Hierarchy.hierarchy(proxyShapeItem1)
            proxyShape2 = ufe.Hierarchy.hierarchy(proxyShapeItem2)

            def checkUnparent(done):
                proxyShape1Children   = proxyShape1.children()
                proxyShape2Children   = proxyShape2.children()
                cylinder1Children     = cylinder1.children()
                shadingGroup2Children = shadingGroup2.children()
                self.assertEqual(
                    'pCube1' in childrenNames(proxyShape1Children), done)
                self.assertEqual(
                    'pCube1' in childrenNames(cylinder1Children), not done)
                self.assertEqual(
                    'initialShadingGroup_lambert' in childrenNames(proxyShape2Children), done)
                self.assertEqual(
                    'initialShadingGroup_lambert' in childrenNames(shadingGroup2Children), not done)

            checkUnparent(done=False)

            # Use relative parenting, else trying to keep absolute world
            # position of Lambert node fails (of course).
            cmds.parent(cubePathStr1, lambertPathStr2, w=True, r=True)
            checkUnparent(done=True)
            
            cmds.undo()
            checkUnparent(done=False)

            cmds.redo()
            checkUnparent(done=True)
示例#17
0
 def test_strNodeDeleted(self):
     for attr_instance in get_scene_attribute_instances(
             maya_attributes=False):
         mc.delete(attr_instance.nodeName)
         self.assertRaises(InvalidMayaObjectError, attr_instance.__str__)
         mc.undo()
         str(attr_instance)
         mc.redo()
         self.assertRaises(InvalidMayaObjectError, attr_instance.__str__)
         mc.undo()
         str(attr_instance)
示例#18
0
 def testUndoLast(self):
     self.assertEquals(len(self.executor.undoStack), 0)
     result = self.executor.execute("test.mayaTestCreateNodeCommand")
     self.assertIsInstance(result, om2.MObject)
     self.assertEquals(len(self.executor.undoStack), 1)
     cmds.undo()
     self.assertEquals(len(self.executor.undoStack), 0)
     self.assertEquals(len(self.executor.redoStack), 1)
     cmds.redo()
     self.assertEquals(len(self.executor.redoStack), 0)
     self.assertEquals(len(self.executor.undoStack), 1)
示例#19
0
    def test_undoPerformance( self ):
        import time
        iterations = 35
        maxdepth = 3
        totalops = 0

        all_elapsed = [list(),list()]

        for undoEnabled in range( 2 ):

            undo = ""
            if not undoEnabled:
                undo = "Undo disabled"

            cmds.undoInfo( st=undoEnabled )

            # decorated !
            starttime = time.time()
            numops = TestUndoPerformance._recurseUndoDeco( iterations, 0, maxdepth )
            totalops += numops
            elapsed = time.time() - starttime
            all_elapsed[undoEnabled].append( elapsed )

            print >> sys.stderr, "UNDO: DECORATED %s: %i ops in %f s ( %f / s )" % ( undo, numops, elapsed, numops / elapsed )


            starttime = time.time()
            numops = TestUndoPerformance._recurseUndo( iterations, 0, maxdepth )
            totalops += numops
            elapsed_deco = elapsed
            elapsed = time.time() - starttime
            all_elapsed[undoEnabled].append( elapsed )

            print >> sys.stderr, "UNDO: MANUAL %s: %i ops in %f s ( %f / s )" % ( undo, numops, elapsed, numops / elapsed )
            starttime = time.time()

            print >> sys.stderr, "UNDO: DECORATED is %f %% faster than manually implemented functions !" % ( 100 - ( elapsed_deco / elapsed ) * 100 )

            if undoEnabled:
                cmds.undo()
                cmds.undo()
                cmds.redo()
                cmds.redo()
                elapsed = time.time() - starttime

                print >> sys.stderr, "UNDO: CALL TIME: %i operations in %f s ( %f / s )" % ( totalops, elapsed, totalops / elapsed )
            #END if undo enabled
        # END for each undo queue state

        ratio = 100.0 - ( ( all_elapsed[0][0] / all_elapsed[1][0] ) * 100 )
        difference = all_elapsed[1][1] - all_elapsed[0][1]

        # RATIOS between enabled undo system and without
        print >> sys.stderr, "UNDO: RATIO UNDO QUEUE ON/OFF: %f s (on) vs %f s (off) = %f %% speedup on disabled queue ( difference [s] = %f )" % (all_elapsed[1][0], all_elapsed[0][0], ratio, difference )
示例#20
0
	def test_dgmod( self ):
		persp = Node( "persp" )
		front = Node( "front" )
		side = Node( "side" )

		# SIMPLE CONNECTION
		################
		# start undo
		uobj = undo.StartUndo( )
		dgmod = undo.DGModifier( )
		assert len( sys._maya_stack ) == 1 

		dgmod.connect( persp.message, front.isHistoricallyInteresting )
		dgmod.doIt( )

		# create undo step
		del( uobj )

		assert len( sys._maya_stack ) == 0 
		cmds.undo()	# undo connection
		# check connection - should be undone
		assert not persp.message.misConnectedTo( front.isHistoricallyInteresting ) 

		cmds.redo()
		# redo it and check connection
		assert persp.message.misConnectedTo( front.isHistoricallyInteresting ) 

		# connect and break existing conenction
		uobj = undo.StartUndo( )
		dgmod = undo.DGModifier( )
		dgmod.disconnect( persp.message, front.isHistoricallyInteresting )
		dgmod.connect( side.message, front.isHistoricallyInteresting )
		dgmod.doIt( )
		del( uobj )

		assert side.message.misConnectedTo( front.isHistoricallyInteresting ) 
		cmds.undo()

		# old connection should be back
		assert persp.message.misConnectedTo( front.isHistoricallyInteresting ) 


		# undo first change
		cmds.undo()

		# EMPTY DOIT
		################
		undo.startUndo( )
		dgmod = undo.DGModifier( )
		dgmod.doIt( )
		undo.endUndo( )

		cmds.undo()
示例#21
0
文件: test_undo.py 项目: kthulhu/mrv
    def test_dgmod(self):
        persp = Node("persp")
        front = Node("front")
        side = Node("side")

        # SIMPLE CONNECTION
        ################
        # start undo
        uobj = undo.StartUndo()
        dgmod = undo.DGModifier()
        assert len(sys._maya_stack) == 1

        dgmod.connect(persp.message, front.isHistoricallyInteresting)
        dgmod.doIt()

        # create undo step
        del (uobj)

        assert len(sys._maya_stack) == 0
        cmds.undo()  # undo connection
        # check connection - should be undone
        assert not persp.message.misConnectedTo(
            front.isHistoricallyInteresting)

        cmds.redo()
        # redo it and check connection
        assert persp.message.misConnectedTo(front.isHistoricallyInteresting)

        # connect and break existing conenction
        uobj = undo.StartUndo()
        dgmod = undo.DGModifier()
        dgmod.disconnect(persp.message, front.isHistoricallyInteresting)
        dgmod.connect(side.message, front.isHistoricallyInteresting)
        dgmod.doIt()
        del (uobj)

        assert side.message.misConnectedTo(front.isHistoricallyInteresting)
        cmds.undo()

        # old connection should be back
        assert persp.message.misConnectedTo(front.isHistoricallyInteresting)

        # undo first change
        cmds.undo()

        # EMPTY DOIT
        ################
        undo.startUndo()
        dgmod = undo.DGModifier()
        dgmod.doIt()
        undo.endUndo()

        cmds.undo()
示例#22
0
    def fforwardMemento(self):
        '''Redo through all items in memento.

        Starting at the bottom of the undo stack, perform redo to bring us to
        the top of the undo stack.  During iteration, we ensure that the current
        state matches the state stored in the memento.
        '''
        # For a memento list of length n, n-1 redo operations sets us current.
        self.assertEqual(self.memento[0], self.snapshotRunTimeUFE())
        # Skip first
        for m in self.memento[1:]:
            cmds.redo()
            self.assertEqual(m, self.snapshotRunTimeUFE())
示例#23
0
 def test_MPlugAccess_nodeDeleted(self):
     attr = Attribute(MayaTest.SCENE['transform_1_attr_1'])
     attr.MPlug
     mc.delete(MayaTest.SCENE['transform_1'])
     with self.assertRaises(InvalidMayaObjectError):
         attr.MPlug
     mc.undo()
     attr.MPlug
     mc.redo()
     with self.assertRaises(InvalidMayaObjectError):
         attr.MPlug
     mc.undo()
     attr.MPlug
示例#24
0
    def testComplexSetAssemblyChangeReps(self):
        """
        This tests that changing representations of a USD reference assembly
        node in Maya that references a complex hierarchy of different types of
        prims works as expected, including undo'ing and redo'ing representation
        changes.
        """
        assemblyNode = self._SetupScene('ComplexSet.usda', '/ComplexSet')

        # No representation has been activated yet, so ensure the assembly node
        # has no children.
        self._ValidateUnloaded(assemblyNode)

        # Change representations to 'Collapsed' and validate.
        cmds.assembly(assemblyNode, edit=True, active='Collapsed')
        self._ValidateCollapsed(assemblyNode)

        # Change representations to 'Cards' and validate.
        cmds.assembly(assemblyNode, edit=True, active='Cards')
        self._ValidateCards(assemblyNode)

        # Change representations to 'Expanded' and validate.
        cmds.assembly(assemblyNode, edit=True, active='Expanded')
        self._ValidateComplexSetExpandedTopLevel(assemblyNode)

        # Change representations to 'Full' and validate.
        cmds.assembly(assemblyNode, edit=True, active='Full')
        self._ValidateComplexSetFullTopLevel(assemblyNode)

        # Undo and the node should be back to Expanded.
        cmds.undo()
        self._ValidateComplexSetExpandedTopLevel(assemblyNode)

        # Undo and the node should be back to Cards.
        cmds.undo()
        self._ValidateCards(assemblyNode)

        # Undo and the node should be back to Collapsed.
        cmds.undo()
        self._ValidateCollapsed(assemblyNode)

        # Undo once more and no representation should be active.
        cmds.undo()
        self._ValidateUnloaded(assemblyNode)

        # Redo and it's back to Collapsed.
        cmds.redo()
        self._ValidateCollapsed(assemblyNode)

        # Redo and it's back to Cards.
        cmds.redo()
        self._ValidateCards(assemblyNode)

        # Redo again and it's back to Expanded.
        cmds.redo()
        self._ValidateComplexSetExpandedTopLevel(assemblyNode)

        # Redo once more and it's back to Full.
        cmds.redo()
        self._ValidateComplexSetFullTopLevel(assemblyNode)
示例#25
0
 def fforwardMemento(self):
     ''' 
         Redo through all items in memento. Make sure that the current
         selection match their respective registered selection in memento.
     '''
     # Test initial
     self.assertEqual(self.memento[0][0], mayaUtils.getMayaSelectionList())
     self.assertEqual(self.memento[0][1],
                      ufeUtils.getUfeGlobalSelectionList())
     # Skip first
     for m in self.memento[1:]:
         cmds.redo()
         self.assertEqual(m[0], mayaUtils.getMayaSelectionList())
         self.assertEqual(m[1], ufeUtils.getUfeGlobalSelectionList())
示例#26
0
文件: test_base.py 项目: kthulhu/mrv
		def assert_values(fgetname, fsetname, loose):
			getter = getattr(p, fgetname)
			v = getter()
			assert isinstance(v, api.MVector)
			
			nv = api.MVector(i+v.x+1.0, i+v.y+2.0, i+v.z+3.0)
			getattr(p, fsetname)(nv)
			
			cmp_val(nv, getter(), loose)
			
			cmds.undo()
			cmp_val(v, getter(), loose)
			cmds.redo()
			cmp_val(nv, getter(), loose)
示例#27
0
 def assert_values(fgetname, fsetname, loose):
     getter = getattr(p, fgetname)
     v = getter()
     assert isinstance(v, api.MVector)
     
     nv = api.MVector(i+v.x+1.0, i+v.y+2.0, i+v.z+3.0)
     getattr(p, fsetname)(nv)
     
     cmp_val(nv, getter(), loose)
     
     cmds.undo()
     cmp_val(v, getter(), loose)
     cmds.redo()
     cmp_val(nv, getter(), loose)
示例#28
0
    def testDiscardEditsUndoRedo(self):
        '''Discard edits on a USD transform then undo and redo.'''

        # Edit as Maya first.
        (ps, xlateOp, usdXlation, aUsdUfePathStr, aUsdUfePath, aUsdItem, _, _,
         _, _, _) = createSimpleXformScene()

        cmds.mayaUsdEditAsMaya(aUsdUfePathStr)

        # Modify the scene.
        aMayaItem = ufe.GlobalSelection.get().front()
        mayaXlation = om.MVector(4, 5, 6)
        (aMayaPath, aMayaPathStr, aFn, mayaMatrix) = \
            setMayaTranslation(aMayaItem, mayaXlation)

        # Verify the scene modifications.
        def verifyScenesModifications():
            self.assertEqual(aFn.translation(om.MSpace.kObject), mayaXlation)
            mayaToUsd = ufe.PathMappingHandler.pathMappingHandler(aMayaItem)
            self.assertEqual(
                ufe.PathString.string(mayaToUsd.fromHost(aMayaPath)),
                ufe.PathString.string(aUsdUfePath))

        verifyScenesModifications()

        # Discard Maya edits.
        cmds.mayaUsdDiscardEdits(aMayaPathStr)

        def verifyDiscard():
            # Original USD translation values are preserved.
            usdMatrix = xlateOp.GetOpTransform(
                mayaUsd.ufe.getTime(aUsdUfePathStr))
            self.assertEqual(usdMatrix.ExtractTranslation(), usdXlation)

            # Maya node is removed.
            with self.assertRaises(RuntimeError):
                om.MSelectionList().add(aMayaPathStr)

        verifyDiscard()

        # undo
        cmds.undo()

        verifyScenesModifications()

        # redo
        cmds.redo()

        verifyDiscard()
示例#29
0
    def _ValidateAllModelRepresentations(self, nodeName):
        """
        Tests all representations of an assembly node that references a
        model (i.e. has no sub-assemblies). This should apply for both a
        standalone model reference node as well as a nested assembly reference
        node that references a model.
        """
        # No representation has been activated yet, so ensure the assembly node
        # has no children.
        self._ValidateUnloaded(nodeName)

        # Change representations to 'Collapsed' and validate.
        cmds.assembly(nodeName, edit=True, active='Collapsed')
        self._ValidateCollapsed(nodeName)

        # Change representations to 'Cards' and validate.
        cmds.assembly(nodeName, edit=True, active='Cards')
        self._ValidateCards(nodeName)

        # Change representations to 'Expanded' and validate.
        cmds.assembly(nodeName, edit=True, active='Expanded')
        self._ValidateModelExpanded(nodeName)

        # Change representations to 'Full' and validate.
        cmds.assembly(nodeName, edit=True, active='Full')
        self._ValidateModelFull(nodeName)

        # Undo and the node should be back to Expanded.
        cmds.undo()
        self._ValidateModelExpanded(nodeName)

        # Undo and the node should be back to Cards.
        cmds.undo()
        self._ValidateCards(nodeName)

        # Undo and the node should be back to Collapsed.
        cmds.undo()
        self._ValidateCollapsed(nodeName)

        # Undo once more and no representation should be active.
        cmds.undo()
        self._ValidateUnloaded(nodeName)

        # Redo and it's back to Collapsed.
        cmds.redo()
        self._ValidateCollapsed(nodeName)

        # Redo and it's back to Cards.
        cmds.redo()
        self._ValidateCards(nodeName)

        # Redo again and it's back to Expanded.
        cmds.redo()
        self._ValidateModelExpanded(nodeName)

        # Redo once more and it's back to Full.
        cmds.redo()
        self._ValidateModelFull(nodeName)
示例#30
0
    def testGroupUndoRedo(self):
        '''Verify grouping after multiple undo/redo.'''
        cmds.file(new=True, force=True)

        # create a stage
        (stage, proxyShapePathStr, proxyShapeItem, contextOp) = createStage()

        # create a sphere generator
        sphereGen = SphereGenerator(3, contextOp, proxyShapePathStr)

        sphere1Path = sphereGen.createSphere()
        sphere1Prim = mayaUsd.ufe.ufePathToPrim(
            ufe.PathString.string(sphere1Path))

        sphere2Path = sphereGen.createSphere()
        sphere2Prim = mayaUsd.ufe.ufePathToPrim(
            ufe.PathString.string(sphere2Path))

        sphere3Path = sphereGen.createSphere()
        sphere3Prim = mayaUsd.ufe.ufePathToPrim(
            ufe.PathString.string(sphere3Path))

        # group Sphere1, Sphere2, and Sphere3
        groupName = cmds.group(ufe.PathString.string(sphere1Path),
                               ufe.PathString.string(sphere2Path),
                               ufe.PathString.string(sphere3Path))

        # verify that groupItem has 3 children
        groupItem = ufe.GlobalSelection.get().front()
        groupHierarchy = ufe.Hierarchy.hierarchy(groupItem)
        self.assertEqual(len(groupHierarchy.children()), 3)

        cmds.undo()

        self.assertEqual([item for item in stage.Traverse()], [
            stage.GetPrimAtPath("/Sphere3"),
            stage.GetPrimAtPath("/Sphere2"),
            stage.GetPrimAtPath("/Sphere1")
        ])

        cmds.redo()

        self.assertEqual([item for item in stage.Traverse()], [
            stage.GetPrimAtPath("/group1"),
            stage.GetPrimAtPath("/group1/Sphere1"),
            stage.GetPrimAtPath("/group1/Sphere2"),
            stage.GetPrimAtPath("/group1/Sphere3")
        ])
示例#31
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)
示例#32
0
    def test_node_creation_undo(self):
        undoWasEnabled = cmds.undoInfo(q=1, state=1)

        cmds.undoInfo(state=0)
        try:
            cmds.file(new=1, f=1)
            self.setBasicCam()

            self.setHdStormRenderer()

            cmds.undoInfo(state=1)
            cmds.undoInfo(openChunk=1)
            try:
                cubeTrans = cmds.polyCube()
                cubeShape = cmds.listRelatives(cubeTrans)[0]
                cubeRprim = self.rprimPath(cubeShape)
                cmds.select(clear=1)
                cmds.refresh()
                self.assertEqual([cubeRprim], self.getIndex())
                self.assertSnapshotClose("instances_1.png")
            finally:
                cmds.undoInfo(closeChunk=1)

            cmds.undo()

            # the playblast command is entered into the undo queue, so we
            # need to disable without flusing the queue, so we can test redo
            cmds.undoInfo(stateWithoutFlush=0)
            try:
                cmds.refresh()
                self.assertEqual([], self.getIndex())
                self.assertSnapshotClose("instances_0.png")
            finally:
                cmds.undoInfo(stateWithoutFlush=1)

            cmds.redo()

            cmds.undoInfo(stateWithoutFlush=0)
            try:
                cmds.refresh()
                self.assertEqual([cubeRprim], self.getIndex())
                self.assertSnapshotClose("instances_1.png")
            finally:
                cmds.undoInfo(stateWithoutFlush=1)

        finally:
            cmds.undoInfo(state=undoWasEnabled)
示例#33
0
文件: test_undo.py 项目: kthulhu/mrv
    def test_dagmod(self):
        undo.startUndo()
        dagmod = undo.DagModifier()
        obj = dagmod.createNode("transform")
        dagmod.renameNode(obj, "thisnewnode")
        dagmod.doIt()

        handle = api.MObjectHandle(obj)
        assert handle.isValid() and handle.isAlive()

        undo.endUndo()

        cmds.undo()
        assert not handle.isValid() and handle.isAlive()

        cmds.redo()
        assert handle.isValid() and handle.isAlive()
示例#34
0
    def test_dagmod(self):
        undo.startUndo()
        dagmod = undo.DagModifier()
        obj = dagmod.createNode("transform")
        dagmod.renameNode(obj, "thisnewnode")
        dagmod.doIt()

        handle = api.MObjectHandle(obj)
        assert handle.isValid() and handle.isAlive()

        undo.endUndo()

        cmds.undo()
        assert not handle.isValid() and handle.isAlive()

        cmds.redo()
        assert handle.isValid() and handle.isAlive()
示例#35
0
    def test_convenienceFunctions(self):
        # SELECTION
        ############
        nt.select("persp")
        persp = nt.selection()[0]
        assert persp == nt.Node("persp") 

        # clear selection
        nt.select()
        assert not nt.selection() 
        
        # undo/redo
        cmds.undo()
        assert len(nt.selection()) == 1
        cmds.redo()
        assert len(nt.selection()) == 0

        # select object and selection list
        nt.select(persp)
        assert len(nt.selection()) == 1 
        nt.select(nt.toSelectionList(nt.selection()))
        assert len(nt.selection()) == 1 

        # select mixed
        nt.select(persp, "front")
        assert len(nt.selection()) == 2 


        # GET BY NAME
        ###############
        persp = nt.findByName("pers*")[0]
        assert persp == nt.Node("persp") 
        
        # filter selection
        ##################
        nt.select("persp", "perspShape")
        assert len(nt.selection(api.MFn.kCamera)) == 1
        assert len(list(nt.iterSelection(api.MFn.kCamera))) == 1
        
        sl = nt.activeSelectionList()
        assert len(sl) and isinstance(sl, api.MSelectionList)
示例#36
0
    def test_keepWorldSpace(self):
        g = nt.createNode("g", "transform")
        t = nt.createNode("t", "transform")
        t.setParent(g)

        mainattrs = ("t","s")
        subattrs = ("x","y","z")

        count = 0.0
        for ma in mainattrs:
            for sa in subattrs:
                getattr(g, ma).mchildByName(ma+sa).msetFloat(count)
                count += 1.0
            # END for each sa
        # END for each ma

        # REPARENT TO WORLD
        ###################
        t = t.reparent(None, keepWorldSpace = 1)

        count = 0.0
        for ma in mainattrs:
            for sa in subattrs:
                value = t.findPlug(ma+sa).asFloat()
                assert value == count 
                count += 1.0
            # END
        # END

        # undo - everything should be back to normal
        cmds.undo()
        self._checkIdentity(t)
        cmds.redo()

        # REPARENT TO PARENT NODE
        ###########################
        t = t.setParent(g, keepWorldSpace = 1)

        self._checkIdentity(t)
    def testNestedAssemblyChangeReps(self):
        """
        This tests that changing representations of a USD reference assembly
        node in Maya that references a hierarchy of assemblies works as
        expected, including undo'ing and redo'ing representation changes.
        """
        assemblyNode = self._SetupScene('OneCube_set.usda', '/set')

        # No representation has been activated yet, so ensure the assembly node
        # has no children.
        self._ValidateUnloaded(assemblyNode)

        # Change representations to 'Collapsed' and validate.
        cmds.assembly(assemblyNode, edit=True, active='Collapsed')
        self._ValidateCollapsed(assemblyNode)

        # Change representations to 'Expanded' and validate.
        cmds.assembly(assemblyNode, edit=True, active='Expanded')
        self._ValidateNestedExpandedTopLevel(assemblyNode)

        # Change representations to 'Full' and validate.
        cmds.assembly(assemblyNode, edit=True, active='Full')
        self._ValidateNestedFullTopLevel(assemblyNode)

        # Undo and the node should be back to Expanded.
        cmds.undo()
        self._ValidateNestedExpandedTopLevel(assemblyNode)

        # Undo and the node should be back to Collapsed.
        cmds.undo()
        self._ValidateCollapsed(assemblyNode)

        # Undo once more and no representation should be active.
        cmds.undo()
        self._ValidateUnloaded(assemblyNode)

        # Redo and it's back to Collapsed.
        cmds.redo()
        self._ValidateCollapsed(assemblyNode)

        # Redo again and it's back to Expanded.
        cmds.redo()
        self._ValidateNestedExpandedTopLevel(assemblyNode)

        # Redo once more and it's back to Full.
        cmds.redo()
        self._ValidateNestedFullTopLevel(assemblyNode)


        # Now test changing representations of the sub-assembly.
        # Start by unloading the sub-assembly.
        childNodes = self._GetChildren(assemblyNode)
        nestedAssemblyNode = childNodes[0]
        cmds.assembly(nestedAssemblyNode, edit=True, active='')

        # From here, testing the nested assembly node should be the same as
        # testing a standalone model reference node.
        self._ValidateAllModelRepresentations(nestedAssemblyNode)
示例#38
0
 def test_create_nodes(self):
     # create all types of nodes, just individual samples, assure createNode
     # gets it right
     pe = nt.PointEmitter()
     assert pe.parent() is None
     
     # a shape with just a shortname works as well
     m = nt.createNode("myMesh", "mesh")
     mp = m.parent()
     assert isinstance(mp, nt.Transform)
     
     cmds.undo()
     cmds.undo()
     
     assert pe.isAlive() and not pe.isValid()
     assert mp.isAlive() and not mp.isValid()
     assert m.isAlive() and not m.isValid()
     
     cmds.redo()
     assert pe.isValid()
     
     cmds.redo()
     assert m.isValid() and mp.isValid()
示例#39
0
        def measurePlugConnection( msg, func, callNumberList ):
            """Call func of named operation msg number of times as in callNumberList"""
            for numcons in callNumberList:
                undoObj = undo.StartUndo()

                starttime = time.time()
                for i in xrange( numcons ):
                    func( i )
                elapsed = time.time( ) - starttime

                print >> sys.stderr, "%i %s in %f s ( %f / s )" % ( numcons, msg, elapsed, numcons / elapsed )

                del( undoObj )

                starttime = time.time()
                cmds.undo()
                undoelapsed = time.time() - starttime

                starttime = time.time()
                cmds.redo()
                redoelapsed = time.time() - starttime

                print >> sys.stderr, "UNDO / REDO Time = %f / %f ( %f * faster than initial creation )" % ( undoelapsed, redoelapsed,  elapsed / max( redoelapsed, 0.001) )
示例#40
0
	def test_storageSetHandling( self ):
		mrvmaya.Scene.new( force = True )
		snode = nt.createNode( "storage",  "storageNode" )

		# SIMPLE SET
		did = "objset"
		
		# error checking 
		
		objset = snode.objectSet( did, 0, autoCreate = True )
		assert isinstance( objset, nt.ObjectSet ) 
		assert len(snode.setsByID(did)) == 1

		# does not exist anymore
		cmds.undo()
		self.failUnlessRaises( AttributeError, snode.objectSet, did, 0, autoCreate = False )

		# objset should be valid again
		cmds.redo()
		assert objset.isValid() and objset.isAlive() 

		# del set
		snode.deleteObjectSet( did, 0 )
		assert not objset.isValid() and objset.isAlive() 
		self.failUnlessRaises( AttributeError, snode.objectSet, did, 0, False ) 
		cmds.undo()
		assert objset.isValid() 
		assert snode.objectSet(did, 0, False) == objset
		cmds.redo()
		assert not objset.isValid() 
		self.failUnlessRaises( AttributeError, snode.objectSet, did, 0, False )
		cmds.undo()	# undo deletion after all
		assert objset.isValid()
		assert snode.objectSet(did, 0, False) == objset
		# SIMPLE OBJSET OPERATIONS

		# MULTIPLE SETS


		# PARTITION HANDLING
		#######################
		partition = snode.setPartition( did, True )
		assert snode.partition( did ) is not None 
		cmds.undo()
		assert snode.partition( did ) is None 
		cmds.redo()	# set is available again

		# delete the single set we have, partition should be gone as well
		snode.deleteObjectSet( did, 0 )
		assert not partition.isValid() 
		cmds.undo()
		assert partition.isValid() 

		# disable partition
		snode.setPartition( did, False )
		assert snode.isAlive() and snode.isValid() 		# recently it would be deleted
		assert snode.partition( did ) is None 
		snode.setPartition( did, True )

		# new set, check partition
		oset = snode.objectSet( did, 1, autoCreate = 1 )
		assert isinstance( oset, nt.ObjectSet ) 
		assert len( oset.partitions() ) == 1 
		assert oset.partitions()[0] == snode.partition( did ) 

		cmds.undo()
		assert len( oset.partitions() ) == 0 
		cmds.redo()

		# set is in multiple partitions, some from us, some from the user
		myprt = nt.createNode( "mypartition", "partition" )
		myprt.addSets( oset )
		assert myprt != snode.partition( did ) 
		snode.setPartition( did, False )
		assert myprt.sets( )[0] == oset 
		assert len( oset.partitions() ) == 1 

		# undo / redo
		cmds.undo()
		assert len( oset.partitions() ) == 2 
 		cmds.redo()
		assert len( oset.partitions() ) == 1 
示例#41
0
	def test_MPlug( self ):
		persp = nt.Node( "persp" )
		front	 = nt.Node( "front" )
		side	 = nt.Node( "side" )
		matworld = persp.worldMatrix
		assert isinstance(matworld.mfullyQualifiedName(), basestring)

		str( matworld )
		repr( matworld )

		# CONNECTIONS
		#######################
		# CHECK COMPOUND ACCESS
		tx = persp.translate.mchildByName('tx')
		
		# can access attributes twice
		persp.translate

		# DO CONNECTIONS ( test undo/redo )
		persp.translate.mconnectTo(front.translate, force=True)

		assert persp.translate.misConnectedTo(front.translate) 	# misConnectedTo
		assert persp.translate.minput().isNull( ) 
		cmds.undo( )
		assert not persp.translate.misConnectedTo( front.translate ) 
		cmds.redo( )
		assert front.translate in persp.translate.moutputs() 

		# check moutput
		assert persp.translate.moutput() == front.translate 
		assert persp.rotate.moutput().isNull()		# unconnected return nullPlus as minput does

		# CHECK CONNECTION FORCING
		persp.translate.mconnectTo(front.translate, force=False) 			# already connected
		self.failUnlessRaises( RuntimeError, persp.s.mconnectTo, front.translate, force=False )

		# overwrite connection
		side.translate.mconnectTo(front.translate)	# force default True
		assert side.translate.misConnectedTo(front.translate) 

		# undo - old connection should be back
		cmds.undo()
		assert persp.translate.misConnectedTo(front.translate) 

		# disconnect input
		front.translate.mdisconnectInput()
		assert not persp.translate.misConnectedTo(front.translate) 

		cmds.undo()

		# disconnect output
		persp.t.mdisconnectOutputs( )
		assert len( persp.translate.moutputs() ) == 0 

		cmds.undo()
		assert persp.t.misConnectedTo( front.translate ) 

		# disconnect from
		persp.t.mdisconnectFrom(front.translate)
		assert not persp.t.misConnectedTo(front.t) 

		cmds.undo()
		assert persp.t.misConnectedTo(front.t) 

		# COMPARISONS
		assert persp.t != front.t 
		assert persp.t.mchildByName('tx') != persp.t.mchildByName('ty') 

		# affected plugs
		affectedPlugs = persp.t.maffects( )
		assert len( affectedPlugs ) > 1  

		affectedPlugs = persp.t.maffected( )
		assert len( affectedPlugs ) > 1  
		
		
		# test multi connections
		sn = nt.createNode("network1", "network")
		sn2 = nt.createNode("network2", "network") 
		tn = nt.createNode("network3", "network")
		
		def pir(array_plug, range_iter):
			for index in range_iter:
				yield array_plug.elementByLogicalIndex(index)
			# END for each item in range
		# END plugs-in-range
		
		# connect 10 to 10 
		r = range(10)
		api.MPlug.mconnectMultiToMulti(	izip(pir(sn.a, r), pir(tn.affectedBy, r)), force=False) 
		for i in r:
			assert sn.a.elementByLogicalIndex(i).misConnectedTo(tn.affectedBy.elementByLogicalIndex(i))
		# END make connection assertion
		
		# connection of overlapping range fails without force
		r = range(5, 15)
		self.failUnlessRaises(RuntimeError, api.MPlug.mconnectMultiToMulti, izip(pir(sn2.a, r), pir(tn.affectedBy, r)), force=False)
		
		# there no connection should have worked ( its atomic )
		# hence slot 10 is free
		persp.tx > tn.affectedBy.elementByLogicalIndex(10)
		
		# force connection works
		api.MPlug.mconnectMultiToMulti(izip(pir(sn2.a, r), pir(tn.affectedBy, r)), force=True)
		
		for i in r:
			assert sn2.a.elementByLogicalIndex(i).misConnectedTo(tn.affectedBy.elementByLogicalIndex(i))
		# END make connection assertion

		# ATTRIBUTES AND UNDO
		#######################
		funcs = ( 	( "isLocked", "msetLocked" ), ( "isKeyable", "msetKeyable" ),
					( "isCachingFlagSet", "msetCaching" ), ( "isChannelBoxFlagSet", "msetChannelBox" ) )

		plugnames =( "t", "tx", "r","rx", "s", "sy" )
		for p in plugnames:
			plug = persp.findPlug(p)

			for ( getname, setname ) in funcs:
				fget = getattr( plug, getname )
				fset = getattr( plug, setname )

				curval = fget()
				oval = bool( 1 - curval )
				fset( oval )

				# SPECIAL HANDLING as things cannot be uncached
				if setname == "msetCaching":
					continue

				assert fget() == oval 

				cmds.undo()
				assert fget() == curval 

				cmds.redo()
				assert fget() == oval 

				fset( curval )	# reset
			# END for each function
		# END for each plugname

		# QUERY
		############################
		# ELEMENT ITERATION
		matworld.evaluateNumElements( )
		for elm in matworld:
			assert elm.mparent( ) == matworld 

		translate = persp.translate

		assert len( translate.mchildren() ) == translate.numChildren() 

		# CHILD ITERATION
		for child in translate.mchildren( ):
			assert child.mparent( ) == translate 
		assert len( translate.mchildren() ) == 3 

		# SUB PLUGS GENERAL METHOD
		assert len( matworld ) == len( matworld.msubPlugs() ) 
		assert translate.numChildren() == len( translate.msubPlugs() ) 
		assert len( translate.msubPlugs() ) == 3 


		# ARRAY CONNECTIONS
		###################
		objset = nt.createNode( "set1", "objectSet" )
		partition = nt.createNode( "partition1", "partition" )
		pma = nt.createNode( "plusMinusAverage1", "plusMinusAverage" )
		destplug = persp.translate.mconnectToArray( pma.input3D, exclusive_connection = True )
		assert persp.translate.misConnectedTo(destplug) 

		# exclusive connection should return exisiting plug
		assert persp.translate.mconnectToArray( pma.input3D, exclusive_connection = True ) == destplug 

		# but newones can also be created
		assert persp.translate.mconnectToArray( pma.input3D, exclusive_connection = False ) != destplug 
		#assert objset.partition.mconnectToArray( partition.sets, exclusive_connection = False ) != destplug 


		# assure the standin classes are there - otherwise my list there would
		# bind to the standins as the classes have not been created yet
		plugs = [ matworld, translate ]
		for plug in plugs: plug.mwrappedAttribute()

		# CHECK ATTRIBUTES and NODES
		for plug, attrtype in zip( plugs, [ nt.TypedAttribute, nt.CompoundAttribute ] ):
			attr = plug.mwrappedAttribute( )
			assert isinstance( attr, nt.Attribute ) 
			assert isinstance( attr, attrtype ) 

			node = plug.mwrappedNode()
			assert isinstance( node, nt.Node ) 
			assert node == persp 

		# UNDO / REDO
		##############
		cam = nt.createNode( "myTrans", "transform" )
		testdb = [ ( cam.visibility, "Bool", True, False ),
					( cam.tx, "Double", 0.0, 2.0 ) ]
		# TODO: Add all missing types !
		for plug, typename, initialval, targetval in testdb:
			getattrfunc = getattr( plug, "as"+typename )
			setattrfunc = getattr( plug, "mset"+typename )

			assert getattrfunc() == initialval 
			setattrfunc( targetval )
			assert getattrfunc() == targetval 
			cmds.undo()
			assert getattrfunc() == initialval 
			cmds.redo()
			assert getattrfunc() == targetval 
		# END for each tuple in testdb
		
		
		# TEST EVERYTHING
		#################
		# This part has been written to be very sure every customized method gets 
		# called at least once. I don't trust my 'old'  tests, although they do 
		# something and are valuable to the testing framework. 
		nwnode = nt.Network()
		persp.msg.mct(nwnode.affectedBy.elementByLogicalIndex(0))
		front.msg.mct(nwnode.affectedBy.elementByLogicalIndex(1))
		
		t = persp.translate
		tx = persp.tx
		wm = persp.wm
		a = nwnode.affectedBy
		
		a.evaluateNumElements()
		assert len(wm) == 1 and len(a) == 2
		assert isinstance(iter(wm).next(), api.MPlug)
		assert len(list(a)) == 2
		
		# test str/repr
		assert str(wm) != str(a)
		assert repr(wm) != str(wm)
		assert wm != a
		
		# is it really necessary to apply custom handling here ? Check __eq__ method
		# test comparison
		assert a[0] == a[0]
		assert a[0] != a[1]
		
		# mparent 
		assert tx.mparent() == t
		assert a[0].mparent() == a
		
		# mchildren
		assert len(a[0].mchildren()) == 0
		assert len(t.mchildren()) == 3
		
		# mchildByName
		assert t.mchildByName('tx') == tx
		self.failUnlessRaises(TypeError, tx.mchildByName, 'something')
		self.failUnlessRaises(AttributeError, t.mchildByName, 'doesntexist')
		
		# msubPlugs
		assert len(t.msubPlugs()) == 3
		assert len(a.msubPlugs()) == 2
		assert len(tx.msubPlugs()) == 0
		
		# msetLocked
		tx.msetLocked(1)
		assert tx.isLocked()
		tx.msetLocked(0)
		assert not tx.isLocked()
		
		# msetKeyable
		tx.msetKeyable(0)
		assert not tx.isKeyable()
		tx.msetKeyable(1)
		assert tx.isKeyable()
		
		# msetCaching
		tx.msetCaching(0)
		#assert not tx.isCachingFlagSet()	# for some reason, the caching cannot be changed here
		tx.msetCaching(1)
		assert tx.isCachingFlagSet() == 1
		
		# msetChannelBox
		tx.msetChannelBox(0)
		assert not tx.isChannelBoxFlagSet()
		tx.msetChannelBox(1)
		assert tx.isChannelBoxFlagSet() == 1
		
		# mconnectMultiToMulti
		# is tested elsewhere
		
		# connectTo
		self.failUnlessRaises(RuntimeError, persp.msg.mconnectTo, a[1], force=False)	# already connected
		front.msg.mconnectTo(a[1], force=False)		# already connected
		front.msg.mconnectTo(a[0], force=True)		# force breaks connections
		persp.msg.mconnectTo(a[0])					# default is force
		
		# mconnectToArray
		# sufficiently tested ( -> st )
		
		# mdisconnect
		# st
		
		# mdisconnectInput
		# st
		
		# mdisconnectOutputs
		# st
		
		# mdisconnectFrom
		# st
		
		# mdisconnectNode
		# st
		
		# mhaveConnection
		assert api.MPlug.mhaveConnection(front.msg, a[1]) and api.MPlug.mhaveConnection(a[1], front.msg)
		assert not api.MPlug.mhaveConnection(persp.msg, a[1]) and not api.MPlug.mhaveConnection(a[1], persp.msg)
		
		# misConnectedTo
		# st
		
		# moutputs
		assert len(front.msg.moutputs()) == 1 and front.msg.moutputs()[0] == a[1]
		assert len(a[0].moutputs()) == 0
		
		# moutput
		# st
		
		# minputs
		assert len(a.minputs()) == 2
		assert len(a[1].minputs()) == 1
		
		
		# miterGraph 
		# st
		
		# miterInputGraph
		# st
		
		# miterOutputGraph
		# st
		
		# minput
		# st
		
		# mconnections
		assert len(front.msg.mconnections()) == 2
		assert len(a[1].mconnections()) == 2
		
		
		# mdependencyInfo
		m = nt.Mesh()
		assert len(m.outMesh.maffected())
		assert isinstance(m.outMesh.maffected()[0], api.MPlug)
		assert m.outMesh.maffected() == m.outMesh.mdependencyInfo(by=True)
		assert isinstance(m.inMesh.maffects(), list)	# no affected items for some reason
		assert m.inMesh.maffects() == m.inMesh.mdependencyInfo(by=False)
		
		
		# mnextLogicalIndex|plug
		assert a.mnextLogicalIndex() == 2
		assert a.mnextLogicalPlug().logicalIndex()
		
		# mwrappedAttribute
		assert isinstance(a.mwrappedAttribute(), nt.Attribute)
		
		# mwrappedNode
		assert isinstance(a.mwrappedNode(), nt.Node)
		
		# masData
		nt.PolyCube().output.mconnectTo(m.inMesh)	# need data here
		assert isinstance(m.outMesh.masData(), nt.Data)
		
		# mfullyQualifiedName
		assert a.mfullyQualifiedName() != a.partialName()
示例#42
0
    def test_undoBasics(self):
        undo.startUndo()

        # put some undoable operation
        op = TestUndoQueue.TestOperation()
        op.doIt()  # apply operation

        assert len(sys._maya_stack) == 1
        assert sys._maya_stack_depth == 1

        undo.endUndo()

        # STACK MUST BE EMPTY#
        # as it has been taken by the command
        assert len(sys._maya_stack) == 0

        # UNDO
        cmds.undo()
        assert op.numDoit == op.numUndoIt

        # REDO
        cmds.redo()
        assert op.numDoit - 1 == op.numUndoIt

        # OP WITHOUT PUSH
        self.failUnlessRaises(AssertionError, TestUndoQueue.TestOperation)

        mrvmaya.Mel.flushUndo()

        # handle undo ourselves
        persp = Node("persp")
        curvalue = persp.tx.asFloat()
        newvalue = curvalue + 1.0

        undo.startUndo()
        persp.tx.msetFloat(newvalue)
        assert persp.tx.asFloat() == newvalue

        undo.undoAndClear()  # end undo must come afterwards, otherwise the comand takes the queue
        undo.endUndo()
        assert persp.tx.asFloat() == curvalue  # its back to normal without an official undo

        # UNDO AND FILE FLUSHES
        ########################
        # Our stack must be flused once maya's undo queue gets flushed
        # This is critical if an undoable method causes undo flushes, but also
        # built up our own intermediate stack which might now contain entries from
        # a non-existing scene
        # NOTE: Currently this is a known limitation that could be circumvented
        # with some pre-scene-callbacks
        trans = nt.createNode("mytrans", "transform")

        undo.startUndo()
        trans.tx.msetFloat(10.0)
        assert len(sys._maya_stack) == 1
        mrvmaya.Scene.new(force=1)
        # DO NOT FAIL - allow releases to be done which would fail otherwise
        # Print a reminder though
        # TODO: Try to fix this
        # assert len( sys._maya_stack ) == 0, "Known Undo-Limitation"
        # http://github.com/Byron/mrv/issues#issue/2
        print "FIX KNOWN UNDO LIMITATION WHICH HAS BEEN SKIPPED TO ALLOW RELEASES"
        undo.endUndo()
示例#43
0
    def test_checkNamespaces( self ):
        rootns = Namespace( Namespace.rootpath )
        childns = rootns.children( )
        assert rootns.isRoot() 
        assert len( childns ) == 3 

        for ns in childns:
            assert ns.parent( ) == rootns 
            assert ns.isAbsolute()
            assert ns.exists()
            allChildren = ns.childrenDeep( )
            assert len( allChildren ) == 2 

            for child in allChildren:
                assert len( child.parentDeep() ) 

        # end for each childns

        # cannot delete root namespace
        self.failUnlessRaises( ValueError, rootns.delete )
        
        # default constructor creates root namesapce
        assert Namespace() == RootNamespace


        # create a few namespaces
        for ns in [ "newns", "newns:child", "longer:namespace",":hello:world:here" ]:
            curns = Namespace.current()
            newns = Namespace.create( ns )
            assert newns.exists() 
            assert Namespace.current() == curns 

            # test undo: creation
            cmds.undo()
            assert not newns.exists() 
            cmds.redo()
            assert newns.exists() 

            # test undo: change current
            assert newns.setCurrent() == newns
            assert Namespace.current() == newns 
            cmds.undo()
            assert Namespace.current() == curns 




        # rename all children
        for ns in childns:
            newname = str( ns ) + "_renamed"
            renamedns = ns.rename( newname )
            assert renamedns == renamedns 
            assert renamedns.exists() 

        # delete all child namepaces
        childns = rootns.children()

        # check relative namespace
        for ns in childns:
            assert not ns.relativeTo( rootns ).isAbsolute() 

        for ns in childns:
            allchildren = ns.childrenDeep()
            ns.delete( move_to_namespace = rootns )
            assert not ns.exists() 
            for child in allChildren:
                assert not child.exists() 


        # ITER ROOT NAMESPACE - REAL OBJECTS
        curns = Namespace.current()
        numobjs = 0
        for obj in RootNamespace.iterNodes( depth = 0 ):
            numobjs += 1
        assert numobjs != 0 
        assert Namespace.current() == curns 

        # ITER STRINGS
        newnumobjs = 0
        for obj in Namespace( ":" ).iterNodes( depth = 0, asNode = 0 ):
            newnumobjs += 1

        assert newnumobjs == numobjs
        assert Namespace.current() == curns 
         

        # empty namespace must come out as root
        ns = Namespace( "" )
        assert ns == Namespace.rootpath 

        # TEST SPLIT
        ###########
        t = Namespace.splitNamespace( "hello:world" )
        assert t[0] == ":hello" and t[1] == "world" 

        t = Namespace.splitNamespace( ":hello:world:there" )
        assert t[0] == ":hello:world" and t[1] == "there" 


        # TEST TORELATIVE
        #################
        assert Namespace( "hello" ).toRelative( ) == "hello" 
        assert Namespace( ":hello" ).toRelative( ) == "hello" 

        # TEST REPLACEMENT
        #####################
        rootrel,rootabs,nsrel,nsabs,multins,multinabs = "rootnsrel", ":rootnsabs", "ns:relns", ":ns:absolutens", "ns1:ns2:multinsrel",":ns1:ns2:ns3:ns2:multinabs"
        rootns,ns,ns2 = Namespace( "" ),Namespace("ns",absolute=False),Namespace( "ns2",absolute=False )
        newnssingle = Namespace( "nns" )
        newnsmulti = Namespace( "nns1:nns2" )

        assert rootns.substitute( rootrel, newnssingle ) == ":nns:rootnsrel" 
        assert rootns.substitute( rootrel, newnsmulti ) == ":nns1:nns2:rootnsrel" 

        assert rootns.substitute( rootabs, newnssingle ) == ":nns:rootnsabs" 
        assert rootns.substitute( rootabs, newnsmulti ) == ":nns1:nns2:rootnsabs" 

        assert ns2.substitute( multins, newnssingle ) == "ns1:nns:multinsrel" 
        assert ns2.substitute( multins, newnsmulti ) == "ns1:nns1:nns2:multinsrel" 

        assert ns2.substitute( multinabs, newnssingle ) == ":ns1:nns:ns3:nns:multinabs" 
        assert ns2.substitute( multinabs, newnsmulti ) == ":ns1:nns1:nns2:ns3:nns1:nns2:multinabs" 

        # empty replacement - remove ns
        assert ns2.substitute( multins, "" ) == "ns1:multinsrel" 
        assert ns.substitute( nsabs, "" ) == ":absolute" 
        
        # namespaces have slots
        self.failUnlessRaises( AttributeError, setattr, ns, "myattr", 2 )
示例#44
0
    def test_createNodes(self):
        names = ["hello","bla|world","this|world|here","that|this|world|here"]
        nsnames = ["a:hello","blab|b:world","c:this|b:world","d:that|c:this|b:world|a:b:c:d:here"]
        types = ["facade", "nurbsCurve", "nurbsSurface", "subdiv"]

        # SIMPLE CREATION: Paths + nested namespaces
        for i in range(len(names)):
            ntype = types[i]
            newnode = nt.createNode(names[i], ntype)
            assert isinstance(newnode, getattr(nt, capitalize(ntype))) 
            assert newnode.isValid() and newnode.isAlive() 

            # test undo
            cmds.undo()
            assert not newnode.isValid() and newnode.isAlive() 
            cmds.redo()
            assert newnode.isValid() and newnode.isAlive() 

            newnsnode = nt.createNode(nsnames[i], ntype)
            assert isinstance(newnsnode, getattr(nt, capitalize(ntype))) 
            assert newnsnode.isValid() and newnsnode.isAlive() 

            # test undo
            cmds.undo()
            assert not newnsnode.isValid() and newnsnode.isAlive() 
            cmds.redo()
            assert newnsnode.isValid() and newnsnode.isAlive() 
        # END for each created object

        # EMPTY NAME and ROOT
        self.failUnlessRaises(RuntimeError, nt.createNode, '|', "facade")
        self.failUnlessRaises(RuntimeError, nt.createNode, '', "facade")


        # CHECK DIFFERENT ROOT TYPES
        depnode = nt.createNode("blablub", "facade")
        self.failUnlessRaises(NameError, nt.createNode, "|blablub|:this", "transform", renameOnClash = False)

        # DIFFERENT TYPES AT END OF PATH
        nt.createNode("this|mesh", "mesh")
        self.failUnlessRaises(NameError, nt.createNode, "this|mesh", "nurbsSurface", forceNewLeaf = False)

        # renameOnClash  - it fails if the dep node exists first
        nt.createNode("node", "facade")
        self.failUnlessRaises(NameError, nt.createNode, "this|that|node", "mesh", renameOnClash = False)

        # obj exists should match dg nodes with dag node like path (as they occupy the same
        # namespace after all
        assert nt.objExists("|node") 

        # it also clashes if the dg node is created after a  dag node with the same name
        nt.createNode("that|nodename", "mesh")
        self.failUnlessRaises(NameError, nt.createNode, "nodename", "facade", renameOnClash = False)


        # it should be fine to have the same name in several dag levels though !
        newmesh = nt.createNode("parent|nodename", "transform")
        newmesh1 = nt.createNode("parent|nodename|nodename", "mesh")
        newmesh2 = nt.createNode("otherparent|nodename|nodename", "mesh")
        assert newmesh != newmesh1 
        assert newmesh1 != newmesh2 

        # FORCE NEW
        ##############
        oset = nt.createNode("objset", "objectSet", forceNewLeaf = False)
        newoset = nt.createNode("objset", "objectSet", forceNewLeaf = True)
        assert oset != newoset 

        # would expect same set to be returned
        sameoset = nt.createNode("objset", "objectSet", forceNewLeaf = False)
        assert sameoset == oset 

        # force new and dag paths
        newmesh3 = nt.createNode("otherparent|nodename|nodename", "mesh", forceNewLeaf = True)
        assert newmesh3 != newmesh2 
示例#45
0
    def test_wrapDepNode(self):
        node = nt.Node("defaultRenderGlobals")

        # SKIP CHECKS TEST
        self.failUnlessRaises(ValueError, nt.Node, "this")  # does not exist
        # results inconsitent between maya 8.5 and 2008, thus we skip it as it is not of much value
        # self.failUnlessRaises(TypeError, nt.Node, "this", 1)  # skip check , maya throws

        # string should be name
        assert str(node) == node.name() 
        repr(node)


        # must not have methods that require undo
        try:
            node.create("this")
            node.setName("this")
        except AttributeError:
            pass
        except:
            raise       # could fail, but raise is better

        # get simple attributes
        for attr in ["preMel", "postMel"]:
            plug = getattr(node, attr)
            assert plug == getattr(node, attr)
            assert plug == node.findPlug(attr)
            assert not plug.isNull() 

        # check connection methods
        cons = node.connections()
        assert len(cons) 


        # DEPENDENCY INFO
        persp = nt.Node("persp")
        affected_attrs = persp.dependencyInfo("t", by=0)
        assert len(affected_attrs) > 1 
        affected_attrs = persp.dependencyInfo("t", by=1)
        assert len(affected_attrs) > 1 
        assert isinstance(affected_attrs[0], nt.Attribute)


        # CHECK LAZY WRAPPING
        # get mfn lazy wrapped attributes
        t = node.attributeCount()
        for state in [1,0]:
            node.setLocked(state)
            assert node.isLocked() == state 

        # ATTRIBUTES
        attr = node.attribute(0)
        attr.name()
        assert not attr.isNull() 

        for i in xrange(node.attributeCount()):
            attr = node.attribute(i)
            assert not attr.isNull()  and attr.name()

        # CHECK namespaces - should be root namespace
        ns = node.namespace()
        assert ns == nt.Namespace.rootpath 
        

        # RENAME DEP NODES
        ######################
        node = nt.createNode("mynode", "facade")
        renamed = node.rename("myrenamednode")

        assert renamed.name() == "myrenamednode" 
        assert node == renamed 

        # undo - redo
        cmds.undo()
        assert node.name() == "mynode" 
        cmds.redo()
        assert node.name() == "myrenamednode" 


        # trigger namespace error
        self.failUnlessRaises(RuntimeError, node.rename, "nsdoesnotexist:othername", autocreateNamespace = False)

        # now it should work
        node.rename("nsdoesnotexist:othername", autocreateNamespace=True)

        # multi undo - namespace is one operation in this one
        cmds.undo()
        assert not nsm.existsNamespace("nsdoesnotexist") 
        cmds.redo()
        assert node.isValid() 


        # rename to same name
        renamed = node.rename("nsdoesnotexist") # should be fine
        assert renamed == node 

        # othernode with different type exists
        othernode = nt.createNode("othernode", "groupId")
        self.failUnlessRaises(RuntimeError, node.rename, "othernode", renameOnClash = False)

        # locking
        othernode.setLocked(1)
        assert othernode.isLocked()
        cmds.undo()
        assert not othernode.isLocked()
        cmds.redo()
        assert othernode.isLocked()
        othernode.setLocked(0)
        assert not othernode.isLocked()

        # works if rename enabeld though
        node.rename("othernode")
示例#46
0
    def test_wrapDagNode(self):
        mesh = nt.createNode("parent|mesh", "mesh")
        parent = mesh.parent()

        # simple rename
        mesh.rename("fancymesh")


        # simple dupl test
        duplbase = nt.createNode("parent|this|other|duplbase", "mesh")
        transcopy = duplbase.transform().duplicate()
        copy = duplbase.duplicate("parent|this|other|duplcopy")
        assert copy != duplbase 
        assert str(copy) != str(duplbase) 
        assert str(copy) == "|parent|this|other|duplcopy" 

        # TEST ADDITIONAL OPTIONS
        for i in range(1,3):
            ocopy = duplbase.duplicate()
            assert str(ocopy) == str(duplbase) + str(i) 

            ocopy = duplbase.duplicate(newTransform=1)
            assert ocopy.basename() == duplbase.basename() 
            assert str(ocopy.parent()) == str(duplbase.parent()) + str(i + 1) 

            # undo both duplications and redo
            # CRASHES MAYA AFTER REDO
            # and if someone tries to access an object already created
            #cmds.undo()
            #cmds.undo()
            #assert duplbase.isValid() 
            #cmds.redo()
            #cmds.redo()
        # END for each copy


        # simple reparent
        otherparent = nt.createNode("oparent", "transform")
        mesh.reparent(otherparent)

        # REPARENT UNDO TEST
        cmds.undo()
        assert mesh.parent() == parent 
        cmds.redo()
        assert mesh.parent() == otherparent 



        # REPARENT RENAME CLASH
        origmesh = nt.createNode("parent|fancymesh", "mesh")            #  "|parent|fancymesh"
        self.failUnlessRaises(RuntimeError, mesh.reparent, parent , renameOnClash = False)

        # RENAME CLASH DAG NODE
        othermesh = nt.createNode("parent|mesh", "mesh")
        self.failUnlessRaises(RuntimeError, origmesh.rename, "mesh", renameOnClash = False)

        # now it works
        othermesh.rename("mesh", renameOnClash = True)
        assert othermesh.basename() == "mesh" 


        # shape under root
        self.failUnlessRaises(RuntimeError, mesh.reparent, None)

        # REPARENT AGAIN
        # should just work as the endresult is the same
        mesh.reparent(otherparent)  # it will also trigger a new undo event, so undo will react as it should
        mesh.reparent(otherparent)  #  "|otherparent|fancymesh"

        # REPARENT UNDER SELF
        self.failUnlessRaises(RuntimeError, mesh.reparent, mesh)

        # reparent transform to world
        wtrans = nt.createNode("parent2|worldtrans", "transform")
        parent = nt.Node("parent2")
        oparent = nt.createNode("oparent2", "transform")
        wtrans = wtrans.reparent(None)

        wtransnewparent = wtrans.setParent(parent)
        assert wtrans == wtransnewparent
        assert wtransnewparent.instanceCount(1) == 1 
        wtransnewparent.addParent(oparent)
        assert wtransnewparent.instanceCount(1) == 2 
        wtransnewparent.removeParent(oparent)
        assert wtrans.instanceCount(1) == 1 



        # OBJECT NAVIGATION
        #######################
        # TODO: navigate the object properly




        # DUPLICATE (Dag only)
        #########################
        newmesh = mesh.duplicate("|duplparent|duplmesh")
        assert str(newmesh) == "|duplparent|duplmesh" 
        self.failUnlessRaises(RuntimeError, mesh.duplicate, "|duplparent2|doesntexistns:duplmesh",
                                autocreateNamespace = False)
        assert newmesh != mesh 
        instbase = nt.createNode("|duplparent2|newnamespace:instmesh", "transform")
        meshinst = instbase.addInstancedChild(mesh)
        meshinstname = str(meshinst)

        # UNDO DUPLICATE
        #################
        cmds.undo()

        # this object will end up pointing to the same object , as it came from, use string test
        assert not nt.objExists(meshinstname) 
        cmds.redo()
        cmds.undo()
        cmds.redo()
        assert meshinst != mesh 
        assert meshinst.isAlive() and meshinst.isValid() and str(meshinst) == meshinstname 

        # Duplicate TRANSFORM (just a name given)
        # dag paths should be different although object is the same
        mesh = nt.createNode("|parent|mybeautifuluniquemeshname", "mesh")
        meshassert = nt.createNode("|parent|mesh", "mesh")
        meshself = nt.Node("|parent|mybeautifuluniquemeshname")
        assert mesh == meshself 

        # connect it, to track the instance by connection
        persp = nt.Node("persp")
        perspplug = persp.t.mchildByName('tx')
        triplug = meshself.maxTriangles
        perspplug.mconnectTo(triplug)

        # target does exist
        # this is blocking the target instance name with an incorrect type
        nt.createNode("parent|this|mybeautifuluniquemeshname", "transform")
        self.failUnlessRaises(RuntimeError, mesh.duplicate, "|parent|this")

        # if the path is too short ...
        self.failUnlessRaises(NameError, mesh.duplicate, str(mesh.transform()))
        self.failUnlessRaises(NameError, mesh.parent().duplicate, '|')


        meshinstname = mesh.transform().fullChildName("newns:meshinst")
        assert isinstance(meshinst, nt.Mesh) 
示例#47
0
    def test_childEditing(self):
        base = nt.createNode("basenode", "transform")
        obase = nt.createNode("otherbasenode", "transform")

        trans = nt.createNode("trans", "transform")
        otrans = nt.createNode("parent|trans", "transform")
        mesh = nt.createNode("meshparent|meshshape", "mesh")
        curve = nt.createNode("nurbsparent|ncurve", "nurbsCurve")
        itemlist = [trans, mesh, curve]

        instlist = list()

        # MULTIPLE ADDS
        ####################
        # Returns the same instance - its what the user wants
        for item in itemlist:
            assert item.instanceCount(0) == 1
            inst = base.addInstancedChild(item)
            assert base.addInstancedChild(item) == inst
            assert item.instanceCount(0) == 2
            assert item != inst and inst.isValid() and item.isValid() 

            instlist.append(inst)

            # UNDO TEST
            # undo basemesh
            cmds.undo()
            assert not inst.isValid() and inst.isAlive() 

            cmds.redo()
            assert inst.isValid() and inst.isAlive()
        # END for each object including undo/redo


        # KEEP PARENT FALSE - USE INSTANCES
        # TODO: this test needs a redo - the original purpose got lost when
        # the addChild method has been changed, additionally it needs to be
        # better documented as this instancing stuff is not easily understood if
        # one just sees the code
        for orig,inst in zip(itemlist, instlist):
            assert orig.object() == inst.object() and orig != inst
            ninst = obase.addChild(inst, keepExistingParent=False)
            
            # # duplicate adds are not problem, but it can't be tested as the inst is already invalid
            # assert obase.addChild(inst, keepExistingParent=False) == ninst
            
            assert not inst.isValid()
            assert ninst.isValid() and ninst.isAlive() 
            assert orig.isValid()           # original may not be influenced by that operation

            # undo / redo
            cmds.undo()
            assert orig.isValid()
            assert not ninst.isValid()
            assert inst.isValid()

            cmds.redo()
            assert not inst.isValid() and orig.isValid() and ninst.isValid()
        # END for each instance
        

        # RENAME ON CLASH = False
        self.failUnlessRaises(RuntimeError, obase.addChild, otrans, renameOnClash = False)

        # RENAME ON CLASH = True
        otransname = str(otrans)
        renamedtrans = obase.addChild(otrans, renameOnClash = True)
        assert renamedtrans.isValid() 
        renamedname = str(renamedtrans)
        assert renamedname != otransname 

        cmds.undo()
        assert nt.objExists(otransname) and not nt.objExists(renamedname) 

        cmds.redo()
示例#48
0
	def test_memberHandling( self ):
		s = nt.createNode( "memberSet", "objectSet" )

		# ADD/REMOVE SINGLE MEMBER
		####################
		# add Node ( dgnode )
		memberlist = self._getMemberList( )

		for i,member in enumerate( memberlist ):
			s.addMember( member )
			assert s.members( ).length() == i+1 
			assert s.isMember( member ) 
			cmds.undo()
			assert s.members( ).length() == i 
			cmds.redo()
		# end for each member

		# clear the set by undoing it all
		for i in range( len( memberlist ) ):
			cmds.undo()

		assert s.members().length() == 0 

		# get it back
		for i in range( len( memberlist ) ):
			cmds.redo()

		assert s.members().length() == len( memberlist ) 

		# MULTI-MEMBER UNDO/REDO
		##########################
		s.removeMembers( memberlist )
		assert s.members().length() == 0 
		cmds.undo()
		assert s.members().length() == len( memberlist ) 
		cmds.redo()
		assert s.members().length() == 0 

		# add members again
		s.addMembers( memberlist )
		assert s.members().length() == len( memberlist ) 
		cmds.undo()
		assert s.members().length() == 0 
		cmds.redo()
		assert s.members().length() == len( memberlist ) 


		# remove all members
		for i,member in enumerate( memberlist ):
			s.removeMember( member )

		assert s.members().length() == 0 

		# ADD/REMOVE MULTIPLE MEMBER
		######################
		# add node list
		s.addMembers( memberlist )
		assert s.members().length() == len( memberlist ) 

		s.clear()
		assert s.members().length() == 0 

		# Add selection listx
		sellist = nt.toSelectionList( memberlist )
		s.addMembers( sellist )
		assert s.members().length() == sellist.length() 

		# remove members from sellist
		s.removeMembers( sellist )
		assert s.members().length() == 0 

		cmds.undo()
		assert s.members().length() == sellist.length() 

		cmds.redo()
		assert s.members().length() == 0 

		
		# test smart add
		s.add(sellist)
		assert len(s) == len(sellist)
		single_item = sellist.mtoIter().next()
		s.add(single_item)
		assert len(s) == len(sellist)

		s.discard(single_item)
		assert single_item not in s
		
		s.discard(sellist.mtoList())
		assert len(s) == 0


		# TEST CLEAR
		#############
		s.addMembers( sellist )
		assert s.members().length() == sellist.length() 

		s.clear()
		assert s.members().length() == 0 

		cmds.undo()
		assert s.members().length() == sellist.length() 


		# USING SETMEMBERS
		########################
		members = self._getMemberList()
		# replace
		s.setMembers( members[0:2], 0 )
		assert s.members().length() == 2 
		
		# add
		s.setMembers( members[-2:-1], 1 )
		assert s.members().length() == 3 
		
		# remove
		s.setMembers( members[0:2], 2 )
		assert s.members().length() == 1 
		
		cmds.undo()
		assert s.members().length() == 3 
		
		
		# TEST SET PROTOCOLS
		####################
		assert len(s) == 3
		assert [ m for m in s ] == s.members().mtoList()
		assert iter(s).next() in s
示例#49
0
    def test_undo_stack(self):
        mrvmaya.Scene.new(force=1)
        ur = undo.UndoRecorder()

        # works inside of another undo level as well
        p = Node("persp")
        t = Node("top")

        # ===================
        undo.startUndo()
        p.t.mconnectTo(t.t)

        ########################
        # startRecording needs to come first
        self.failUnlessRaises(AssertionError, ur.stopRecording)
        ur.startRecording()
        ur.startRecording()  # doesnt matter
        p.r.mconnectTo(t.r)

        # second instance will fail
        ur2 = undo.UndoRecorder()
        self.failUnlessRaises(AssertionError, ur2.startRecording)
        self.failUnlessRaises(AssertionError, ur2.stopRecording)

        ur.stopRecording()
        ur.stopRecording()  # doesnt matter
        ########################
        assert p.r.misConnectedTo(t.r)
        assert p.t.misConnectedTo(t.t)
        ur.undo()
        assert not p.r.misConnectedTo(t.r)
        assert p.t.misConnectedTo(t.t)

        ur.redo()
        assert p.r.misConnectedTo(t.r)
        ur.undo()
        assert not p.r.misConnectedTo(t.r)

        undo.endUndo()
        # ===================

        assert p.t.misConnectedTo(t.t)
        cmds.undo()
        assert not p.t.misConnectedTo(t.t)
        cmds.redo()
        assert p.t.misConnectedTo(t.t)

        # we should be able to selectively redo it, even after messing with the queue
        ur.redo()
        assert p.r.misConnectedTo(t.r)
        cmds.undo()
        assert not p.t.misConnectedTo(t.t)

        # TEST UNDO GETS ENABLED
        try:
            cmds.undoInfo(swf=0)

            ur = undo.UndoRecorder()
            ur.startRecording()
            assert cmds.undoInfo(q=1, swf=1)

            p.s.mconnectTo(t.s)

            ur.stopRecording()
            assert not cmds.undoInfo(q=1, swf=1)
            assert p.s.misConnectedTo(t.s)
            ur.undo()
            assert not p.s.misConnectedTo(t.s)
            ur.redo()
            assert p.s.misConnectedTo(t.s)

        finally:
            cmds.undoInfo(swf=1)
        # END assure it gets turned back on

        # TEST UNDO QUEUE INTEGRATION
        # if we never called startRecording, it will not do anything
        ur = undo.UndoRecorder()
        p.tx.mconnectTo(t.tx)
        del (ur)

        assert p.tx.misConnectedTo(t.tx)
        cmds.undo()
        assert not p.tx.misConnectedTo(t.tx)
        cmds.redo()
        assert p.tx.misConnectedTo(t.tx)

        # If we recorded something, it will be part of the undo queue if
        # undo was not called
        ur = undo.UndoRecorder()
        ur.startRecording()
        p.ty.mconnectTo(t.ty)
        ur.stopRecording()

        assert p.ty.misConnectedTo(t.ty)
        cmds.undo()
        assert not p.ty.misConnectedTo(t.ty)
        cmds.redo()
        assert p.ty.misConnectedTo(t.ty)
示例#50
0
    def test_createNodes( self ):
        runs = [ 100,2500 ]
        all_elapsed = []

        numObjs = len( cmds.ls() )
        for numNodes in runs:

            nslist = genNestedNamesList( numNodes / 100, (0,3), genRandomNames(10,(3,8)),":" )
            nodenames = genNodeNames( numNodes, (1,5),(3,8),nslist )

            st = time.time( )
            undoobj = undo.StartUndo( )
            for nodename in nodenames:
                try:    # it can happen that he creates dg and dag nodes with the same name
                    self._createNodeFromName( nodename )
                except NameError:
                    pass
            # END for each node
            del( undoobj )  # good if we raise runtime errors ( shouldnt happend )

            elapsed = time.time() - st
            all_elapsed.append( elapsed )
            print >>sys.stderr, "Created %i nodes in %f s ( %f / s )" % ( numNodes, elapsed, numNodes / elapsed )

            # UNDO OPERATION
            st = time.time()
            cmds.undo()
            elapsed = time.time() - st
            print >>sys.stderr, "Undone Operation in %f s" % elapsed

        # END for each run

        # assure the scene is the same as we undo everything
        assert len( cmds.ls() ) == numObjs 


        # TEST MAYA NODE CREATION RATE
        #################################
        # redo last operation to get lots of nodes
        cmds.redo( )
        nodenames = cmds.ls( l=1 )
        nodes = list()

        st = time.time( )
        for name in nodenames:
            nodes.append(Node(name))

        elapsed = time.time() - st
        print >>sys.stderr, "Created %i WRAPPED Nodes ( from STRING ) in %f s ( %f / s )" % ( len( nodenames ), elapsed, len( nodenames ) / elapsed )


        # NodeFromStr
        st = time.time( )
        tmplist = list()
        for name in nodenames:
            tmplist.append(NodeFromStr(name))

        elapsed = time.time() - st
        print >>sys.stderr, "Created %i WRAPPED Nodes ( from STRING using NodeFromStr ) in %f s ( %f / s )" % ( len( nodenames ), elapsed, len( nodenames ) / elapsed )
        
        nodes_apiobjects = [ node.apiObject() for node in nodes ]
    
        # CREATE MAYA NODES FROM DAGPATHS AND OBJECTS
        st = time.time( )
        tmplist = list()    # previously we measured the time it took to append the node as well
        for apiobj in nodes_apiobjects:
            tmplist.append(Node(apiobj))
        # END for each wrapped node

        api_elapsed = time.time() - st
        print >>sys.stderr, "Created %i WRAPPED Nodes ( from APIOBJ ) in %f s ( %f / s ) -> %f %% faster" % ( len( nodenames ), api_elapsed, len( nodenames ) / api_elapsed, (elapsed / api_elapsed) * 100 )


        # CREATE MAYA NODES USING THE FAST CONSTRUCTOR
        st = time.time( )
        tmplist = list()    # previously we measured the time it took to append the node as well
        for apiobj in nodes_apiobjects:
            tmplist.append(NodeFromObj(apiobj))
        # END for each wrapped node

        api_elapsed = time.time() - st
        print >>sys.stderr, "Created %i WRAPPED Nodes ( from APIOBJ using NodeFromObj) in %f s ( %f / s ) -> %f %% faster" % ( len( nodenames ), api_elapsed, len( nodenames ) / api_elapsed, (elapsed / api_elapsed) * 100 )


        # RENAME PERFORMANCE
        st = time.time()
        for node in tmplist:
            node.rename(node.basename()[:-1])
        # END for each node 
        elapsed = time.time() - st
        ltl = len(tmplist)
        print >>sys.stderr, "Renamed %i WRAPPED Nodes in %f s ( %f / s )" % ( ltl, elapsed, ltl / elapsed )
示例#51
0
    def test_general( self ):
        mrvmaya.Scene.new( force = True )

        s1 = nt.createNode( "storage1", "storageNode" )
        s2 = nt.createNode( "storage2", "storageNode" )
        
        s1msg = s1.storagePlug( "s1", plugType = 1, autoCreate = True )
        s2msg = s1.storagePlug( "s1", plugType = 1, autoCreate = True )

        # connect the message attributes respectively

        def measurePlugConnection( msg, func, callNumberList ):
            """Call func of named operation msg number of times as in callNumberList"""
            for numcons in callNumberList:
                undoObj = undo.StartUndo()

                starttime = time.time()
                for i in xrange( numcons ):
                    func( i )
                elapsed = time.time( ) - starttime

                print >> sys.stderr, "%i %s in %f s ( %f / s )" % ( numcons, msg, elapsed, numcons / elapsed )

                del( undoObj )

                starttime = time.time()
                cmds.undo()
                undoelapsed = time.time() - starttime

                starttime = time.time()
                cmds.redo()
                redoelapsed = time.time() - starttime

                print >> sys.stderr, "UNDO / REDO Time = %f / %f ( %f * faster than initial creation )" % ( undoelapsed, redoelapsed,  elapsed / max( redoelapsed, 0.001) )
            # END for each amount of plugs to connct
        # END measure function

        conlist = [ 250, 1000, 2000, 4000 ]

        # CONNECT MULTI PLUGS
        ######################
        multifunc = lambda i: s1msg.elementByLogicalIndex( i ).mconnectTo(s2msg.elementByLogicalIndex( i ))
        measurePlugConnection( "MULTI PLUG Connected", multifunc, conlist )

        # CONNECT SINGLE PLUGS
        persp = nt.Node( "persp" )
        front = nt.Node( "front" )
        def singleFunc( i ):
            persp.message.mconnectTo(front.isHistoricallyInteresting)
            persp.message.mdisconnectFrom(front.isHistoricallyInteresting)
        measurePlugConnection( "SINGLE PLUGS Connected", singleFunc, conlist )


        # SET AND GET
        ##############
        persp = nt.Node( "persp" )
        perspshape = persp[0]
        plugs = [ persp.tx, perspshape.fl ]

        num_iterations = 2500
        iterations = range( num_iterations )

        undoObj = undo.StartUndo()
        starttime = time.time()
        for plug in plugs:
            for i in iterations:
                value = plug.asFloat()
                plug.msetFloat( value )
            # END get set plug
        # END for each plug
        elapsed = time.time() - starttime
        del( undoObj )

        total_count = num_iterations * len( plugs )
        print >> sys.stderr, "Get/Set %i plugs %i times ( total = %i ) in %f ( %g / s )" % ( len( plugs ), num_iterations, total_count,  elapsed, total_count / elapsed )

        starttime = time.time()
        cmds.undo()
        undoelapsed = time.time() - starttime

        starttime = time.time()
        cmds.redo()
        redoelapsed = time.time() - starttime

        print >> sys.stderr, "UNDO / REDO Time = %f / %f ( %f * faster than initial set/get )" % ( undoelapsed, redoelapsed,  elapsed / max( redoelapsed, 0.001) )