def testSkelBindPoseSparseIndices(self):
        """
        Check that if a dagPose has sparse indices on some of it's attributes,
        with differing number of created indices, that things still work.
        """
        mayaFile = os.path.join(self.inputPath, "UsdExportSkeletonTest", "UsdExportSkeletonBindPoseSparseIndices.ma")
        cmds.file(mayaFile, force=True, open=True)

        usdFile = os.path.abspath('UsdExportBindPoseSparseIndicesTest.usda')

        cmds.select('joint_grp')
        cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFile, shadingMode='none',
                           exportSkels='auto', selection=True)

        stage = Usd.Stage.Open(usdFile)

        skeleton = UsdSkel.Skeleton.Get(stage, '/joint_grp/joint1')
        self.assertEqual(skeleton.GetRestTransformsAttr().Get(),
            Vt.Matrix4dArray(
                # If we're not correlating using logical indices correctly, we may get this
                # matrix in here somehwere (which we shouldn't):
                # Gf.Matrix4d( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (777, 888, 999, 1) ),
                [Gf.Matrix4d( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 2, 1) ),
                 Gf.Matrix4d( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 3, 0, 1) ),
                 Gf.Matrix4d( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (5, 0, 0, 1) )]))
Пример #2
0
    def testReexport(self):
        cmds.mayaUSDImport(file=self._usdFile, primPath='/')

        exportedUsdFile = os.path.abspath('ExoticTypeNames.reexported.usda')
        cmds.mayaUSDExport(file=exportedUsdFile)

        stage = Usd.Stage.Open(exportedUsdFile)
        self.assertTrue(stage)

        self.assertTrue(stage.GetPrimAtPath('/A'))
        self.assertEqual(stage.GetPrimAtPath('/A').GetTypeName(), 'Xform')
        self.assertTrue(stage.GetPrimAtPath('/A/A_1'))
        self.assertEqual(stage.GetPrimAtPath('/A/A_1').GetTypeName(), '')
        self.assertTrue(stage.GetPrimAtPath('/A/A_1/A_1_I'))
        self.assertEqual(stage.GetPrimAtPath('/A/A_1/A_1_I').GetTypeName(),
                '')
        self.assertTrue(stage.GetPrimAtPath('/A/A_1/A_1_II'))
        self.assertEqual(stage.GetPrimAtPath('/A/A_1/A_1_II').GetTypeName(),
                '') # Originally Cube, but not on re-export!
        self.assertTrue(stage.GetPrimAtPath('/A/A_1/A_1_III'))
        self.assertEqual(stage.GetPrimAtPath('/A/A_1/A_1_III').GetTypeName(),
                'Scope')
        self.assertTrue(stage.GetPrimAtPath('/A/A_2'))
        self.assertEqual(stage.GetPrimAtPath('/A/A_2').GetTypeName(), 'Scope')
        self.assertTrue(stage.GetPrimAtPath('/B'))
        self.assertEqual(stage.GetPrimAtPath('/B').GetTypeName(), '')
        self.assertTrue(stage.GetPrimAtPath('/B/B_1'))
        self.assertEqual(stage.GetPrimAtPath('/B/B_1').GetTypeName(), 'Xform')
Пример #3
0
    def testExportSelfContainedPackage(self):
        """
        Tests that the exported usdz file is self contained, such that it's valid for AR QuickLook on iOS
        """

        maya_file = os.path.join(self.temp_dir, "UsdExportPackage", "asset.ma")
        cmds.file(maya_file, force=True, open=True)

        # Write the file out
        path = os.path.join(self.temp_dir,
                            'testExportSelfContainedPackage.usdz')
        cmds.mayaUSDExport(f=path, compatibility='appleArKit')

        # Check with USD what the path to the texture is
        stage = Usd.Stage.Open(path)
        prim = stage.GetPrimAtPath(
            "/AssetGroup/Looks/pxrUsdPreviewSurface1SG/file1")
        shader = UsdShade.Shader(prim)
        tex = shader.GetInput("file").Get().path

        # Check to see if the zipfile contains the texture
        with zipfile.ZipFile(path) as zf:
            for zfile in zf.filelist:
                if zfile.filename == tex:
                    break
            else:
                self.fail("Could not find texture inside zip file")
    def testSkelMissingJointFromDagPose(self):
        """
        Check that dagPoses that don't contain all desired joints issue an
        appropriate warning
        """
        mayaFile = os.path.join(self.inputPath, "UsdExportSkeletonTest", "UsdExportSkeletonBindPoseMissingJoints.ma")
        cmds.file(mayaFile, force=True, open=True)

        usdFile = os.path.abspath('UsdExportBindPoseMissingJointsTest.usda')

        joints = cmds.listRelatives('joint_grp', allDescendents=True, type='joint')
        bindMembers = cmds.dagPose('dagPose1', q=1, members=1)
        nonBindJoints = [j for j in joints if j not in bindMembers]
        self.assertEqual(nonBindJoints, [u'joint4'])

        delegate = UsdUtils.CoalescingDiagnosticDelegate()

        cmds.select('joint_grp')
        cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFile, shadingMode='none',
                           exportSkels='auto', selection=True)

        messages = delegate.TakeUncoalescedDiagnostics()
        warnings = [x.commentary for x in messages if x.diagnosticCode == Tf.TF_DIAGNOSTIC_WARNING_TYPE]
        missingJointWarnings = [x for x in warnings if 'is not a member of dagPose' in x]
        self.assertEqual(len(missingJointWarnings), 1)
        self.assertIn("Node 'joint4' is not a member of dagPose 'dagPose1'",
                      missingJointWarnings[0])
