def testMergeToUsdToNonRootTargetInSessionLayer(self): '''Merge edits on a USD transform back to USD targeting a non-root destination path that does not exists in the destination layer.''' # To merge back to USD, we must edit as Maya first. (ps, aXlateOp, _, aUsdUfePathStr, aUsdUfePath, aUsdItem, bXlateOp, _, bUsdUfePathStr, bUsdUfePath, bUsdItem) = \ createSimpleXformScene() with mayaUsd.lib.OpUndoItemList(): self.assertTrue( mayaUsd.lib.PrimUpdaterManager.editAsMaya(bUsdUfePathStr)) bMayaItem = ufe.GlobalSelection.get().front() (bMayaPath, bMayaPathStr, _, bMayaMatrix) = \ setMayaTranslation(bMayaItem, om.MVector(10, 11, 12)) psHier = ufe.Hierarchy.hierarchy(ps) # Merge edits back to USD. with mayaUsd.lib.OpUndoItemList(): stage = mayaUsd.ufe.getStage(bUsdUfePathStr) stage.SetEditTarget(stage.GetSessionLayer()) self.assertTrue( mayaUsd.lib.PrimUpdaterManager.mergeToUsd(bMayaPathStr)) # Check that edits have been preserved in USD. bUsdMatrix = bXlateOp.GetOpTransform( mayaUsd.ufe.getTime(bUsdUfePathStr)) mayaValues = [v for v in bMayaMatrix] usdValues = [v for row in bUsdMatrix for v in row] assertVectorAlmostEqual(self, mayaValues, usdValues)
def testDuplicateAsMaya(self): '''Duplicate a USD transform hierarchy to Maya.''' (_, _, aXlation, aUsdUfePathStr, aUsdUfePath, _, _, bXlation, bUsdUfePathStr, bUsdUfePath, _) = \ createSimpleXformScene() # Duplicate USD data as Maya data, placing it under the root. with mayaUsd.lib.OpUndoItemList(): self.assertTrue(mayaUsd.lib.PrimUpdaterManager.duplicate( aUsdUfePathStr, '|world')) # Should now have two transform nodes in the Maya scene: the path # components in the second segment of the aUsdItem and bUsdItem will # now be under the Maya world. aMayaPathStr = str(aUsdUfePath.segments[1]).replace('/', '|') bMayaPathStr = str(bUsdUfePath.segments[1]).replace('/', '|') self.assertEqual(cmds.ls(aMayaPathStr, long=True)[0], aMayaPathStr) self.assertEqual(cmds.ls(bMayaPathStr, long=True)[0], bMayaPathStr) # Translation should have been copied over to the Maya data model. self.assertEqual(cmds.getAttr(aMayaPathStr + '.translate')[0], aXlation) self.assertEqual(cmds.getAttr(bMayaPathStr + '.translate')[0], bXlation)
def testSimplePrimUpdater(self): mayaUsdLib.PrimUpdater.Register( primUpdaterTest, "UsdGeomXform", "transform", primUpdaterTest.Supports.All.value ) # primUpdaterTest.Supports.Push.value + primUpdaterTest.Supports.Clear.value + primUpdaterTest.Supports.AutoPull.value) # Edit as Maya first time. (ps, xlateOp, usdXlation, aUsdUfePathStr, aUsdUfePath, aUsdItem, _, _, _, _, _) = createSimpleXformScene() with mayaUsdLib.OpUndoItemList(): self.assertTrue( mayaUsdLib.PrimUpdaterManager.editAsMaya(aUsdUfePathStr)) aMayaItem = ufe.GlobalSelection.get().front() (aMayaPath, aMayaPathStr, _, aMayaMatrix) = setMayaTranslation(aMayaItem, om.MVector(4, 5, 6)) # Discard Maya edits. with mayaUsdLib.OpUndoItemList(): self.assertTrue( mayaUsdLib.PrimUpdaterManager.discardEdits(aMayaPathStr)) cmds.file(new=True, force=True) # Edit as Maya second time. (ps, xlateOp, usdXlation, aUsdUfePathStr, aUsdUfePath, aUsdItem, _, _, _, _, _) = createSimpleXformScene() with mayaUsdLib.OpUndoItemList(): self.assertTrue( mayaUsdLib.PrimUpdaterManager.editAsMaya(aUsdUfePathStr)) aMayaItem = ufe.GlobalSelection.get().front() (aMayaPath, aMayaPathStr, _, aMayaMatrix) = setMayaTranslation(aMayaItem, om.MVector(4, 5, 6)) # Merge edits back to USD. with mayaUsdLib.OpUndoItemList(): self.assertTrue( mayaUsdLib.PrimUpdaterManager.mergeToUsd(aMayaPathStr)) self.assertTrue(primUpdaterTest.editAsMayaCalled) self.assertTrue(primUpdaterTest.discardEditsCalled) self.assertTrue(primUpdaterTest.pushCopySpecsCalled) self.assertTrue(primUpdaterTest.pushEndCalled)
def testTransformEditAsMaya(self): '''Edit a USD transform as a Maya object.''' (ps, xlateOp, xlation, aUsdUfePathStr, aUsdUfePath, aUsdItem, _, _, _, _, _) = createSimpleXformScene() # Edit aPrim as Maya data. with mayaUsd.lib.OpUndoItemList(): self.assertTrue( mayaUsd.lib.PrimUpdaterManager.canEditAsMaya(aUsdUfePathStr)) self.assertTrue( mayaUsd.lib.PrimUpdaterManager.editAsMaya(aUsdUfePathStr)) # Test the path mapping services. # # Unfortunately, toHost is unimplemented as of 20-Sep-2021. Use the # selection to retrieve the Maya object. # # usdToMaya = ufe.PathMappingHandler.pathMappingHandler(aUsdItem) # aMayaUfePath = usdToMaya.toHost(aUsdUfePath) # self.assertEqual(aMayaUfePath.nbSegments(), 1) aMayaItem = ufe.GlobalSelection.get().front() aMayaPath = aMayaItem.path() self.assertEqual(aMayaPath.nbSegments(), 1) mayaToUsd = ufe.PathMappingHandler.pathMappingHandler(aMayaItem) self.assertEqual(mayaToUsd.fromHost(aMayaPath), aUsdUfePath) # Confirm the hierarchy is preserved through the Hierarchy interface: # one child, the parent of the pulled item is the proxy shape, and # the proxy shape has the pulled item as a child, not the original USD # scene item. aMayaHier = ufe.Hierarchy.hierarchy(aMayaItem) self.assertEqual(len(aMayaHier.children()), 1) self.assertEqual(ps, aMayaHier.parent()) psHier = ufe.Hierarchy.hierarchy(ps) self.assertIn(aMayaItem, psHier.children()) self.assertNotIn(aUsdItem, psHier.children()) # Confirm the translation has been transferred, and that the local # transformation is only a translation. aDagPath = om.MSelectionList().add( ufe.PathString.string(aMayaPath)).getDagPath(0) aFn = om.MFnTransform(aDagPath) self.assertEqual(aFn.translation(om.MSpace.kObject), om.MVector(*xlation)) mayaMatrix = aFn.transformation().asMatrix() usdMatrix = xlateOp.GetOpTransform(mayaUsd.ufe.getTime(aUsdUfePathStr)) mayaValues = [v for v in mayaMatrix] usdValues = [v for row in usdMatrix for v in row] assertVectorAlmostEqual(self, mayaValues, usdValues)
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()
def testDiscardEdits(self): '''Discard edits on a USD transform.''' # Edit as Maya first. (ps, xlateOp, usdXlation, aUsdUfePathStr, aUsdUfePath, aUsdItem, _, _, _, _, _) = createSimpleXformScene() with mayaUsd.lib.OpUndoItemList(): self.assertTrue( mayaUsd.lib.PrimUpdaterManager.editAsMaya(aUsdUfePathStr)) aMayaItem = ufe.GlobalSelection.get().front() mayaXlation = om.MVector(4, 5, 6) (aMayaPath, aMayaPathStr, aFn, mayaMatrix) = \ setMayaTranslation(aMayaItem, mayaXlation) self.assertEqual(aFn.translation(om.MSpace.kObject), mayaXlation) mayaToUsd = ufe.PathMappingHandler.pathMappingHandler(aMayaItem) self.assertEqual(mayaToUsd.fromHost(aMayaPath), aUsdUfePath) psHier = ufe.Hierarchy.hierarchy(ps) self.assertNotIn(aUsdItem, psHier.children()) self.assertIn(aMayaItem, psHier.children()) # Discard Maya edits. with mayaUsd.lib.OpUndoItemList(): self.assertTrue( mayaUsd.lib.PrimUpdaterManager.discardEdits(aMayaPathStr)) # Original USD translation values are preserved. usdMatrix = xlateOp.GetOpTransform(mayaUsd.ufe.getTime(aUsdUfePathStr)) self.assertEqual(usdMatrix.ExtractTranslation(), usdXlation) # There no longer is a path mapping from the Maya path to the USD path. self.assertEqual(len(mayaToUsd.fromHost(aMayaPath)), 0) # Hierarchy is restored: USD item is child of proxy shape, Maya item is # not. Be careful to use the Maya path rather than the Maya item, which # should no longer exist. self.assertIn(aUsdItem, psHier.children()) self.assertNotIn(aMayaPath, [child.path() for child in psHier.children()]) # Maya node is removed. with self.assertRaises(RuntimeError): om.MSelectionList().add(aMayaPathStr)
def testDuplicateAsMayaUndoRedo(self): '''Duplicate a USD transform hierarchy to Maya and then undo and redo the command.''' (_, _, aXlation, aUsdUfePathStr, aUsdUfePath, _, _, bXlation, bUsdUfePathStr, bUsdUfePath, _) = \ createSimpleXformScene() # Duplicate USD data as Maya data, placing it under the root. cmds.mayaUsdDuplicate(aUsdUfePathStr, '|world') def verifyDuplicate(): # Should now have two transform nodes in the Maya scene: the path # components in the second segment of the aUsdItem and bUsdItem will # now be under the Maya world. aMayaPathStr = str(aUsdUfePath.segments[1]).replace('/', '|') bMayaPathStr = str(bUsdUfePath.segments[1]).replace('/', '|') self.assertEqual(cmds.ls(aMayaPathStr, long=True)[0], aMayaPathStr) self.assertEqual(cmds.ls(bMayaPathStr, long=True)[0], bMayaPathStr) # Translation should have been copied over to the Maya data model. self.assertEqual(cmds.getAttr(aMayaPathStr + '.translate')[0], aXlation) self.assertEqual(cmds.getAttr(bMayaPathStr + '.translate')[0], bXlation) verifyDuplicate() cmds.undo() def verifyDuplicateIsGone(): bMayaPathStr = str(bUsdUfePath.segments[1]).replace('/', '|') self.assertListEqual(cmds.ls(bMayaPathStr, long=True), []) verifyDuplicateIsGone() cmds.redo() verifyDuplicate()
def testEditAsMayaUndoRedo(self): '''Edit a USD transform as a Maya object and apply undo and redo.''' (ps, xlateOp, xlation, aUsdUfePathStr, aUsdUfePath, aUsdItem, _, _, _, _, _) = createSimpleXformScene() # Edit aPrim as Maya data. self.assertTrue( mayaUsd.lib.PrimUpdaterManager.canEditAsMaya(aUsdUfePathStr)) cmds.mayaUsdEditAsMaya(aUsdUfePathStr) def getMayaPathStr(): aMayaItem = ufe.GlobalSelection.get().front() aMayaPath = aMayaItem.path() aMayaPathStr = ufe.PathString.string(aMayaPath) return aMayaPathStr aMayaPathStr = getMayaPathStr() def verifyEditedScene(): aMayaItem = ufe.GlobalSelection.get().front() aMayaPath = aMayaItem.path() aMayaPathStr = ufe.PathString.string(aMayaPath) # Confirm the hierarchy is preserved through the Hierarchy interface: # one child, the parent of the pulled item is the proxy shape, and # the proxy shape has the pulled item as a child, not the original USD # scene item. aMayaHier = ufe.Hierarchy.hierarchy(aMayaItem) self.assertEqual(len(aMayaHier.children()), 1) self.assertEqual(ps, aMayaHier.parent()) psHier = ufe.Hierarchy.hierarchy(ps) self.assertIn(aMayaItem, psHier.children()) self.assertNotIn(aUsdItem, psHier.children()) # Confirm the translation has been transferred, and that the local # transformation is only a translation. aDagPath = om.MSelectionList().add( ufe.PathString.string(aMayaPath)).getDagPath(0) aFn = om.MFnTransform(aDagPath) self.assertEqual(aFn.translation(om.MSpace.kObject), om.MVector(*xlation)) mayaMatrix = aFn.transformation().asMatrix() usdMatrix = xlateOp.GetOpTransform( mayaUsd.ufe.getTime(aUsdUfePathStr)) mayaValues = [v for v in mayaMatrix] usdValues = [v for row in usdMatrix for v in row] assertVectorAlmostEqual(self, mayaValues, usdValues) verifyEditedScene() # Undo cmds.undo() def verifyNoLongerEdited(): # Maya node is removed. with self.assertRaises(RuntimeError): om.MSelectionList().add(aMayaPathStr) verifyNoLongerEdited() # Redo cmds.redo() verifyEditedScene()
def testTransformMergeToUsd(self): '''Merge edits on a USD transform back to USD.''' # To merge back to USD, we must edit as Maya first. (ps, aXlateOp, _, aUsdUfePathStr, aUsdUfePath, aUsdItem, bXlateOp, _, bUsdUfePathStr, bUsdUfePath, bUsdItem) = \ createSimpleXformScene() with mayaUsd.lib.OpUndoItemList(): self.assertTrue( mayaUsd.lib.PrimUpdaterManager.editAsMaya(aUsdUfePathStr)) aMayaItem = ufe.GlobalSelection.get().front() (aMayaPath, aMayaPathStr, _, aMayaMatrix) = \ setMayaTranslation(aMayaItem, om.MVector(4, 5, 6)) bMayaPathStr = aMayaPathStr + '|B' bMayaPath = ufe.PathString.path(bMayaPathStr) bMayaItem = ufe.Hierarchy.createItem(bMayaPath) (_, _, _, bMayaMatrix) = \ setMayaTranslation(bMayaItem, om.MVector(10, 11, 12)) # There should be a path mapping for the edit as Maya hierarchy. for (mayaItem, mayaPath, usdUfePath) in \ zip([aMayaItem, bMayaItem], [aMayaPath, bMayaPath], [aUsdUfePath, bUsdUfePath]): mayaToUsd = ufe.PathMappingHandler.pathMappingHandler(mayaItem) self.assertEqual(mayaToUsd.fromHost(mayaPath), usdUfePath) psHier = ufe.Hierarchy.hierarchy(ps) # Merge edits back to USD. with mayaUsd.lib.OpUndoItemList(): self.assertTrue( mayaUsd.lib.PrimUpdaterManager.mergeToUsd(aMayaPathStr)) # Edit will re-allocate anything that was under pulled prim due to deactivation # Grab new references for /A/B prim bUsdPrim = mayaUsd.ufe.ufePathToPrim(bUsdUfePathStr) bXlateOp = UsdGeom.Xformable(bUsdPrim).GetOrderedXformOps()[0] # Check that edits have been preserved in USD. for (usdUfePathStr, mayaMatrix, xlateOp) in \ zip([aUsdUfePathStr, bUsdUfePathStr], [aMayaMatrix, bMayaMatrix], [aXlateOp, bXlateOp]): usdMatrix = xlateOp.GetOpTransform( mayaUsd.ufe.getTime(usdUfePathStr)) mayaValues = [v for v in mayaMatrix] usdValues = [v for row in usdMatrix for v in row] assertVectorAlmostEqual(self, mayaValues, usdValues) # There no longer are any Maya to USD path mappings. for mayaPath in [aMayaPath, bMayaPath]: self.assertEqual(len(mayaToUsd.fromHost(mayaPath)), 0) # Hierarchy is restored: USD item is child of proxy shape, Maya item is # not. Be careful to use the Maya path rather than the Maya item, which # should no longer exist. self.assertIn(aUsdItem, psHier.children()) self.assertNotIn(aMayaPath, [child.path() for child in psHier.children()]) # Maya nodes are removed. for mayaPathStr in [aMayaPathStr, bMayaPathStr]: with self.assertRaises(RuntimeError): om.MSelectionList().add(mayaPathStr)