def testAttributeAliases(self): """Tests behavior with the purpose/USD_purpose alias.""" cmds.file(new=True, force=True) cmds.group(name="group1", empty=True) cmds.addAttr("group1", longName="USD_purpose", dataType="string") cmds.setAttr("group1.USD_purpose", "proxy", type="string") self.assertEqual( UsdMaya.Adaptor("group1").GetSchema(UsdGeom.Xform).GetAttribute( UsdGeom.Tokens.purpose).Get(), UsdGeom.Tokens.proxy) cmds.addAttr("group1", longName="USD_ATTR_purpose", dataType="string") cmds.setAttr("group1.USD_ATTR_purpose", "render", type="string") self.assertEqual( UsdMaya.Adaptor("group1").GetSchema(UsdGeom.Xform).GetAttribute( UsdGeom.Tokens.purpose).Get(), UsdGeom.Tokens.render) cmds.deleteAttr("group1.USD_purpose") self.assertEqual( UsdMaya.Adaptor("group1").GetSchema(UsdGeom.Xform).GetAttribute( UsdGeom.Tokens.purpose).Get(), UsdGeom.Tokens.render) cmds.deleteAttr("group1.USD_ATTR_purpose") self.assertIsNone( UsdMaya.Adaptor("group1").GetSchema(UsdGeom.Xform).GetAttribute( UsdGeom.Tokens.purpose).Get()) UsdMaya.Adaptor("group1")\ .GetSchema(UsdGeom.Xform)\ .CreateAttribute(UsdGeom.Tokens.purpose) self.assertTrue( cmds.attributeQuery("USD_ATTR_purpose", node="group1", exists=True))
def testAttributes(self): """Tests creating and removing schema attributes.""" cmds.file(new=True, force=True) cmds.group(name="group1", empty=True) modelAPI = UsdMaya.Adaptor('group1').ApplySchema(UsdGeom.ModelAPI) xform = UsdMaya.Adaptor('group1').GetSchema(UsdGeom.Xform) # Schema attributes list versus authored attributes list. self.assertIn(UsdGeom.Tokens.modelCardTextureXPos, modelAPI.GetAttributeNames()) self.assertNotIn(UsdGeom.Tokens.modelCardTextureXPos, modelAPI.GetAuthoredAttributeNames()) self.assertIn(UsdGeom.Tokens.purpose, xform.GetAttributeNames()) self.assertNotIn(UsdGeom.Tokens.purpose, xform.GetAuthoredAttributeNames()) # Unauthored API attribute. self.assertFalse( modelAPI.GetAttribute(UsdGeom.Tokens.modelCardTextureXPos)) # Unauthored schema attribute. self.assertFalse( xform.GetAttribute(UsdGeom.Tokens.purpose)) # Non-existent attribute. with self.assertRaises(Tf.ErrorException): modelAPI.GetAttribute("fakeAttr") # Create and set an API attribute. attr = modelAPI.CreateAttribute(UsdGeom.Tokens.modelCardTextureXPos) self.assertTrue(attr) self.assertTrue(attr.Set(Sdf.AssetPath("example.png"))) attr = modelAPI.GetAttribute(UsdGeom.Tokens.modelCardTextureXPos) self.assertTrue(attr) self.assertEqual(attr.Get(), Sdf.AssetPath("example.png")) self.assertEqual(attr.GetAttributeDefinition().name, "model:cardTextureXPos") self.assertEqual(modelAPI.GetAuthoredAttributeNames(), [UsdGeom.Tokens.modelCardTextureXPos]) # Existing attrs become invalid when the plug is removed. modelAPI.RemoveAttribute(UsdGeom.Tokens.modelCardTextureXPos) self.assertFalse(attr) # Should return None on invalid attr access. self.assertIsNone(attr.Get()) # Create a typed schema attribute. It should be set to the fallback # initially. self.assertEqual(xform.CreateAttribute(UsdGeom.Tokens.purpose).Get(), UsdGeom.Tokens.default_)
def testConcreteSchemaRegistrations(self): """Tests some of the PXRUSDMAYA_REGISTER_ADAPTOR_SCHEMA macros.""" cmds.file(new=True, force=True) cmds.createNode("joint", name="TestJoint") self.assertTrue( UsdMaya.Adaptor("TestJoint").GetSchema(UsdSkel.Skeleton)) self.assertFalse(UsdMaya.Adaptor("TestJoint").GetSchema(UsdGeom.Mesh)) cmds.createNode("camera", name="TestCamera") self.assertTrue( UsdMaya.Adaptor("TestCamera").GetSchema(UsdGeom.Camera)) cmds.createNode("mesh", name="TestMesh") self.assertTrue(UsdMaya.Adaptor("TestMesh").GetSchema(UsdGeom.Mesh)) cmds.createNode("instancer", name="TestInstancer") self.assertTrue( UsdMaya.Adaptor("TestInstancer").GetSchema(UsdGeom.PointInstancer)) cmds.createNode("nurbsSurface", name="TestNurbsSurface") self.assertTrue( UsdMaya.Adaptor("TestNurbsSurface").GetSchema(UsdGeom.NurbsPatch)) cmds.createNode("nurbsCurve", name="TestNurbsCurve") self.assertTrue( UsdMaya.Adaptor("TestNurbsCurve").GetSchema(UsdGeom.NurbsCurves)) cmds.createNode("locator", name="TestLocator") self.assertTrue( UsdMaya.Adaptor("TestLocator").GetSchema(UsdGeom.Xform)) cmds.createNode("nParticle", name="TestParticles") self.assertTrue( UsdMaya.Adaptor("TestParticles").GetSchema(UsdGeom.Points))
def testImport_GeomModelAPI(self): """Tests importing UsdGeomModelAPI attributes.""" cmds.file(new=True, force=True) usdFile = os.path.abspath('UsdAttrs.usda') cmds.usdImport(file=usdFile, shadingMode='none', apiSchema=['GeomModelAPI']) worldProxy = UsdMaya.Adaptor('World') modelAPI = worldProxy.GetSchema(UsdGeom.ModelAPI) # model:cardGeometry self.assertTrue( cmds.attributeQuery('USD_ATTR_model_cardGeometry', node='World', exists=True)) self.assertEqual(cmds.getAttr('World.USD_ATTR_model_cardGeometry'), UsdGeom.Tokens.fromTexture) self.assertEqual( modelAPI.GetAttribute(UsdGeom.Tokens.modelCardGeometry).Get(), UsdGeom.Tokens.fromTexture) # model:cardTextureXPos self.assertTrue( cmds.attributeQuery('USD_ATTR_model_cardTextureXPos', node='World', exists=True)) self.assertEqual(cmds.getAttr('World.USD_ATTR_model_cardTextureXPos'), 'right.png') self.assertEqual( modelAPI.GetAttribute(UsdGeom.Tokens.modelCardTextureXPos).Get(), 'right.png')
def testUnapplySchema(self): """Tests unapplying schemas and effect on existing proxy objects.""" cmds.file(new=True, force=True) cmds.group(name="group1", empty=True) proxy = UsdMaya.Adaptor('group1') self.assertEqual(proxy.GetAppliedSchemas(), []) proxy.ApplySchema(UsdGeom.ModelAPI) proxy.ApplySchema(UsdGeom.MotionAPI) self.assertEqual(proxy.GetAppliedSchemas(), ["GeomModelAPI", "MotionAPI"]) proxy.UnapplySchema(UsdGeom.ModelAPI) self.assertEqual(proxy.GetAppliedSchemas(), ["MotionAPI"]) # Note that schema objects still remain alive after being # unapplied. modelAPI = proxy.GetSchema(UsdGeom.ModelAPI) self.assertTrue(modelAPI) # But they expire once the underlying Maya node is removed. cmds.delete("group1") self.assertFalse(modelAPI) self.assertFalse(proxy)
def testApplySchema(self): """Tests schema application.""" cmds.file(new=True, force=True) cmds.group(name="group1", empty=True) proxy = UsdMaya.Adaptor('group1') self.assertTrue(proxy) self.assertEqual(proxy.GetAppliedSchemas(), []) modelAPI = proxy.ApplySchema(UsdGeom.ModelAPI) self.assertTrue(modelAPI) self.assertEqual(proxy.GetAppliedSchemas(), ["GeomModelAPI"]) self.assertEqual(modelAPI.GetAuthoredAttributeNames(), []) motionAPI = proxy.ApplySchema(UsdGeom.MotionAPI) self.assertTrue(motionAPI) self.assertEqual(proxy.GetAppliedSchemas(), ["GeomModelAPI", "MotionAPI"]) self.assertEqual(motionAPI.GetAuthoredAttributeNames(), []) # No support currently for typed schemas. with self.assertRaises(Tf.ErrorException): proxy.ApplySchema(UsdGeom.Xformable) with self.assertRaises(Tf.ErrorException): proxy.ApplySchema(UsdGeom.Mesh) self.assertEqual(proxy.GetAppliedSchemas(), ["GeomModelAPI", "MotionAPI"])
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)
def testMetadata(self): """Tests setting and clearing metadata.""" cmds.file(new=True, force=True) cmds.group(name="group1", empty=True) proxy = UsdMaya.Adaptor('group1') self.assertEqual(proxy.GetAllAuthoredMetadata(), {}) self.assertIsNone(proxy.GetMetadata("instanceable")) proxy.SetMetadata("instanceable", True) self.assertEqual(proxy.GetMetadata("instanceable"), True) proxy.SetMetadata("kind", "awesomeKind") self.assertEqual(proxy.GetAllAuthoredMetadata(), { "instanceable": True, "kind": "awesomeKind" }) # Unregistered key. with self.assertRaises(Tf.ErrorException): proxy.SetMetadata("fakeMetadata", True) with self.assertRaises(Tf.ErrorException): proxy.GetMetadata("otherFakeMetadata") proxy.ApplySchema(UsdGeom.ModelAPI) apiSchemas = proxy.GetMetadata("apiSchemas") self.assertEqual(apiSchemas.prependedItems, ["GeomModelAPI"]) # Clear metadata. proxy.ClearMetadata("kind") self.assertIsNone(proxy.GetMetadata("kind"))
def testGetSchema(self): """Tests getting schemas from the proxy.""" cmds.file(new=True, force=True) cmds.group(name="group1", empty=True) proxy = UsdMaya.Adaptor('group1') self.assertTrue(proxy.GetSchema(UsdGeom.ModelAPI)) self.assertTrue(proxy.GetSchema(UsdGeom.Xform)) # Wrong schemas should be invalid. Currently, exact schema match is # required (i.e. if Xform is compatible, Xformable isn't). self.assertFalse(proxy.GetSchema(UsdGeom.Mesh)) # We can't currently get prim definitions from the schema registry for # typed non-concrete schemas, so we can't expect them to work with # GetSchema/GetSchemaByName. self.assertFalse(proxy.GetSchema(UsdGeom.Xformable))
def testImportSubdiv(self): mesh = 'SubdivMeshShape' self.assertTrue(cmds.objExists(mesh)) schema = UsdMaya.Adaptor(mesh).GetSchema(UsdGeom.Mesh) subdivisionScheme = \ schema.GetAttribute(UsdGeom.Tokens.subdivisionScheme).Get() self.assertIsNone(subdivisionScheme) faceVaryingLinearInterpolation = schema.GetAttribute( UsdGeom.Tokens.faceVaryingLinearInterpolation).Get() self.assertEqual(faceVaryingLinearInterpolation, UsdGeom.Tokens.all) interpolateBoundary = schema.GetAttribute( UsdGeom.Tokens.interpolateBoundary).Get() self.assertEqual(interpolateBoundary, UsdGeom.Tokens.edgeOnly) self.assertFalse( cmds.attributeQuery("USD_EmitNormals", node=mesh, exists=True))
def testImportPoly(self): mesh = 'PolyMeshShape' self.assertTrue(cmds.objExists(mesh)) schema = UsdMaya.Adaptor(mesh).GetSchema(UsdGeom.Mesh) subdivisionScheme = schema.GetAttribute( UsdGeom.Tokens.subdivisionScheme).Get() self.assertEqual(subdivisionScheme, UsdGeom.Tokens.none) faceVaryingLinearInterpolation = schema.GetAttribute( UsdGeom.Tokens.faceVaryingLinearInterpolation).Get() self.assertIsNone(faceVaryingLinearInterpolation) # not authored interpolateBoundary = schema.GetAttribute( UsdGeom.Tokens.interpolateBoundary).Get() self.assertEqual(interpolateBoundary, UsdGeom.Tokens.none) self.assertTrue( cmds.attributeQuery("USD_EmitNormals", node=mesh, exists=True))
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)