Пример #5
0
    def testExportUDIM(self):
        '''
        Tests that exporting a UDIM texture works:
        '''

        maya_file = os.path.join(self.test_dir, 'UsdExportUDIMTest.ma')
        cmds.file(maya_file, force=True, open=True)

        # Export to USD.
        usd_file = os.path.abspath('UsdExportUDIMTest.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=usd_file,
                           shadingMode='useRegistry',
                           convertMaterialsTo=['UsdPreviewSurface'],
                           materialsScopeName='Materials')

        stage = Usd.Stage.Open(usd_file)
        self.assertTrue(stage)

        shader_prim = stage.GetPrimAtPath(
            '/pPlane1/Materials/lambert2SG/file1')
        self.assertTrue(shader_prim)

        shader = UsdShade.Shader(shader_prim)
        shader_id = shader.GetIdAttr().Get()
        self.assertEqual(shader_id, 'UsdUVTexture')
        filename = shader.GetInput("file")
        self.assertTrue("<UDIM>" in filename.Get().path)
Пример #6
0
    def testExportStaticSingleSampleOn(self):
        for state in (True, False):
            # Set up the scene in here to prevent having to maintain a Maya file
            cmds.file(new=True, force=True)
            root = cmds.group(empty=True, name="root")
            cube, _ = cmds.polyCube(name="Cube")
            joint = cmds.joint()
            cmds.parent(cube, joint, root)
            cmds.skinCluster(joint, cube)


            cmds.setKeyframe(joint, v=0, at='translateY', time=1)
            cmds.setKeyframe(root, v=0, at='translateY', time=1)
            cmds.setKeyframe(joint, v=0, at='translateY', time=10)

            # Okay now do the export
            path = os.path.join(self.temp_dir, "staticSingleFrame{}.usda".format("On" if state else "Off"))

            cmds.mayaUSDExport(f=path, exportSkels="auto", frameRange=(1, 10), sss=state)

            stage = Usd.Stage.Open(path)

            # Check to see if the flag is working
            prim = stage.GetPrimAtPath("/root")
            attr = prim.GetAttribute("xformOp:translate")
            num_samples = attr.GetNumTimeSamples()
            self.assertEqual(num_samples, int(not state))
    def testBindTransformExport(self):
        temp_export_file = os.path.join(self.temp_dir, 'test_output.usda')
        cmds.select('a', r=True)
        cmds.mayaUSDExport(v=True,
                           sl=True,
                           f=temp_export_file,
                           skl='auto',
                           skn='auto',
                           defaultMeshScheme='catmullClark')

        stage = Usd.Stage.Open(temp_export_file)
        prim = stage.GetPrimAtPath('/a/b/c')
        bindTransforms = prim.GetAttribute('bindTransforms').Get()
        bindTransform = bindTransforms[
            3]  # NOTE: (yliangsiew) The 4th joint is the rt_joint that we're interested in.
        self.assertNotEqual(
            bindTransform,
            Gf.Matrix4d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1))

        self.assertEqual(
            bindTransform,
            Gf.Matrix4d(-0.002290224357008666, -0.0056947280722030105,
                        0.9999807051930374, 0.0, 0.01567493647243696,
                        0.9998602653154095, 0.005729941968379492, 0.0,
                        -0.9998745177471474, 0.01568775712160303,
                        -0.0022006397844859227, 0.0, -4.625417221923634,
                        16.113398996722644, 5.401075137997586, 1.0))
Пример #8
0
    def testSidedness(self):
        for sidedness in ('single', 'double', 'derived'):
            for doubleSided in (False, True):
                output = os.path.join(
                    self.temp_dir,
                    'sidedness_{}_{}.usda'.format(sidedness, doubleSided))
                cmds.file(new=True, force=True)

                xform, _ = cmds.polyCube()
                shape = cmds.listRelatives(xform)[0]

                cmds.setAttr("{}.doubleSided".format(shape), doubleSided)
                cmds.mayaUSDExport(file=output,
                                   selection=True,
                                   geomSidedness=sidedness)

                stage = Usd.Stage.Open(output)
                prim = stage.GetPrimAtPath("/pCube1")

                value = UsdGeom.Mesh(prim).GetDoubleSidedAttr().Get()
                if sidedness == 'derived':
                    self.assertEqual(value, doubleSided,
                                     "Incorrect derived sidedness value")
                elif sidedness == 'single':
                    self.assertFalse(value, "Incorrect single sidedness value")
                elif sidedness == 'double':
                    self.assertTrue(value, "Incorrect double sidedness value")
Пример #9
0
    def testRotateScalePivotCompensationAfterExport(self):
        '''Rotate and scale pivots must match after export.'''

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

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

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

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

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

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

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

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

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

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

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

        checkPivotsAndCompensations(self, "pSphere1", usdSphereT3d)

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

        checkPivotsAndCompensations(self, "pSphere1", usdSphereT3d)
Пример #10
0
    def testExportWithSelection(self):

        mayaFilePath = os.path.join(self.inputPath,
                                    "UsdExportSelectionHierarchy",
                                    "UsdExportSelectionHierarchy.ma")
        cmds.file(mayaFilePath, force=True, open=True)

        selectionInput = [
            '|pSphere1|pSphere3|pSphere9|pSphere19',
            '|pSphere1|pSphere3|pSphere7', '|pSphere1|pSphere3|pSphere9',
            '|pSphere1|pSphere2|pSphere4|pSphereShape4', '|pSphere1|pSphere2',
            '|pSphere1|pSphere3|pSphereShape3'
        ]

        cmds.select(selectionInput, af=True)

        selectionResult = cmds.ls(long=True, sl=True)

        # Want to make sure the order is maintatined
        self.assertTrue(selectionResult == selectionInput)

        usdFilePath = os.path.abspath(
            'UsdExportSelectionHierarchy_EXPORTED.usda')
        cmds.mayaUSDExport(selection=True,
                           file=usdFilePath,
                           shadingMode='none')

        stage = Usd.Stage.Open(usdFilePath)
        self.assertTrue(stage)

        expectedExportedPrims = [
            '/pSphere1',
            '/pSphere1/pSphere2',
            '/pSphere1/pSphere2/pSphereShape2',
            '/pSphere1/pSphere2/pSphere4',
            '/pSphere1/pSphere2/pSphere5',
            '/pSphere1/pSphere2/pSphere6',
            '/pSphere1/pSphere2/pSphere4/pSphere10',
            '/pSphere1/pSphere2/pSphere4/pSphere11',
            '/pSphere1/pSphere2/pSphere4/pSphere12',
            '/pSphere1/pSphere2/pSphere4/pSphere13',
            '/pSphere1/pSphere2/pSphere4/pSphere14',
            '/pSphere1/pSphere2/pSphere4/pSphere15',
        ]

        expectedNonExportedPrims = [
            '/pSphere1/pSphereShape1',
            '/pSphere1/pSphere3/pSphere8',
        ]

        for primPath in expectedExportedPrims:
            prim = stage.GetPrimAtPath(primPath)
            self.assertTrue(prim.IsValid())

        for primPath in expectedNonExportedPrims:
            prim = stage.GetPrimAtPath(primPath)
            self.assertFalse(prim.IsValid())
