def setUp(self): ''' Called initially to set up the maya test environment ''' # Load plugins self.assertTrue(self.pluginsLoaded) # Open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene()
def testTranslateLockedLayer(self): # create new stage cmds.file(new=True, force=True) # Open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # get the stage proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) proxyShapePath = proxyShapes[0] stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() # cylinder prim cylinderPrim = stage.GetPrimAtPath('/pCylinder1') self.assertIsNotNone(cylinderPrim) # create a sub-layer. rootLayer = stage.GetRootLayer() subLayerA = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="LayerA")[0] # check to see the if the sublayers was added addedLayers = [subLayerA] self.assertEqual(rootLayer.subLayerPaths, addedLayers) # set the edit target to LayerA. cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerA) # set permission to edit to false layerA = Sdf.Find(subLayerA) layerA.SetPermissionToEdit(False) # Check that our helper function is returning the right thing self.assertFalse(mayaUsdUfe.isEditTargetLayerModifiable(stage)) # Get translate attribute and make sure its empty translateAttr = cylinderPrim.GetAttribute('xformOp:translate') self.assertIsNotNone(translateAttr) tranlateBeforeEdit = translateAttr.Get() # create a transform3d and translate cylinderPath = ufe.Path([ mayaUtils.createUfePathSegment("|mayaUsdTransform|shape"), usdUtils.createUfePathSegment("/pCylinder1") ]) cylinderItem = ufe.Hierarchy.createItem(cylinderPath) cylinderT3d = ufe.Transform3d.transform3d(cylinderItem) if cylinderT3d is not None: cylinderT3d.translate(5.0, 6.0, 7.0) # check that the translate operation didn't change anything tranlateAfterEdit = translateAttr.Get() self.assertEqual(tranlateBeforeEdit, tranlateAfterEdit)
def testRenameNotifications(self): '''Rename a USD node and test for the UFE notifications.''' # open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # clear selection to start off cmds.select(clear=True) # select a USD object. mayaPathSegment = mayaUtils.createUfePathSegment( '|mayaUsdTransform|shape') usdPathSegment = usdUtils.createUfePathSegment('/pCylinder1') cylinderPath = ufe.Path([mayaPathSegment, usdPathSegment]) cylinderItem = ufe.Hierarchy.createItem(cylinderPath) ufe.GlobalSelection.get().append(cylinderItem) # get the USD stage stage = mayaUsd.ufe.getStage(str(mayaPathSegment)) # set the edit target to the root layer stage.SetEditTarget(stage.GetRootLayer()) self.assertEqual(stage.GetEditTarget().GetLayer(), stage.GetRootLayer()) # Create our UFE notification observer ufeObs = TestObserver() if (os.getenv('UFE_PREVIEW_VERSION_NUM', '0000') < '2021'): # We start off with no observers self.assertFalse(ufe.Scene.hasObjectAddObserver(ufeObs)) self.assertFalse(ufe.Scene.hasObjectDeleteObserver(ufeObs)) self.assertFalse(ufe.Scene.hasObjectPathChangeObserver(ufeObs)) # Add the UFE observers we want to test ufe.Scene.addObjectAddObserver(ufeObs) ufe.Scene.addObjectDeleteObserver(ufeObs) ufe.Scene.addObjectPathChangeObserver(ufeObs) else: # We start off with no observers self.assertFalse(ufe.Scene.hasObserver(ufeObs)) # Add the UFE observer we want to test ufe.Scene.addObserver(ufeObs) # rename newName = 'pCylinder1_Renamed' cmds.rename(newName) # After the rename we should have 1 rename notif and no unexepected notifs. self.assertEqual(ufeObs.notifications(), 1) self.assertFalse(ufeObs.receivedUnexpectedNotif())
def testShareStage(self): ''' Verify share/unshare stage workflow works properly ''' # create new stage cmds.file(new=True, force=True) # Open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # get the stage proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) proxyShapePath = proxyShapes[0] stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() rootIdentifier = stage.GetRootLayer().identifier # check that the stage is shared and the root is the right one self.assertTrue( cmds.getAttr('{}.{}'.format(proxyShapePath, "shareStage"))) self.assertEqual(stage.GetRootLayer().GetDisplayName(), "cylinder.usda") # unshare the stage cmds.setAttr('{}.{}'.format(proxyShapePath, "shareStage"), False) stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() rootLayer = stage.GetRootLayer() # check that the stage is now unshared and the root is the anon layer # and the old root is now sublayered under that self.assertFalse( cmds.getAttr('{}.{}'.format(proxyShapePath, "shareStage"))) self.assertEqual(rootLayer.GetDisplayName(), "unshareableLayer") self.assertEqual(rootLayer.subLayerPaths, [rootIdentifier]) # re-share the stage cmds.setAttr('{}.{}'.format(proxyShapePath, "shareStage"), True) stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() # check that the stage is now shared again and the layer is the same self.assertTrue( cmds.getAttr('{}.{}'.format(proxyShapePath, "shareStage"))) self.assertEqual(stage.GetRootLayer().GetDisplayName(), "cylinder.usda")
def testSingleAttributeBlocking(self): ''' Authoring attribute(s) in weaker layer(s) are not permitted if there exist opinion(s) in stronger layer(s).''' # create new stage cmds.file(new=True, force=True) # Open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # get the stage proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) proxyShapePath = proxyShapes[0] stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() # cylinder prim cylinderPrim = stage.GetPrimAtPath('/pCylinder1') self.assertIsNotNone(cylinderPrim) # author a new radius value self.assertTrue(cylinderPrim.HasAttribute('doubleSided')) doubleSidedAttr = cylinderPrim.GetAttribute('doubleSided') # authoring new attribute edit is expected to be allowed. self.assertTrue(mayaUsdUfe.isAttributeEditAllowed(doubleSidedAttr)) doubleSidedAttr.Set(0) # create a sub-layer. rootLayer = stage.GetRootLayer() subLayerA = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="LayerA")[0] # check to see the if the sublayers was added addedLayers = [subLayerA] self.assertEqual(rootLayer.subLayerPaths, addedLayers) # set the edit target to LayerA. cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerA) # doubleSidedAttr is not allowed to change since there is an opinion in a stronger layer self.assertFalse(mayaUsdUfe.isAttributeEditAllowed(doubleSidedAttr))
def testRenameUndo(self): '''Rename USD node.''' # open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # clear selection to start off cmds.select(clear=True) # select a USD object. mayaPathSegment = mayaUtils.createUfePathSegment( '|mayaUsdTransform|shape') usdPathSegment = usdUtils.createUfePathSegment('/pCylinder1') cylinderPath = ufe.Path([mayaPathSegment, usdPathSegment]) cylinderItem = ufe.Hierarchy.createItem(cylinderPath) cylinderHierarchy = ufe.Hierarchy.hierarchy(cylinderItem) propsItem = cylinderHierarchy.parent() propsHierarchy = ufe.Hierarchy.hierarchy(propsItem) propsChildrenPre = propsHierarchy.children() ufe.GlobalSelection.get().append(cylinderItem) # get the USD stage stage = mayaUsd.ufe.getStage(str(mayaPathSegment)) # check GetLayerStack behavior self.assertEqual(stage.GetLayerStack()[0], stage.GetSessionLayer()) self.assertEqual(stage.GetEditTarget().GetLayer(), stage.GetRootLayer()) # by default edit target is set to the Rootlayer. self.assertEqual(stage.GetEditTarget().GetLayer(), stage.GetRootLayer()) # rename cylinderItemType = cylinderItem.nodeType() newName = 'pCylinder1_Renamed' cmds.rename(newName) # The renamed item is in the selection. snIter = iter(ufe.GlobalSelection.get()) pCylinder1Item = next(snIter) pCylinder1RenName = str(pCylinder1Item.path().back()) self.assertEqual(pCylinder1RenName, newName) propsChildren = propsHierarchy.children() self.assertEqual(len(propsChildren), len(propsChildrenPre)) self.assertIn(pCylinder1Item, propsChildren) cmds.undo() self.assertEqual(cylinderItemType, ufe.GlobalSelection.get().back().nodeType()) def childrenNames(children): return [str(child.path().back()) for child in children] propsHierarchy = ufe.Hierarchy.hierarchy(propsItem) propsChildren = propsHierarchy.children() propsChildrenNames = childrenNames(propsChildren) self.assertNotIn(pCylinder1RenName, propsChildrenNames) self.assertIn('pCylinder1', propsChildrenNames) self.assertEqual(len(propsChildren), len(propsChildrenPre)) cmds.redo() self.assertEqual(cylinderItemType, ufe.GlobalSelection.get().back().nodeType()) propsHierarchy = ufe.Hierarchy.hierarchy(propsItem) propsChildren = propsHierarchy.children() propsChildrenNames = childrenNames(propsChildren) self.assertIn(pCylinder1RenName, propsChildrenNames) self.assertNotIn('pCylinder1', propsChildrenNames) self.assertEqual(len(propsChildren), len(propsChildrenPre))
def testShareStageSourceChange(self): ''' Verify the stage source change maintains the position in the hierarchy ''' # create new stage cmds.file(new=True, force=True) # Open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # get the proxy shape path proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) proxyShapeA = proxyShapes[0] # create another proxyshape (B) import mayaUsd_createStageWithNewLayer proxyShapeB = mayaUsd_createStageWithNewLayer.createStageWithNewLayer() proxyShapeB = proxyShapeB.split("|")[-1] # Connect them using stage data cmds.connectAttr('{}.outStageData'.format(proxyShapeA), '{}.inStageData'.format(proxyShapeB)) # get the stage stageB = mayaUsd.lib.GetPrim(proxyShapeB).GetStage() originalRootIdentifierB = stageB.GetRootLayer().identifier # check that the stage is shared and the root is the right one self.assertTrue(cmds.getAttr('{}.{}'.format(proxyShapeB, "shareStage"))) self.assertEqual(stageB.GetRootLayer().GetDisplayName(), "cylinder.usda") # unshare the stage cmds.setAttr('{}.{}'.format(proxyShapeB, "shareStage"), False) stageB = mayaUsd.lib.GetPrim(proxyShapeB).GetStage() rootLayerB = stageB.GetRootLayer() # check that the stage is now unshared and the root is the anon layer # and the old root is now sublayered under that self.assertFalse( cmds.getAttr('{}.{}'.format(proxyShapeB, "shareStage"))) self.assertEqual(rootLayerB.GetDisplayName(), "unshareableLayer") self.assertEqual(rootLayerB.subLayerPaths, [originalRootIdentifierB]) # Add complex hierarchy middleLayerB = Sdf.Layer.CreateAnonymous("middleLayer") middleLayerB.subLayerPaths = [originalRootIdentifierB] rootLayerB.subLayerPaths = [middleLayerB.identifier] # unshare the stage from the first proxy cmds.setAttr('{}.{}'.format(proxyShapeA, "shareStage"), False) stageA = mayaUsd.lib.GetPrim(proxyShapeA).GetStage() rootLayerA = stageA.GetRootLayer() stageB = mayaUsd.lib.GetPrim(proxyShapeB).GetStage() rootLayerB = stageB.GetRootLayer() # check that the stage is now unshared and the entire hierachy is good (A) self.assertFalse( cmds.getAttr('{}.{}'.format(proxyShapeA, "shareStage"))) self.assertEqual(rootLayerA.GetDisplayName(), "unshareableLayer") self.assertEqual(len(rootLayerA.subLayerPaths), 1) self.assertEqual(rootLayerA.subLayerPaths[0], originalRootIdentifierB) # Make sure the hierachy is good (B) self.assertFalse( cmds.getAttr('{}.{}'.format(proxyShapeB, "shareStage"))) self.assertEqual(rootLayerB.GetDisplayName(), "unshareableLayer") self.assertEqual(len(rootLayerB.subLayerPaths), 1) middleLayer = Sdf.Layer.Find(rootLayerB.subLayerPaths[0]) self.assertEqual(middleLayer.GetDisplayName(), "middleLayer") self.assertEqual(len(middleLayer.subLayerPaths), 1) unshareableLayerFromA = Sdf.Layer.Find(middleLayer.subLayerPaths[0]) self.assertEqual(unshareableLayerFromA.GetDisplayName(), "unshareableLayer") self.assertEqual(len(unshareableLayerFromA.subLayerPaths), 1) self.assertEqual(unshareableLayerFromA.subLayerPaths[0], originalRootIdentifierB)
def testShareStageComplexHierarchyToggle(self): ''' Verify share/unshare stage toggle works with complex heirharchies ''' # create new stage cmds.file(new=True, force=True) # Open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # get the stage proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) proxyShapePath = proxyShapes[0] stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() originalRootIdentifier = stage.GetRootLayer().identifier # check that the stage is shared and the root is the right one self.assertTrue( cmds.getAttr('{}.{}'.format(proxyShapePath, "shareStage"))) self.assertEqual(stage.GetRootLayer().GetDisplayName(), "cylinder.usda") # unshare the stage cmds.setAttr('{}.{}'.format(proxyShapePath, "shareStage"), False) stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() rootLayer = stage.GetRootLayer() # check that the stage is now unshared and the root is the anon layer # and the old root is now sublayered under that self.assertFalse( cmds.getAttr('{}.{}'.format(proxyShapePath, "shareStage"))) self.assertEqual(rootLayer.GetDisplayName(), "unshareableLayer") self.assertEqual(rootLayer.subLayerPaths, [originalRootIdentifier]) middleLayer = Sdf.Layer.CreateAnonymous("middleLayer") middleLayer.subLayerPaths = [originalRootIdentifier] rootLayer.subLayerPaths = [middleLayer.identifier] # Save and re-open testDir = tempfile.mkdtemp(prefix='ProxyShapeBase') tempMayaFile = os.path.join(testDir, 'ShareStageComplexHierarchyToggle.ma') cmds.file(rename=tempMayaFile) # make the USD layer absolute otherwise it won't be found cmds.setAttr('{}.{}'.format(proxyShapePath, "filePath"), originalRootIdentifier, type='string') cmds.file(save=True, force=True) cmds.file(new=True, force=True) cmds.file(tempMayaFile, open=True) # get the stage again (since we opened a new file) proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) proxyShapePath = proxyShapes[0] stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() rootLayer = stage.GetRootLayer() # make sure the middle layer is back (only one) self.assertEqual(len(rootLayer.subLayerPaths), 1) middleLayer = Sdf.Layer.Find(rootLayer.subLayerPaths[0]) self.assertEqual(middleLayer.GetDisplayName(), "middleLayer") # re-share the stage cmds.setAttr('{}.{}'.format(proxyShapePath, "shareStage"), True) stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() # check that the stage is now shared again and the identifier is correct self.assertTrue( cmds.getAttr('{}.{}'.format(proxyShapePath, "shareStage"))) self.assertEqual(stage.GetRootLayer().identifier, originalRootIdentifier) # unshare the stage cmds.setAttr('{}.{}'.format(proxyShapePath, "shareStage"), False) stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() rootLayer = stage.GetRootLayer() # check that the stage is now shared and the root is the anon layer # and the old root is now sublayered under that self.assertFalse( cmds.getAttr('{}.{}'.format(proxyShapePath, "shareStage"))) self.assertEqual(rootLayer.GetDisplayName(), "unshareableLayer") self.assertEqual(rootLayer.subLayerPaths, [middleLayer.identifier])
def testAttributeBlocking3dMatrixOps(self): ''' Verify authoring transformation attribute(s) in weaker layer(s) are not permitted if there exist opinion(s) in stronger layer(s) when using UsdTransform3dMatrixOp. ''' # create new stage cmds.file(new=True, force=True) # Open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # get the stage proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) proxyShapePath = proxyShapes[0] stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() # cylinder prim cylinderPrim = stage.GetPrimAtPath('/pCylinder1') self.assertIsNotNone(cylinderPrim) # create 3 sub-layers ( LayerA, LayerB, LayerC ) and set the edit target to LayerB. rootLayer = stage.GetRootLayer() subLayerC = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="SubLayerC")[0] subLayerB = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="SubLayerB")[0] subLayerA = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="SubLayerA")[0] # check to see the sublayers added addedLayers = [subLayerA, subLayerB, subLayerC] self.assertEqual(rootLayer.subLayerPaths, addedLayers) # set the edit target to LayerB cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerB) # create a xformable and give it a matrix4d xformOp:transform # This will match the UsdTransform3dMatrixOp, but not the Maya API. cylinderXformable = UsdGeom.Xformable(cylinderPrim) transformOp = cylinderXformable.AddTransformOp() xform = Gf.Matrix4d(1.0).SetTranslate(Gf.Vec3d(10, 20, 30)) transformOp.Set(xform) self.assertTrue( cylinderPrim.GetPrim().HasAttribute("xformOp:transform")) # Now that we have set up the transform stack to be 3dMatrixOp compatible, # create the Transform3d interface. cylinderPath = ufe.Path([ mayaUtils.createUfePathSegment("|mayaUsdTransform|shape"), usdUtils.createUfePathSegment("/pCylinder1") ]) cylinderItem = ufe.Hierarchy.createItem(cylinderPath) cylinderT3d = ufe.Transform3d.transform3d(cylinderItem) # select the cylinderItem sn = ufe.GlobalSelection.get() sn.clear() sn.append(cylinderItem) # move cmds.move(65, 20, 10) self.assertEqual(cylinderXformable.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:transform', ))) # validate the Matrix4d entires actual = cylinderXformable.GetLocalTransformation() expected = Gf.Matrix4d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 65, 20, 10, 1) self.assertTrue(Gf.IsClose(actual, expected, 1e-5)) # set the edit target to a weaker layer (LayerC) cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerC) # check if transform attribute is editable transformAttr = cylinderPrim.GetAttribute('xformOp:transform') self.assertIsNotNone(transformAttr) # authoring new transformation edit is not allowed. self.assertFalse(mayaUsdUfe.isAttributeEditAllowed(transformAttr)) # set the edit target to a stronger layer (LayerA) cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerA) # authoring new transformation edit is allowed. self.assertTrue(mayaUsdUfe.isAttributeEditAllowed(transformAttr))
def testAttributeBlocking3dCommonApi(self): ''' Verify authoring transformation attribute(s) in weaker layer(s) are not permitted if there exist opinion(s) in stronger layer(s) when using UsdGeomXformCommonAPI. ''' # create new stage cmds.file(new=True, force=True) # Open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # get the stage proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) proxyShapePath = proxyShapes[0] stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() # cylinder prim cylinderPrim = stage.GetPrimAtPath('/pCylinder1') self.assertIsNotNone(cylinderPrim) # create 3 sub-layers ( LayerA, LayerB, LayerC ) and set the edit target to LayerB. rootLayer = stage.GetRootLayer() subLayerC = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="SubLayerC")[0] subLayerB = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="SubLayerB")[0] subLayerA = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="SubLayerA")[0] # check to see the sublayers added addedLayers = [subLayerA, subLayerB, subLayerC] self.assertEqual(rootLayer.subLayerPaths, addedLayers) # set the edit target to LayerB cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerB) # create a xformable and give it a common API single "pivot". # This will match the common API, but not the Maya API. cylinderXformable = UsdGeom.Xformable(cylinderPrim) cylinderXformable.AddTranslateOp(UsdGeom.XformOp.PrecisionFloat, "pivot") cylinderXformable.AddTranslateOp(UsdGeom.XformOp.PrecisionFloat, "pivot", True) self.assertEqual( cylinderXformable.GetXformOpOrderAttr().Get(), Vt.TokenArray(("xformOp:translate:pivot", "!invert!xformOp:translate:pivot"))) self.assertTrue(UsdGeom.XformCommonAPI(cylinderXformable)) # Now that we have set up the transform stack to be common API-compatible, # create the Transform3d interface. cylinderPath = ufe.Path([ mayaUtils.createUfePathSegment("|mayaUsdTransform|shape"), usdUtils.createUfePathSegment("/pCylinder1") ]) cylinderItem = ufe.Hierarchy.createItem(cylinderPath) cylinderT3d = ufe.Transform3d.transform3d(cylinderItem) # select the cylinderItem sn = ufe.GlobalSelection.get() sn.clear() sn.append(cylinderItem) # rotate the cylinder cmds.rotate(0, 90, 0, relative=True, objectSpace=True, forceOrderXYZ=True) self.assertEqual( cylinderXformable.GetXformOpOrderAttr().Get(), Vt.TokenArray(("xformOp:translate:pivot", "xformOp:rotateXYZ", "!invert!xformOp:translate:pivot"))) self.assertTrue(UsdGeom.XformCommonAPI(cylinderXformable)) # set the edit target to a weaker layer (LayerC) cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerC) # check if rotate attribute is editable rotateAttr = cylinderPrim.GetAttribute('xformOp:rotateXYZ') self.assertIsNotNone(rotateAttr) # authoring new transformation edit is not allowed. self.assertFalse(mayaUsdUfe.isAttributeEditAllowed(rotateAttr)) # set the edit target to a stronger layer (LayerA) cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerA) # authoring new transformation edit is allowed. self.assertTrue(mayaUsdUfe.isAttributeEditAllowed(rotateAttr))
def testTransformationAttributeBlocking(self): '''Authoring transformation attribute(s) in weaker layer(s) are not permitted if there exist opinion(s) in stronger layer(s).''' # create new stage cmds.file(new=True, force=True) # Open usdCylinder.ma scene in testSamples mayaUtils.openCylinderScene() # get the stage proxyShapes = cmds.ls(type="mayaUsdProxyShapeBase", long=True) proxyShapePath = proxyShapes[0] stage = mayaUsd.lib.GetPrim(proxyShapePath).GetStage() # cylinder prim cylinderPrim = stage.GetPrimAtPath('/pCylinder1') self.assertIsNotNone(cylinderPrim) # create 3 sub-layers ( LayerA, LayerB, LayerC ) and set the edit target to LayerB. rootLayer = stage.GetRootLayer() subLayerC = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="SubLayerC")[0] subLayerB = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="SubLayerB")[0] subLayerA = cmds.mayaUsdLayerEditor(rootLayer.identifier, edit=True, addAnonymous="SubLayerA")[0] # check to see the sublayers added addedLayers = [subLayerA, subLayerB, subLayerC] self.assertEqual(rootLayer.subLayerPaths, addedLayers) # set the edit target to LayerB cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerB) # create a transform3d cylinderPath = ufe.Path([ mayaUtils.createUfePathSegment("|mayaUsdTransform|shape"), usdUtils.createUfePathSegment("/pCylinder1") ]) cylinderItem = ufe.Hierarchy.createItem(cylinderPath) cylinderT3d = ufe.Transform3d.transform3d(cylinderItem) # create a xformable cylinderXformable = UsdGeom.Xformable(cylinderPrim) # writing to "transform op order" is expected to be allowed. self.assertTrue( mayaUsdUfe.isAttributeEditAllowed( cylinderXformable.GetXformOpOrderAttr())) # do any transform editing. cylinderT3d = ufe.Transform3d.transform3d(cylinderItem) cylinderT3d.scale(2.5, 2.5, 2.5) cylinderT3d.translate(4.0, 2.0, 3.0) # check the "transform op order" stack. self.assertEqual(cylinderXformable.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:translate', 'xformOp:scale'))) # check if translate attribute is editable translateAttr = cylinderPrim.GetAttribute('xformOp:translate') self.assertIsNotNone(translateAttr) # authoring new transformation edit is expected to be allowed. self.assertTrue(mayaUsdUfe.isAttributeEditAllowed(translateAttr)) cylinderT3d.translate(5.0, 6.0, 7.0) self.assertEqual(translateAttr.Get(), Gf.Vec3d(5.0, 6.0, 7.0)) # set the edit target to a weaker layer (LayerC) cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerC) # authoring new transformation edit is not allowed. self.assertFalse(mayaUsdUfe.isAttributeEditAllowed(translateAttr)) # set the edit target to a stronger layer (LayerA) cmds.mayaUsdEditTarget(proxyShapePath, edit=True, editTarget=subLayerA) # authoring new transformation edit is allowed. self.assertTrue(mayaUsdUfe.isAttributeEditAllowed(translateAttr)) cylinderT3d.rotate(0.0, 90.0, 0.0) # check the "transform op order" stack. self.assertEqual( cylinderXformable.GetXformOpOrderAttr().Get(), Vt.TokenArray( ('xformOp:translate', 'xformOp:rotateXYZ', 'xformOp:scale')))