Пример #11
0
    def testExportStandaloneUsdPreviewSurface(self):
        """
        Tests that a usdPreviewSurface with attribute values but no
        connections authored exports correctly.
        """
        expectedInputTuples = [
            ("clearcoat", 0.1),
            ("clearcoatRoughness", 0.2),
            ("diffuseColor", Gf.Vec3f(0.3, 0.4, 0.5)),
            ("displacement", 0.6),
            ("emissiveColor", Gf.Vec3f(0.07, 0.08, 0.09)),
            ("ior", 1.1),
            ("metallic", 0.11),
            ("normal", Gf.Vec3f(0.12, 0.13, 0.14)),
            ("occlusion", 0.9),
            ("opacity", 0.8),
            ("roughness", 0.7),
            ("specularColor", Gf.Vec3f(0.3, 0.2, 0.1)),
            ("useSpecularWorkflow", 1),
        ]
        maya_file = self.generateStandaloneTestScene(expectedInputTuples)
        cmds.file(maya_file, force=True, open=True)
        usd_file_path = os.path.join(self.temp_dir,
                                     "UsdPreviewSurfaceExportTest.usda")
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=usd_file_path,
                           shadingMode="useRegistry")

        stage = Usd.Stage.Open(usd_file_path)

        standaloneMaterial = self._GetUsdMaterial(
            stage, "usdPreviewSurface_StandaloneSG")

        surfaceOutput = standaloneMaterial.GetOutput(UsdShade.Tokens.surface)
        previewSurfaceShader = self._GetSourceShader(surfaceOutput)

        expectedShaderPrimPath = standaloneMaterial.GetPath().AppendChild(
            "usdPreviewSurface_Standalone")

        self.assertEqual(previewSurfaceShader.GetPath(),
                         expectedShaderPrimPath)

        self.assertEqual(previewSurfaceShader.GetShaderId(),
                         "UsdPreviewSurface")

        expectedOutputs = {
            "surface": Sdf.ValueTypeNames.Token,
            "displacement": Sdf.ValueTypeNames.Token,
        }

        self._ValidateUsdShader(previewSurfaceShader, expectedInputTuples,
                                expectedOutputs)

        # There should not be any additional inputs.
        self.assertEqual(len(previewSurfaceShader.GetInputs()),
                         len(expectedInputTuples))
Пример #12
0
    def testUsdExportFileFormat_cmd_usda(self):
        name = 'ascii.usd'
        usdFile = os.path.abspath(name)

        args = ()
        kwargs = {'file': usdFile, 'defaultUSDFormat': 'usda'}
        cmds.mayaUSDExport(*args, **kwargs)

        layer = Sdf.Layer.FindOrOpen(usdFile)
        format = self.GetUnderlyingUsdFileFormat(layer)
        self.assertEqual(format, 'usda')
    def setUpClass(cls):
        cls.temp_dir = fixturesUtils.setUpClass(__file__)
        cls.maya_file = os.path.join(cls.temp_dir, "UsdExportUVTransforms",
                                     "UsdExportUVTransforms.ma")
        cmds.file(cls.maya_file, force=True, open=True)

        usd_file_path = os.path.join(cls.temp_dir,
                                     "UsdExportUVTransforms.usda")
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=usd_file_path,
                           shadingMode='useRegistry')

        cls.stage = Usd.Stage.Open(usd_file_path)
Пример #14
0
    def testExportJobContextConflicts(self):
        """Testing that merging incompatible contexts generates errors"""
        mark = Tf.Error.Mark()
        mark.SetMark()
        self.assertTrue(mark.IsClean())

        cmds.polySphere(r=1)
        usdFilePath = os.path.abspath('UsdExportSchemaApiTestBasic.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=usdFilePath,
                           jobContext=["Larry", "Curly", "Moe"])

        self.assertFalse(mark.IsClean())

        errors = mark.GetErrors()
        messages = set()
        for e in errors:
            messages.add(e.commentary)

        expected = set([
            "Arguments for job context 'Larry' can not include extra contexts.",
            "Context 'Curly' and context 'Larry' do not agree on type of argument 'apiSchema'.",
            "Context 'Moe' and context 'Larry' do not agree on argument 'geomSidedness'."
        ])
        self.assertEqual(messages, expected)

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

        mark = Tf.Error.Mark()
        mark.SetMark()
        self.assertTrue(mark.IsClean())

        cmds.polySphere(r=1)
        usdFilePath = os.path.abspath('UsdExportSchemaApiTestBasic.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=usdFilePath,
                           jobContext=["NullAPI", "Moe"])

        self.assertFalse(mark.IsClean())

        errors = mark.GetErrors()
        messages = set()
        for e in errors:
            messages.add(e.commentary)

        expected = set(
            ["Missing implementation for NullAPIChaser::ExportDefault"])
        self.assertEqual(messages, expected)

        cmds.file(f=True, new=True)
    def setUpClass(cls):
        inputPath = fixturesUtils.setUpClass(__file__)

        mayaFile = os.path.join(inputPath, 'UsdExportRfMShadersTest',
            'MarbleCube.ma')
        cmds.file(mayaFile, force=True, open=True)

        # Export to USD.
        usdFilePath = os.path.abspath('MarbleCube.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFilePath,
            shadingMode='useRegistry', convertMaterialsTo='rendermanForMaya',
            materialsScopeName='Materials')

        cls._stage = Usd.Stage.Open(usdFilePath)
    def setUpClass(cls):
        inputPath = fixturesUtils.setUpClass(__file__)

        mayaFile = os.path.join(inputPath, 'UsdExportDisplacementTest',
            'SimpleDisplacement.ma')
        cmds.file(mayaFile, force=True, open=True)

        # Export to USD.
        usdFilePath = os.path.abspath('SimpleDisplacement.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFilePath,
            shadingMode='useRegistry', convertMaterialsTo=['UsdPreviewSurface'],
            materialsScopeName='Materials')

        cls._stage = Usd.Stage.Open(usdFilePath)
Пример #17
0
    def testSkelForSegfault(self):
        """
        Certain skeletons cause heap corruption and segfaulting when exported multiple times.
        Because this can happen anywhere from the first to last time, we run this test multiple times.
        """
        mayaFile = os.path.join(self.inputPath, "UsdExportSkeletonTest", "UsdExportSkeletonSegfaultTest.ma")
        cmds.file(mayaFile, force=True, open=True)

        usdFile = os.path.abspath('UsdExportSkeletonSegfaultTest.usda')
        cmds.select('skinned_mesh')

        # Run 5 times because the crash only happens every few runs.
        for _ in range(5):
            cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFile,
                         shadingMode='none', exportSkels='auto', selection=True)
    def testImagingShapeDoesNotExport(self):
        """
        Tests that the USD exported from a scene that uses the
        pxrHdImagingShape does *not* include any prims for the
        pxrHdImagingShape itself.

        The pxrHdImagingShape and its parent transform are set so that they do
        not write to the Maya scene file and are not exported to USD.
        """
        usdFilePath = os.path.abspath('ProxyShapeBaseExportTest.usda')
        cmds.mayaUSDExport(file=usdFilePath)

        usdStage = Usd.Stage.Open(usdFilePath)
        prim = usdStage.GetPrimAtPath('/HdImaging')
        self.assertFalse(prim)
        prim = usdStage.GetPrimAtPath('/HdImaging/HdImagingShape')
        self.assertFalse(prim)
    def setUpClass(cls):
        inputPath = fixturesUtils.setUpClass(__file__)

        mayaSceneFilePath = os.path.join(inputPath,
            'UsdExportUserTaggedAttributesTest', 'UserTaggedAttributesTest.ma')

        cmds.file(mayaSceneFilePath, open=True, force=True)

        usdFilePathFormat = 'UserTaggedAttributesTest_EXPORTED_%s.usda'
        
        cls._mergedUsdFilePath = os.path.abspath(usdFilePathFormat % 'MERGED')
        cls._unmergedUsdFilePath = os.path.abspath(usdFilePathFormat % 'UNMERGED')

        cmds.mayaUSDExport(file=cls._mergedUsdFilePath,
            mergeTransformAndShape=True)
        cmds.mayaUSDExport(file=cls._unmergedUsdFilePath,
            mergeTransformAndShape=False)
    def testMeshNextToProxyShapeAndImported(self):
        """
        Tests the colors between a mesh with (0.55, 0.55, 0.55)
        exporting that file and then re-importing it, and also referencing
        it back into the same scene through a proxy shape.

        While this is a bit more than just "GL" testing, it's a useful place to
        centralize all this.  If we don't like that this is testing usdImport
        functionality, we can remove

        This will render as follows:


        blank    |  usdImport
                 |
        ---------+-----------
        modeled  |  ref'd
                 |

        """
        x = self._PlaneWithColor((0.55, 0.55, 0.55))
        cmds.select(x)
        usdFile = os.path.join(self._testDir, 'plane.usd')
        cmds.mayaUSDExport(file=usdFile,
                           selection=True,
                           shadingMode='none',
                           exportDisplayColor=True)
        proxyShape = cmds.createNode('mayaUsdProxyShape', name='usdProxyShape')
        proxyTransform = cmds.listRelatives(proxyShape,
                                            parent=True,
                                            fullPath=True)[0]
        cmds.xform(proxyTransform, translation=(30.48, 0, 0))
        cmds.setAttr('%s.filePath' % proxyShape, usdFile, type='string')
        cmds.setAttr('%s.primPath' % proxyShape, '/pPlane1', type='string')

        x = cmds.mayaUSDImport(file=usdFile)
        cmds.xform(x, translation=(30.48, 30.48, 0))

        cmds.setAttr("hardwareRenderingGlobals.floatingPointRTEnable", 0)
        cmds.setAttr('defaultColorMgtGlobals.outputTransformEnabled', 0)
        self._Snapshot('default')
        cmds.setAttr("hardwareRenderingGlobals.floatingPointRTEnable", 1)
        cmds.setAttr('defaultColorMgtGlobals.outputTransformEnabled', 1)
        self._Snapshot('colorMgt')
    def testSkelRestXformsWithNoDagPose(self):
        """
        Tests export of rest xforms when there is no dagPose node at all.
        """
        mayaFile = os.path.join(self.inputPath, "UsdExportSkeletonTest",
            "UsdExportSkeletonNoDagPose.ma")
        cmds.file(mayaFile, force=True, open=True)

        usdFile = os.path.abspath('UsdExportSkeletonRestXformsWithNoDagPose.usda')
        cmds.select('skel_root')
        cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFile,
                           shadingMode='none', exportSkels='auto', selection=True)

        stage = Usd.Stage.Open(usdFile)

        skeleton = UsdSkel.Skeleton.Get(stage, '/skel_root/joint1')

        self.assertEqual(skeleton.GetJointsAttr().Get(),
            Vt.TokenArray(['joint1',
                           'joint1/joint2',
                           'joint1/joint2/joint3',
                           'joint1/joint2/joint3/joint4']))

        self.assertEqual(
            skeleton.GetBindTransformsAttr().Get(),
            Vt.Matrix4dArray([
                Gf.Matrix4d( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, -1, 0), (0, 0, 0, 1) ),
                Gf.Matrix4d( (0, -1, 0, 0), (-1, 0, 0, 0), (0, 0, -1, 0), (3, 0, 0, 1) ),
                Gf.Matrix4d( (0, -1, 0, 0), (0, 0, -1, 0), (1, 0, 0, 0), (3, 0, -2, 1) ),
                Gf.Matrix4d( (0, -1, 0, 0), (1, 0, 0, 0), (0, 0, 1, 0), (3, 0, -4, 1) ),
            ])
        )

        self.assertEqual(
            skeleton.GetRestTransformsAttr().Get(),
            Vt.Matrix4dArray([
                Gf.Matrix4d( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, -1, 0), (0, 0, 0, 1) ),
                Gf.Matrix4d( (0, -1, 0, 0), (1, 0, 0, 0), (0, 0, 1, 0), (-3, 0, 0, 1) ),
                Gf.Matrix4d( (1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0), (0, 0, 2, 1) ),
                Gf.Matrix4d( (1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0), (0, 2, 0, 1) ),
            ])
        )        
    def setUpClass(cls):
        suffix = ""
        if mayaUsdLib.WriteUtil.WriteMap1AsST():
            suffix += "ST"

        inputPath = fixturesUtils.setUpClass(__file__, suffix)

        mayaFile = os.path.join(inputPath, 'UsdExportUVSetMappingsTest',
                                'UsdExportUVSetMappingsTest.ma')
        cmds.file(mayaFile, force=True, open=True)

        # Export to USD.
        usdFilePath = os.path.abspath('UsdExportUVSetMappingsTest.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=usdFilePath,
                           shadingMode='useRegistry',
                           convertMaterialsTo='UsdPreviewSurface',
                           materialsScopeName='Materials')

        cls._stage = Usd.Stage.Open(usdFilePath)
Пример #23
0
    def test_fps(self):
        fps_map = {
            "ntsc": 30,
            "game": 15,
            "film": 24,
            "pal": 25,
            "show": 48,
            "palf": 50,
            "ntscf": 60
        }

        for name, fps in fps_map.items():
            cmds.currentUnit(time=name)
            temp_file = os.path.join(self.temp_dir,
                                     'test_{}.usda'.format(name))
            cmds.mayaUSDExport(f=temp_file, frameRange=(1, 5))

            stage = Usd.Stage.Open(temp_file)
            self.assertEqual(stage.GetTimeCodesPerSecond(), fps)
            self.assertEqual(stage.GetFramesPerSecond(), fps)
Пример #24
0
    def testExportAnimatedCompundValue(self):
        """MayaUSD Issue #1712: Test that animated custom compound attributes
           on a mesh are exported."""
        cmds.file(new=True, force=True)
        cubeShape = "MyCubeShape"
        cmds.polyCube(name="MyCube")
        cmds.addAttr(cubeShape, sn="tf2", ln="TestFloatTwo", at="float2")
        cmds.addAttr(cubeShape, sn="tf2u", ln="TestFloatTwoU", at="float", p="TestFloatTwo")
        cmds.addAttr(cubeShape, sn="tf2v", ln="TestFloatTwoV", at="float", p="TestFloatTwo")
        cmds.setAttr(cubeShape + ".TestFloatTwoU", e=True, keyable=True)
        cmds.setAttr(cubeShape + ".TestFloatTwoV", e=True, keyable=True)
        cmds.setKeyframe(cubeShape, attribute="tf2")
        cmds.currentTime(10)
        cmds.setAttr(cubeShape + ".TestFloatTwoU", 20.0)
        cmds.setAttr(cubeShape + ".TestFloatTwoV", 40.0)
        cmds.setKeyframe(cubeShape, attribute="tf2")
        cmds.addAttr(cubeShape, ci=True, sn="USD_UserExportedAttributesJson", ln="USD_UserExportedAttributesJson", dt="string")
        cmds.setAttr(cubeShape + ".USD_UserExportedAttributesJson", '{"TestFloatTwo": {}}', type="string")

        # Exporting with a time range results in time samples:
        path = os.path.join(self.temp_dir, "animatedCompoundValue.usda")
        cmds.mayaUSDExport(f=path, exportSkels="auto", frameRange=(1, 10), sss=True)

        stage = Usd.Stage.Open(path)

        prim = stage.GetPrimAtPath("/MyCube")
        attr = prim.GetAttribute("userProperties:TestFloatTwo")
        self.assertGreater(attr.GetNumTimeSamples(), 1)

        # Exporting without time range results in a single authored value:
        path = os.path.join(self.temp_dir, "animatedCompoundValueStatic.usda")
        cmds.mayaUSDExport(f=path)

        stage = Usd.Stage.Open(path)

        prim = stage.GetPrimAtPath("/MyCube")
        attr = prim.GetAttribute("userProperties:TestFloatTwo")
        self.assertEqual(attr.GetNumTimeSamples(), 0)
        # Make sure value is there because previous code did not write any:
        self.assertEqual(attr.Get(), [20.0, 40.0])
Пример #25
0
    def testPythonCustomShaderExporter(self):
        '''
        Add a custom exporter to the mix and see if it can export a compositing node.
        '''
        cmds.file(f=True, new=True)

        # Register our new exporter:
        mayaUsdLib.ShaderWriter.Register(mxCompositeExportTest, "colorComposite")

        mayaFile = os.path.join(self._inputPath, 'UsdExportMaterialXTest',
            'MaterialX_decal.ma')
        cmds.file(mayaFile, force=True, open=True)

        # Export to USD.
        usdFilePath = os.path.abspath('MaterialX_decal.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFilePath,
            shadingMode='useRegistry', convertMaterialsTo=['MaterialX'],
            materialsScopeName='Materials')

        stage = Usd.Stage.Open(usdFilePath)
        self.assertTrue(stage)

        # We should have a nice colorComposite1 node in the graph curtesy of the custom exporter:
        prim = stage.GetPrimAtPath("/pPlane1/Materials/standardSurface2SG/MayaNG_standardSurface2SG/colorComposite1")
        self.assertTrue(prim)
        shader = UsdShade.Shader(prim)
        self.assertTrue(shader)
        self.assertEqual(shader.GetIdAttr().Get(), "ND_mix_color3")
        input = shader.GetInput("fg")
        self.assertEqual(input.Get(), (1,1,0))
        input = shader.GetInput("bg")
        cnxTuple = input.GetConnectedSource()
        self.assertTrue(cnxTuple)
        self.assertEqual(cnxTuple[0].GetPrim().GetName(), "file1")
        input = shader.GetInput("mix")
        cnxTuple = input.GetConnectedSource()
        self.assertTrue(cnxTuple)
        self.assertEqual(cnxTuple[0].GetPrim().GetName(), "MayaSwizzle_file2_a")
        self.assertTrue("MaterialX" in mxCompositeExportTest._AllMaterialConversions)
    def _StartTest(self, testName):
        cmds.file(force=True, new=True)
        mayaUtils.loadPlugin("mayaUsdPlugin")

        self._testName = testName
        testFile = testUtils.getTestScene("displayColors",
                                          self._testName + ".ma")

        cmds.file(testFile, o=True)

        exportedFile = os.path.join(self._testDir, "ColorTest.usda")
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=exportedFile,
                           shadingMode='none',
                           exportDisplayColor=True)

        shapeNode = mayaUtils.createProxyFromFile(exportedFile)[0]
        cmds.move(0, 0, -1, shapeNode)

        globalSelection = ufe.GlobalSelection.get()
        globalSelection.clear()
        self.assertSnapshotClose('%s_unselected.png' % self._testName)
Пример #27
0
    def testComponentTags(self):
        """
        Test that component tags can round-trip through USD.
        """
        geo = cmds.polySphere(sx=6, sy=6)[0]
        geo_name = geo
        geo = geo_utils.extendToShape(geo)
        ctag_utils.createTag(geo, 'top', ['f[18:23]', 'f[30:35]'])
        ctag_utils.createTag(geo, 'bottom', ['f[0:5]', 'f[24:29]'])

        usdFilePath = os.path.join(os.environ.get('MAYA_APP_DIR'),
                                   'testComponentTags.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=usdFilePath,
                           shadingMode='none')

        cmds.file(new=True, force=True)
        rootPaths = cmds.mayaUSDImport(v=True, f=usdFilePath)
        self.assertEqual(len(rootPaths), 1)

        indices = cmds.getAttr('{0}.componentTags'.format(geo_name),
                               multiIndices=True) or []
        self.assertEqual(len(indices), 2)
Пример #28
0
    def testBlendShapesExport(self):
        # NOTE: (yliangsiew) Basic blendshape export test.
        om.MFileIO.newFile(True)
        parent = cmds.group(name="root", empty=True)
        base, _ = cmds.polyCube(name="base")
        cmds.parent(base, parent)
        target, _ = cmds.polyCube(name="blend")
        cmds.parent(target, parent)
        cmds.polyMoveVertex('{}.vtx[0:2]'.format(target), s=(1.0, 1.5, 1.0))

        cmds.blendShape(target, base, automatic=True)

        cmds.select(base, replace=True)
        temp_file = os.path.join(self.temp_dir, 'blendshape.usda')
        cmds.mayaUSDExport(f=temp_file, v=True, sl=True, ebs=True, skl="auto")

        stage = Usd.Stage.Open(temp_file)
        prim = stage.GetPrimAtPath("/root/base/blendShape")
        offsets = prim.GetAttribute("offsets").Get()

        for i, coords in enumerate(offsets):
            coords = list(coords)  # convert from GfVec3
            self.assertEqual(coords, [0, -0.25 if i < 2 else 0.25, 0])

        """
        Sample BlendShape prim:

        def BlendShape "blendShape"
        {
            uniform vector3f[] normalOffsets = [(0, 0, 0), (0, 0, 0), (0, 0, 0)]
            uniform vector3f[] offsets = [(0, -0.25, 0), (0, -0.25, 0), (0, 0.25, 0)]
            uniform int[] pointIndices = [0, 1, 2]
        }
        """

        # NOTE: (yliangsiew) Test simple inbetween setup.
        om.MFileIO.open(self.scene_path, None, True)
        cmds.select("basic_cube_2_inbetweens_no_anim|base", r=True)
        cmds.mayaUSDExport(f=temp_file, v=True, sl=True, ebs=True, skl="auto", skn="auto")
        stage = Usd.Stage.Open(temp_file)
        prim = stage.GetPrimAtPath("/basic_cube_2_inbetweens_no_anim/base/pCube2")
        blendShape = UsdSkel.BlendShape(prim)
        inbetweens = blendShape.GetInbetweens()
        self.assertEqual(len(inbetweens), 2)  # NOTE: (yliangsiew) This particular setup has two additional inbetweens.

        # NOTE: (yliangsiew) Test simple multiple targets setup.
        om.MFileIO.open(self.scene_path, None, True)
        cmds.select("basic_cube_4_blendshapes_no_anim|base", r=True)
        cmds.mayaUSDExport(f=temp_file, v=True, sl=True, ebs=True, skl="auto", skn="auto")
        stage = Usd.Stage.Open(temp_file)
        prim = stage.GetPrimAtPath("/basic_cube_4_blendshapes_no_anim/base")
        blendShapes = prim.GetChildren()
        for bs in blendShapes:
            self.assertEqual(bs.GetTypeName(), 'BlendShape')
Пример #29
0
    def testComplexAdaptation(self):
        """Test that we can adapt a bullet simulation"""

        mayaUsdLib.SchemaApiAdaptor.Register(TestBulletMassShemaAdaptor,
                                             "shape", "PhysicsMassAPI")
        mayaUsdLib.SchemaApiAdaptor.Register(TestBulletRigidBodyShemaAdaptor,
                                             "shape", "PhysicsRigidBodyAPI")

        # Build a scene (and exercise the adaptor in a freeform context)
        cmds.file(f=True, new=True)

        s1T = cmds.polySphere()[0]
        cmds.loadPlugin("bullet")
        if not BulletUtils.checkPluginLoaded():
            return

        rbT, rbShape = RigidBody.CreateRigidBody().command(
            autoFit=True,
            colliderShapeType=RigidBody.eShapeType.kColliderSphere,
            meshes=[s1T],
            radius=1.0,
            mass=5.0,
            centerOfMass=(0.9, 0.8, 0.7))

        # See if the plugin adaptor can read the bullet shape under the mesh:
        sl = om.MSelectionList()
        sl.add(s1T)
        dagPath = sl.getDagPath(0)
        dagPath.extendToShape()

        adaptor = mayaUsdLib.Adaptor(dagPath.fullPathName())
        self.assertEqual(adaptor.GetUsdType(),
                         Tf.Type.FindByName('UsdGeomMesh'))
        # NOTICE: PhysicsRigidBodyAPI is not in the list because that API is
        # supported only on export!!!
        self.assertEqual(adaptor.GetAppliedSchemas(), ['PhysicsMassAPI'])
        physicsMass = adaptor.GetSchemaByName("PhysicsMassAPI")
        self.assertEqual(physicsMass.GetName(), "PhysicsMassAPI")
        massAttributes = set([
            'physics:centerOfMass', 'physics:density',
            'physics:diagonalInertia', 'physics:mass', 'physics:principalAxes'
        ])
        self.assertEqual(set(physicsMass.GetAttributeNames()), massAttributes)
        bulletAttributes = set(['physics:centerOfMass', 'physics:mass'])
        self.assertEqual(set(physicsMass.GetAuthoredAttributeNames()),
                         bulletAttributes)
        bulletMass = physicsMass.GetAttribute('physics:mass')
        self.assertAlmostEqual(bulletMass.Get(), 5.0)
        bulletMass.Set(12.0)

        bulletCenter = physicsMass.GetAttribute('physics:centerOfMass')
        bulletCenter.Set(Gf.Vec3f(3, 4, 5))

        sl = om.MSelectionList()
        sl.add(s1T)
        bulletPath = sl.getDagPath(0)
        bulletPath.extendToShape(1)
        massDepFn = om.MFnDependencyNode(bulletPath.node())
        plug = om.MPlug(bulletPath.node(), massDepFn.attribute("mass"))
        self.assertAlmostEqual(plug.asFloat(), 12.0)

        # Create an untranslated attribute:
        usdDensity = physicsMass.CreateAttribute('physics:density')
        usdDensity.Set(33.0)
        self.assertAlmostEqual(usdDensity.Get(), 33.0)

        # This will result in a dynamic attribute on the bulletShape:
        plug = massDepFn.findPlug("USD_ATTR_physics_density", True)
        self.assertAlmostEqual(plug.asFloat(), 33.0)
        bulletAttributes.add('physics:density')
        self.assertEqual(set(physicsMass.GetAuthoredAttributeNames()),
                         bulletAttributes)

        physicsMass.RemoveAttribute('physics:density')
        bulletAttributes.remove('physics:density')
        self.assertEqual(set(physicsMass.GetAuthoredAttributeNames()),
                         bulletAttributes)

        # Add some animation:
        cmds.setKeyframe(bulletPath, at="mass", t=0, v=3.0)
        cmds.setKeyframe(bulletPath, at="mass", t=10, v=30.0)

        # Modify the velocity so it can be exported to the RBD Physics schema.
        cmds.setKeyframe(bulletPath, at="initialVelocityX", t=0, v=5.0)
        cmds.setKeyframe(bulletPath, at="initialVelocityX", t=10, v=50.0)
        cmds.setKeyframe(bulletPath, at="initialVelocityY", t=0, v=6.0)
        cmds.setKeyframe(bulletPath, at="initialVelocityY", t=10, v=60.0)
        cmds.setKeyframe(bulletPath, at="initialVelocityZ", t=0, v=7.0)
        cmds.setKeyframe(bulletPath, at="initialVelocityZ", t=10, v=70.0)

        # Try applying the schema on a new sphere:
        s2T = cmds.polySphere()[0]
        sl.add(s2T)
        dagPath = sl.getDagPath(1)
        dagPath.extendToShape()
        adaptor = UsdMaya.Adaptor(dagPath.fullPathName())
        physicsMass = adaptor.ApplySchemaByName("PhysicsMassAPI")
        self.assertEqual(physicsMass.GetName(), "PhysicsMassAPI")
        self.assertEqual(adaptor.GetUsdType(),
                         Tf.Type.FindByName('UsdGeomMesh'))
        self.assertEqual(adaptor.GetAppliedSchemas(), ['PhysicsMassAPI'])

        usdDensity = physicsMass.CreateAttribute('physics:density')
        usdDensity.Set(33.0)

        # Export, but without enabling Bullet:
        usdFilePath = os.path.abspath('UsdExportSchemaApiTest_NoBullet.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFilePath)

        # Check that there are no Physics API schemas exported:
        stage = Usd.Stage.Open(usdFilePath)
        for i in (1, 2):
            spherePrim = stage.GetPrimAtPath(
                '/pSphere{0}/pSphereShape{0}'.format(i))
            self.assertFalse(
                "PhysicsMassAPI" in spherePrim.GetAppliedSchemas())

        schemasToExport = ["PhysicsMassAPI", "PhysicsRigidBodyAPI"]
        # Export, with Bullet:
        usdFilePath = os.path.abspath('UsdExportSchemaApiTest_WithBullet.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=usdFilePath,
                           apiSchema=schemasToExport,
                           frameRange=(1, 10))

        # Check that Physics API schemas did get exported:
        stage = Usd.Stage.Open(usdFilePath)
        values = [
            ("physics:centerOfMass", (Gf.Vec3f(3, 4, 5), Gf.Vec3f(0, 0, 0))),
            ("physics:mass", (3.0, 1.0)),
            ("physics:density", (None, 33.0)),
        ]
        for i in (1, 2):
            spherePrim = stage.GetPrimAtPath(
                '/pSphere{0}/pSphereShape{0}'.format(i))
            self.assertTrue("PhysicsMassAPI" in spherePrim.GetAppliedSchemas())
            for n, v in values:
                if v[i - 1]:
                    a = spherePrim.GetAttribute(n)
                    self.assertEqual(a.Get(), v[i - 1])
            if i == 1:
                # Is mass animated?
                a = spherePrim.GetAttribute("physics:mass")
                self.assertEqual(a.Get(10), 30)
            # This got exported even though invisible in interactive:
            self.assertTrue(
                "PhysicsRigidBodyAPI" in spherePrim.GetAppliedSchemas())
            a = spherePrim.GetAttribute("physics:velocity")
            if i == 1:
                self.assertEqual(a.Get(0), (5, 6, 7))
                self.assertEqual(a.Get(10), (50, 60, 70))
                numberOfExportedKeys = len(a.GetTimeSamples())

        # Try unapplying the schema:
        adaptor.UnapplySchemaByName("PhysicsMassAPI")
        self.assertEqual(adaptor.GetAppliedSchemas(), [])

        # Test import of USDPhysics without job context:
        cmds.file(new=True, force=True)
        cmds.mayaUSDImport(f=usdFilePath)

        sl = om.MSelectionList()
        # pSphereShape1 is a transform, since the bullet shape prevented merging the mesh and the
        # transform. The shape will be pSphereShape1Shape...
        sl.add("pSphereShape1")
        bulletPath = sl.getDagPath(0)
        # No bullet shape since we did not put Bullet as jobContext
        self.assertEqual(bulletPath.numberOfShapesDirectlyBelow(), 1)

        cmds.file(new=True, force=True)
        cmds.mayaUSDImport(f=usdFilePath,
                           apiSchema=schemasToExport,
                           readAnimData=True)

        sl = om.MSelectionList()
        sl.add("pSphereShape1")
        bulletPath = sl.getDagPath(0)
        # Finds bullet shape since we did put Bullet as jobContext

        self.assertEqual(bulletPath.numberOfShapesDirectlyBelow(), 2)

        # The bullet shape has animated mass and initial velocity since we read the animation.
        bulletPath.extendToShape(1)
        massDepFn = om.MFnDependencyNode(bulletPath.node())
        for attrName in ("mass", "initialVelocityX", "initialVelocityY",
                         "initialVelocityZ"):
            plug = om.MPlug(bulletPath.node(), massDepFn.attribute(attrName))
            self.assertTrue(plug.isConnected)
            fcurve = oma.MFnAnimCurve(plug.source().node())
            self.assertEqual(fcurve.numKeys, numberOfExportedKeys)
Пример #30
0
    def testSimpleShaderWriter(self):
        mayaUsdLib.ShaderWriter.Register(shaderWriterTest, "lambert")

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

        sphere_xform = cmds.polySphere()[0]

        # Need a lambert, with something connected to exercise the
        # full API. The code will survive the test writer not even
        # creating a UsdShade node for the lambert.
        material_node = cmds.shadingNode("lambert",
                                         asShader=True,
                                         name="Lanbert42")

        material_sg = cmds.sets(renderable=True,
                                noSurfaceShader=True,
                                empty=True,
                                name=material_node + "SG")
        cmds.connectAttr(material_node + ".outColor",
                         material_sg + ".surfaceShader",
                         force=True)
        cmds.sets(sphere_xform, e=True, forceElement=material_sg)

        file_node = cmds.shadingNode("file",
                                     asTexture=True,
                                     isColorManaged=True)
        uv_node = cmds.shadingNode("place2dTexture", asUtility=True)

        for att_name in (".coverage", ".translateFrame", ".rotateFrame",
                         ".mirrorU", ".mirrorV", ".stagger", ".wrapU",
                         ".wrapV", ".repeatUV", ".offset", ".rotateUV",
                         ".noiseUV", ".vertexUvOne", ".vertexUvTwo",
                         ".vertexUvThree", ".vertexCameraOne"):
            cmds.connectAttr(uv_node + att_name, file_node + att_name, f=True)
        cmds.connectAttr(uv_node + ".outUV", file_node + ".uvCoord", f=True)
        cmds.connectAttr(uv_node + ".outUvFilterSize",
                         file_node + ".uvFilterSize",
                         f=True)

        cmds.connectAttr(file_node + ".outColor",
                         material_node + ".color",
                         f=True)

        cmds.setAttr(file_node + ".fileTextureName",
                     "unknown.png",
                     type="string")

        # Export to USD. We select MaterialX because all the writer
        # there are reporting "Fallback", which allows our CanExport
        # to always win with "Supported" (also helps that the current
        # version of the MaterialX export does not support lambert).
        usdFilePath = os.path.join(self.temp_dir, 'testShaderWriter.usda')
        cmds.mayaUSDExport(mergeTransformAndShape=True,
                           file=usdFilePath,
                           shadingMode='useRegistry',
                           convertMaterialsTo=['MaterialX'],
                           materialsScopeName='Materials')

        self.assertTrue(shaderWriterTest.CanExportCalled)
        self.assertEqual(shaderWriterTest.WriteCalledCount, 1)
        self.assertTrue(
            shaderWriterTest.GetShadingAttributeForMayaAttrNameCalled)
        self.assertEqual(
            shaderWriterTest.GetShadingAttributeNameForMayaAttrNameCalledWith,
            'color')
        self.assertFalse(shaderWriterTest.NotCalled)