def test_OffsetsAuthoring(self): for fmt in allFormats: # Create a simple structure one rootLayer with one subLayer, a prim # 'Foo' in the rootLayer that references 'Bar' defined in refLayer. # Then we assign a layer offset to the reference and to the sublayer, # and we test authoring a time sample into the reference via an # EditTarget, as well as to the subLayer. In both cases we check that # the time value was correctly transformed. rootLayer = Sdf.Layer.CreateAnonymous('root.'+fmt) subLayer = Sdf.Layer.CreateAnonymous('sub.'+fmt) refLayer = Sdf.Layer.CreateAnonymous('ref.'+fmt) # add subLayer to rootLayer and give it a layer offset. subOffset = Sdf.LayerOffset(scale=3.0, offset=4.0) rootLayer.subLayerPaths.append(subLayer.identifier) rootLayer.subLayerOffsets[0] = subOffset # add Foo root prim. fooRoot = Sdf.PrimSpec(rootLayer, 'Foo', Sdf.SpecifierDef) # add Bar target prim in refLayer. barRef = Sdf.PrimSpec(refLayer, 'Bar', Sdf.SpecifierDef) # make Foo reference Bar. refOffset = Sdf.LayerOffset(scale=2.0, offset=1.0) fooRoot.referenceList.Add(Sdf.Reference(refLayer.identifier, barRef.path, refOffset)) # Create a UsdStage, get 'Foo'. stage = Usd.Stage.Open(rootLayer) foo = stage.GetPrimAtPath('/Foo') # Make an EditTarget to author into the referenced Bar. editTarget = Usd.EditTarget(refLayer, foo.GetPrimIndex().rootNode.children[0]) with Usd.EditContext(stage, editTarget): attr = foo.CreateAttribute('attr', Sdf.ValueTypeNames.Double) attr.Set(1.0, time=2.0) self.assertEqual(attr.Get(time=2.0), 1.0, ( 'expected value 1.0 at time=2.0, got %s' % attr.Get(time=2.0))) # Check that the time value in the reference is correctly # transformed. authoredTime = barRef.attributes[ 'attr'].GetInfo('timeSamples').keys()[0] self.assertEqual(refOffset.GetInverse() * 2.0, authoredTime) # Make an EditTarget to author into the sublayer. editTarget = stage.GetEditTargetForLocalLayer(subLayer) with Usd.EditContext(stage, editTarget): attr = foo.GetAttribute('attr') attr.Set(1.0, time=2.0) self.assertEqual(attr.Get(time=2.0), 1.0, ( 'expected value 1.0 at time=2.0, got %s' % attr.Get(time=2.0))) # Check that the time value in the sublayer is correctly # transformed. authoredTime = subLayer.GetAttributeAtPath( '/Foo.attr').GetInfo('timeSamples').keys()[0] self.assertEqual(subOffset.GetInverse() * 2.0, authoredTime)
def test_StageEditTargetSessionSublayer(self): usdFile = 'testSessionSublayerEditTarget.usda' stage = Usd.Stage.Open(usdFile) assert stage, 'failed to create stage for @%s@' % usdFile sessionLayer = stage.GetSessionLayer() assert len(sessionLayer.subLayerPaths) == 0 # Create a new anonymous layer and make it a sublayer of the sessionLayer. sessionSublayer = Sdf.Layer.CreateAnonymous() sessionLayer.subLayerPaths.append(sessionSublayer.identifier) assert len(sessionLayer.subLayerPaths) == 1 def _CreateAndTestPrimAttribute(stage, primPath, attrName): prim = stage.GetPrimAtPath(primPath) attr = prim.CreateAttribute(attrName, Sdf.ValueTypeNames.String) assert attr attr.Set('foo') assert attr.Get() == 'foo' # Test creating attributes with the sessionSublayer as the edit target. with Usd.EditContext(stage, sessionSublayer): assert stage.GetEditTarget() == sessionSublayer primPath = '/LocalModel/MyPrim' attrName = 'LocalModelSessionSublayerStringAttr' _CreateAndTestPrimAttribute(stage, primPath, attrName) primPath = '/ReferencedModel/MyPrim' attrName = 'ReferencedModelSessionSublayerStringAttr' _CreateAndTestPrimAttribute(stage, primPath, attrName)
def main(): """Run the main execution of the current script.""" inner_stage = _make_target() main_stage = Usd.Stage.CreateInMemory() # XXX : In order to use `inner_stage` in an EditContext, it must be # in `main_stage`'s local LayerStack (e.g. it must be a sublayer) # main_stage.GetRootLayer().subLayerPaths.append( inner_stage.GetRootLayer().identifier) print(main_stage.GetRootLayer().ExportToString()) print('Inner stage before context') print(inner_stage.GetRootLayer().ExportToString()) with Usd.EditContext(main_stage, inner_stage.GetRootLayer()): sphere = UsdGeom.Sphere(main_stage.GetPrimAtPath("/root/sphere")) sphere.GetRadiusAttr().Set(10) print('Inner stage after context') print(inner_stage.GetRootLayer().ExportToString()) main_stage.SetEditTarget(Usd.EditTarget(inner_stage.GetRootLayer())) sphere = UsdGeom.Sphere(main_stage.GetPrimAtPath("/root/sphere")) sphere.GetRadiusAttr().Set(5) print('Inner stage after setting') print(inner_stage.GetRootLayer().ExportToString())
def _testReloadReopen(appController): from pxr import Usd, UsdGeom # # Frame the front sphere, and color it red # appController._dataModel.selection.setPrimPath("/frontSphere") stage = appController._dataModel.stage sphere = UsdGeom.Sphere(stage.GetPrimAtPath("/frontSphere")) with Usd.EditContext(stage, stage.GetRootLayer()): sphere.CreateDisplayColorAttr([(1, 0, 0)]) _emitFrameAction(appController) # Finally, clear selection so the red really shows appController._dataModel.selection.clear() _takeShot(appController, "coloredAndFramed.png") # # Reloading should set the sphere back to gray (because we authored into # its root layer), but otherwise not change the view # _emitReload_All_LayersAction(appController) _takeShot(appController, "reloaded.png") # # Reopening the stage should completely reset the view # _emitReopen_StageAction(appController) _takeShot(appController, "reopened.png")
def _create_camera(viewer, path, as_session=False): """Make a new camera in the user's current USD stage, using the current viewer camera. Args: viewer (:class:`pxr.Usdviewq.usdviewApi.UsdviewApi`): The usdview controller. If has references to both the current stage and the user's current view camera. path (str or :usd:`SdfPath`): The Prim path to create a camera at. as_session (bool, optional): If False, add the camera to the stage's current edit target. If True, add it to the stage's session Layer instead. Default is False. """ @contextlib.contextmanager def _null_context(): # Do nothing try: yield finally: pass path = Sdf.Path(path) path = path.GetPrimPath( ) # Remove any property information, if there is any. context = _null_context() if as_session: context = Usd.EditContext(viewer.stage, viewer.stage.GetSessionLayer()) with context: api = UsdGeom.Camera.Define(viewer.stage, path) api.SetFromCamera(viewer.currentGfCamera)
def test_FlattenWithOffsets(self): """Tests that layer offsets are taken into account when flattening attribute time samples.""" srcAttr = self.stage.GetPrimAtPath("/OffsetTimeSamples") \ .GetAttribute("a") self.assertEqual(self._GetTimeSamples(srcAttr), {10: 100, 20: 1000}) dstAttr = srcAttr.FlattenTo( self.stage.OverridePrim("/OffsetTimeSamplesRoot")) self.assertEqual(self._GetTimeSamples(dstAttr), {10: 100, 20: 1000}) self.assertEqual( self._GetTimeSamplesInLayer(self.rootLayer, "/OffsetTimeSamplesRoot.a"), { 10: 100, 20: 1000 }) with Usd.EditContext( self.stage, self.stage.GetEditTargetForLocalLayer(self.subLayer)): dstAttr = srcAttr.FlattenTo( self.stage.OverridePrim("/OffsetTimeSamplesSublayer")) self.assertEqual(self._GetTimeSamples(dstAttr), { 10: 100, 20: 1000 }) self.assertEqual( self._GetTimeSamplesInLayer(self.subLayer, "/OffsetTimeSamplesSublayer.a"), { 0: 100, 10: 1000 })
def test_Builtins(self): """Tests flattening builtin properties.""" srcPrim = self.stage.GetPrimAtPath("/FlattenPropertyTest") srcAttr = srcPrim.GetAttribute("builtinAttr") # Flatten a builtin attribute with no authored opinions to a prim # with the same type. Since the fallback values are the same for the # source and destination attributes, no fallbacks should be written; # just an attribute spec with the same variability and typename. dstPrim = self.stage.DefinePrim("/FlattenPropertyTestCopy", srcPrim.GetTypeName()) dstAttr = srcAttr.FlattenTo(dstPrim) dstAttrSpec = self.rootLayer.GetAttributeAtPath(dstAttr.GetPath()) self.assertTrue(dstAttrSpec) self._VerifyExpectedFields( dstAttrSpec, { "custom": False, "typeName": "string", "variability": Sdf.VariabilityVarying }) # Author some values on the newly-created attribute, then flatten # again -- this time, into the stronger session layer. This should # cause fallback values to be baked out to ensure they win over the # authored values in the weaker layer. dstAttrSpec.SetInfo("default", "default_2") dstAttrSpec.SetInfo("testCustomMetadata", "foo") with Usd.EditContext(self.stage, self.stage.GetSessionLayer()): dstAttr = srcAttr.FlattenTo(dstPrim) dstAttrSpec = self.stage.GetSessionLayer() \ .GetAttributeAtPath(dstAttr.GetPath()) self.assertTrue(dstAttrSpec) self._VerifyExpectedFields( dstAttrSpec, { "custom": False, "default": "default value", "testCustomMetadata": "garply", "typeName": "string", "variability": Sdf.VariabilityVarying }) # Flatten builtin attribute to non-builtin attribute. This should # cause all fallbacks to be authored, since the destination attribute # has no fallback opinions. dstAttr = srcAttr.FlattenTo(dstPrim, "nonbuiltinAttr") dstAttrSpec = self.rootLayer.GetAttributeAtPath(dstAttr.GetPath()) self.assertTrue(dstAttrSpec) self._VerifyExpectedFields( dstAttrSpec, { "custom": False, "default": "default value", "displayName": "display name", "testCustomMetadata": "garply", "typeName": "string", "variability": Sdf.VariabilityVarying })
def testMultipleFormatsSerialisation(self): # Test setup self.setupEmptyScene() extensions = ["usd", "usda", "usdc"] usdFilePath = os.path.abspath('MultipleFormatsSerializationTest.usda') def createProxyShapeFromFile(filePath): usdNode = cmds.createNode('mayaUsdProxyShape', skipSelect=True, name='UsdStageShape') cmds.setAttr(usdNode + '.filePath', filePath, type='string') return usdNode def getStageFromProxyShape(shapeNode): return mayaUsdLib.GetPrim(shapeNode).GetStage() # Initialise the sublayers cmds.file(new=True, force=True) cmds.file(rename=self._tempMayaFile) rootLayer = Sdf.Layer.CreateNew(usdFilePath) layers = [] for ext in extensions: filePath = os.path.abspath('TestLayer.{}'.format(ext)) layer = Sdf.Layer.CreateNew(filePath) layer.comment = ext layer.Save() layers.append(layer) rootLayer.subLayerPaths.append(filePath) rootLayer.Save() # Add edits to the 3 format layers and save the maya scene proxyShape = createProxyShapeFromFile(usdFilePath) stage = getStageFromProxyShape(proxyShape) for subLayerPath in stage.GetRootLayer().subLayerPaths: layer = Sdf.Layer.Find(subLayerPath) with Usd.EditContext(stage, layer): stage.DefinePrim("/{}".format(layer.GetFileFormat().primaryFileExtension)) self.assertTrue(stage.GetSessionLayer().empty) cmds.file(save=True, force=True) # Assert the edits have been restored cmds.file(new=True, force=True) cmds.file(self._tempMayaFile, open=True) stage = getStageFromProxyShape(proxyShape) stageLayers = stage.GetUsedLayers() # root + session + 3 format layers self.assertEqual(len(stageLayers), 5) # Check they all exist for layer in layers: self.assertIn(layer, stageLayers) # Check their content exists for ext in extensions: prim = stage.GetPrimAtPath("/{}".format(ext)) self.assertTrue(prim.IsValid()) # Cleanup cmds.file(new=True, force=True) shutil.rmtree(self._currentTestDir)
def test_FlattenTimeCodeWithOffsets(self): """Tests that layer offsets are taken into account when flattening attribute time samples and defaults of time code value attributes.""" propName = "a" srcAttr = self.srcStage.GetPrimAtPath("/OffsetTimeCodeTimeSamples") \ .GetAttribute(propName) self.assertEqual(self._GetDefault(srcAttr), Sdf.TimeCode(10)) self.assertEqual(self._GetTimeSamples(srcAttr), { 10: Sdf.TimeCode(110), 20: Sdf.TimeCode(1010) }) rootPrimPath = Sdf.Path("/OffsetTimeCodeTimeSamplesRoot") for dstStage in [self.srcStage, self.stage2]: dstAttr = srcAttr.FlattenTo(dstStage.OverridePrim(rootPrimPath)) self.assertEqual(self._GetDefault(dstAttr), Sdf.TimeCode(10)) self.assertEqual(self._GetTimeSamples(dstAttr), { 10: Sdf.TimeCode(110), 20: Sdf.TimeCode(1010) }) self.assertEqual( self._GetDefaultInLayer(dstStage.GetRootLayer(), rootPrimPath.AppendProperty(propName)), Sdf.TimeCode(10)) self.assertEqual( self._GetTimeSamplesInLayer( dstStage.GetRootLayer(), rootPrimPath.AppendProperty(propName)), { 10: Sdf.TimeCode(110), 20: Sdf.TimeCode(1010) }) subPrimPath = Sdf.Path("/OffsetTimeCodeTimeSamplesSublayer") dstSubLayer = dstStage.GetLayerStack()[-1] with Usd.EditContext( dstStage, dstStage.GetEditTargetForLocalLayer(dstSubLayer)): dstAttr = srcAttr.FlattenTo(dstStage.OverridePrim(subPrimPath)) self.assertEqual(self._GetDefault(dstAttr), Sdf.TimeCode(10)) self.assertEqual(self._GetTimeSamples(dstAttr), { 10: Sdf.TimeCode(110), 20: Sdf.TimeCode(1010) }) self.assertEqual( self._GetDefaultInLayer( dstSubLayer, subPrimPath.AppendProperty(propName)), self.expectedTimeCodeDefaultValueOffsetSubLayer[dstStage]) self.assertEqual( self._GetTimeSamplesInLayer( dstSubLayer, subPrimPath.AppendProperty(propName)), self.expectedTimeCodeTimeSampleOffsetSubLayer[dstStage])
def set_up_axis(self, axis=UsdGeom.Tokens.z): """Change the up axis of the current stage Args: axis: valid values are `UsdGeom.Tokens.y`, or `UsdGeom.Tokens.z` """ stage = self.get_stage() rootLayer = stage.GetRootLayer() rootLayer.SetPermissionToEdit(True) with Usd.EditContext(stage, rootLayer): UsdGeom.SetStageUpAxis(stage, axis)
def ChangeInsignificantSublayer(): '''Test making changes after adding an insignificant sublayer.''' stage = Usd.Stage.CreateInMemory() layer = stage.GetRootLayer() insignificantSublayer = Sdf.Layer.CreateAnonymous(".usda") assert insignificantSublayer.empty layer.subLayerPaths.append(insignificantSublayer.identifier) assert insignificantSublayer in stage.GetUsedLayers() with Usd.EditContext(stage, insignificantSublayer): prim = stage.DefinePrim("/Foo") assert prim
def _MakeFlattenedRegistryLayer(filePath): # We flatten the schema classes to 'eliminate' composition when querying # the schema registry. stage = Usd.Stage.Open(filePath) # Certain qualities on builtin properties are not overridable in scene # description. For example, builtin attributes' types always come from the # definition registry, never from scene description. That's problematic in # this case where we're trying to *establish* the definition registry. # Since the classes in schema.usda use the real prim type names # (e.g. 'Mesh') Usd will pick up these built-in qualities from the existing # prim definition. To side-step this, we temporarily override the prim type # names in the session layer so they do not pick up these special # nonoverridable qualities when we flatten. Then after the fact we repair # all the type names. def mangle(typeName): return '__MANGLED_TO_AVOID_BUILTINS__' + typeName def demangle(typeName): return typeName.replace('__MANGLED_TO_AVOID_BUILTINS__', '') # Mangle the typeNames. with Usd.EditContext(stage, editTarget=stage.GetSessionLayer()): for cls in stage.GetPseudoRoot().GetAllChildren(): if cls.GetTypeName(): cls.SetTypeName(mangle(cls.GetTypeName())) flatLayer = stage.Flatten(addSourceFileComment=False) # Demangle the typeNames. for cls in flatLayer.rootPrims: if cls.typeName: cls.typeName = demangle(cls.typeName) # In order to prevent derived classes from inheriting base class # documentation metadata, we must manually replace docs here. for layer in stage.GetLayerStack(): for cls in layer.rootPrims: flatCls = flatLayer.GetPrimAtPath(cls.path) if cls.HasInfo('documentation'): flatCls.SetInfo('documentation', cls.documentation) else: flatCls.ClearInfo('documentation') return flatLayer
def test_upAxis(self): stage = Usd.Stage.CreateInMemory() self.assertTrue(stage) self.assertEqual(UsdGeom.GetStageUpAxis(stage), UsdGeom.GetFallbackUpAxis()) self.assertTrue(UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.y)) self.assertEqual(UsdGeom.GetStageUpAxis(stage), UsdGeom.Tokens.y) with Usd.EditContext(stage, Usd.EditTarget(stage.GetSessionLayer())): self.assertTrue(UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.z)) self.assertEqual(UsdGeom.GetStageUpAxis(stage), UsdGeom.Tokens.z) # Setting illegal value should raise with self.assertRaises(Tf.ErrorException): UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.x)
def test_VariantSelectionPathAbstraction(self): for fmt in allFormats: s = Usd.Stage.CreateInMemory( 'TestVariantSelectionPathAbstraction.' + fmt) p = s.OverridePrim("/Foo") vss = p.GetVariantSets() self.assertFalse(p.HasVariantSets()) vs = vss.AddVariantSet("LOD") self.assertTrue(p.HasVariantSets()) self.assertTrue(vs) self.assertTrue(vs.AddVariant("High")) self.assertTrue(p.HasVariantSets()) # This call triggers the bug. This happens because it triggers the # computation of a PcpPrimIndex for the variant prim, which then causes # the prim with a variant selection to be included in the UsdStage's # scene graph later when the next round of change processing occurs. # # XXX: WBN to indicate the bug # above. This code changed when the # variant API changed during the switch to using EditTargets instead of # UsdPrimVariant. It's unclear whether or not the mystery bug is still # reproduced. Leaving the test in place as much as possible.. self.assertFalse(p.GetAttribute("bar").IsDefined()) # This triggers change processing which will include the prim with the # variant selection and put it on the stage. vs.SetVariantSelection('High') editTarget = vs.GetVariantEditTarget() self.assertTrue(editTarget) with Usd.EditContext(s, editTarget): s.DefinePrim(p.GetPath().AppendChild('Foobar'), 'Scope') self.assertTrue(s.GetPrimAtPath(p.GetPath().AppendChild('Foobar'))) # Here's the actual manifestation of the bug: We should still not have # this prim on the stage, but when the bug is present, we do. Paths # containing variant selections can never identify objects on a stage. # Verify that the stage does not contain a prim for the variant prim # spec we just created at </Foo{LOD=High}Foobar> testPath = p.GetPath().AppendVariantSelection( 'LOD', 'High').AppendChild('Foobar') self.assertFalse(s.GetPrimAtPath(testPath))
def test_FlattenWithOffsets(self): """Tests that layer offsets are taken into account when flattening attribute time samples.""" srcAttr = self.srcStage.GetPrimAtPath("/OffsetTimeSamples") \ .GetAttribute("a") self.assertEqual(self._GetTimeSamples(srcAttr), {10: 100, 20: 1000}) for dstStage in [self.srcStage, self.stage2]: dstAttr = srcAttr.FlattenTo( dstStage.OverridePrim("/OffsetTimeSamplesRoot")) self.assertEqual(self._GetTimeSamples(dstAttr), { 10: 100, 20: 1000 }) self.assertEqual( self._GetTimeSamplesInLayer(dstStage.GetRootLayer(), dstAttr.GetPath()), { 10: 100, 20: 1000 }) dstSubLayer = dstStage.GetLayerStack()[-1] with Usd.EditContext( dstStage, dstStage.GetEditTargetForLocalLayer(dstSubLayer)): dstAttr = srcAttr.FlattenTo( dstStage.OverridePrim("/OffsetTimeSamplesSublayer")) # flattened time samples self.assertEqual(self._GetTimeSamples(dstAttr), { 10: 100, 20: 1000 }) # time samples from the offset sublayer self.assertEqual( self._GetTimeSamplesInLayer(dstSubLayer, dstAttr.GetPath()), self.expectedTimeSampleOffsetSublayer[dstStage])
def _buildAndEditAndSaveScene(usdFilePath): """Add edits to the 3 format layers and scene the maya scene. """ cmds.file(new=True, force=True) cmds.file(rename=self._mayaFilePath) proxyName = cmds.AL_usdmaya_ProxyShapeImport(file=usdFilePath)[0] ps = ProxyShape.getByName(proxyName) self.assertTrue(ps) stage = ps.getUsdStage() self.assertTrue(stage) rootLayer = stage.GetRootLayer() for subLayerPath in rootLayer.subLayerPaths: layer = Sdf.Layer.Find(subLayerPath) with Usd.EditContext(stage, layer): stage.DefinePrim("/{}".format( layer.GetFileFormat().primaryFileExtension)) self.assertTrue(stage.GetSessionLayer().empty) cmds.file(save=True, force=True) return proxyName
def test_OffsetsAuthoring(self): for fmt in allFormats: # Create a simple structure one rootLayer with one subLayer, a prim # 'Foo' in the rootLayer that references 'Bar' defined in refLayer. # Then we assign a layer offset to the reference and to the sublayer, # and we test authoring a time sample into the reference via an # EditTarget, as well as to the subLayer. In both cases we check that # the time value was correctly transformed. rootLayer = Sdf.Layer.CreateAnonymous('root.' + fmt) subLayer = Sdf.Layer.CreateAnonymous('sub.' + fmt) refLayer = Sdf.Layer.CreateAnonymous('ref.' + fmt) payloadLayer = Sdf.Layer.CreateAnonymous('payload.' + fmt) # add subLayer to rootLayer and give it a layer offset. subOffset = Sdf.LayerOffset(scale=3.0, offset=4.0) rootLayer.subLayerPaths.append(subLayer.identifier) rootLayer.subLayerOffsets[0] = subOffset # add Foo root prim. fooRoot = Sdf.PrimSpec(rootLayer, 'Foo', Sdf.SpecifierDef) # add Bar target prim in refLayer. barRef = Sdf.PrimSpec(refLayer, 'Bar', Sdf.SpecifierDef) # make Foo reference Bar. refOffset = Sdf.LayerOffset(scale=2.0, offset=1.0) fooRoot.referenceList.Add( Sdf.Reference(refLayer.identifier, barRef.path, refOffset)) # add Baz target prim in payloadLayer. bazPayload = Sdf.PrimSpec(payloadLayer, 'Baz', Sdf.SpecifierDef) # make Foo reference Baz. payloadOffset = Sdf.LayerOffset(offset=-1.0) fooRoot.payloadList.Add( Sdf.Payload(payloadLayer.identifier, bazPayload.path, payloadOffset)) # Set the payload layer to have a different tcps. The effective # payloadOffset for verification below will have the effective scale # from the tcps difference between layers. payloadLayer.timeCodesPerSecond = 48.0 payloadOffset = payloadOffset * Sdf.LayerOffset(scale=24.0 / 48.0) # Create a UsdStage, get 'Foo'. stage = Usd.Stage.Open(rootLayer) foo = stage.GetPrimAtPath('/Foo') # Make an EditTarget to author into the referenced Bar. refNode = foo.GetPrimIndex().rootNode.children[0] self.assertEqual(refNode.path, Sdf.Path('/Bar')) editTarget = Usd.EditTarget(refLayer, refNode) with Usd.EditContext(stage, editTarget): attr = foo.CreateAttribute('attr', Sdf.ValueTypeNames.Double) attr.Set(1.0, time=2.0) self.assertEqual(attr.Get(time=2.0), 1.0, ('expected value 1.0 at time=2.0, got %s' % attr.Get(time=2.0))) # Check that the time value in the reference is correctly # transformed. authoredTime = list( barRef.attributes['attr'].GetInfo('timeSamples').keys())[0] self.assertEqual(refOffset.GetInverse() * 2.0, authoredTime) # Make an EditTarget to author into the payloaded Baz. payloadNode = foo.GetPrimIndex().rootNode.children[1] self.assertEqual(payloadNode.path, Sdf.Path('/Baz')) editTarget = Usd.EditTarget(payloadLayer, payloadNode) with Usd.EditContext(stage, editTarget): attr = foo.CreateAttribute('attrFromBaz', Sdf.ValueTypeNames.Double) attr.Set(1.0, time=2.0) self.assertEqual(attr.Get(time=2.0), 1.0, ('expected value 1.0 at time=2.0, got %s' % attr.Get(time=2.0))) # Check that the time value in the payload is correctly # transformed. authoredTime = list( bazPayload.attributes['attrFromBaz'].GetInfo( 'timeSamples').keys())[0] self.assertEqual(payloadOffset.GetInverse() * 2.0, authoredTime) # Make an EditTarget to author into the sublayer. editTarget = stage.GetEditTargetForLocalLayer(subLayer) with Usd.EditContext(stage, editTarget): attr = foo.GetAttribute('attr') attr.Set(1.0, time=2.0) self.assertEqual(attr.Get(time=2.0), 1.0, ('expected value 1.0 at time=2.0, got %s' % attr.Get(time=2.0))) # Check that the time value in the sublayer is correctly # transformed. authoredTime = list( subLayer.GetAttributeAtPath('/Foo.attr').GetInfo( 'timeSamples').keys())[0] self.assertEqual(subOffset.GetInverse() * 2.0, authoredTime)
def test_FlattenTimeCodeWithOffsets(self): """Tests that layer offsets are taken into account when flattening attribute time samples and defaults of time code value attributes.""" propName = "a" srcAttr = self.stage.GetPrimAtPath("/OffsetTimeCodeTimeSamples") \ .GetAttribute(propName) if Usd.UsesInverseLayerOffset(): self.assertEqual(self._GetDefault(srcAttr), Sdf.TimeCode(-10)) self.assertEqual(self._GetTimeSamples(srcAttr), { -10: Sdf.TimeCode(90), 0: Sdf.TimeCode(990) }) else: self.assertEqual(self._GetDefault(srcAttr), Sdf.TimeCode(10)) self.assertEqual(self._GetTimeSamples(srcAttr), { 10: Sdf.TimeCode(110), 20: Sdf.TimeCode(1010) }) rootPrimPath = Sdf.Path("/OffsetTimeCodeTimeSamplesRoot") dstAttr = srcAttr.FlattenTo( self.stage.OverridePrim(rootPrimPath)) if Usd.UsesInverseLayerOffset(): self.assertEqual(self._GetDefault(dstAttr), Sdf.TimeCode(-10)) self.assertEqual( self._GetTimeSamples(dstAttr), { -10: Sdf.TimeCode(90), 0: Sdf.TimeCode(990) }) self.assertEqual( self._GetDefaultInLayer( self.rootLayer, rootPrimPath.AppendProperty(propName)), Sdf.TimeCode(-10)) self.assertEqual( self._GetTimeSamplesInLayer( self.rootLayer, rootPrimPath.AppendProperty(propName)), { -10: Sdf.TimeCode(90), 0: Sdf.TimeCode(990) }) else: self.assertEqual(self._GetDefault(dstAttr), Sdf.TimeCode(10)) self.assertEqual( self._GetTimeSamples(dstAttr), { 10: Sdf.TimeCode(110), 20: Sdf.TimeCode(1010) }) self.assertEqual( self._GetDefaultInLayer( self.rootLayer, rootPrimPath.AppendProperty(propName)), Sdf.TimeCode(10)) self.assertEqual( self._GetTimeSamplesInLayer( self.rootLayer, rootPrimPath.AppendProperty(propName)), { 10: Sdf.TimeCode(110), 20: Sdf.TimeCode(1010) }) subPrimPath = Sdf.Path("/OffsetTimeCodeTimeSamplesSublayer") with Usd.EditContext( self.stage, self.stage.GetEditTargetForLocalLayer(self.subLayer)): dstAttr = srcAttr.FlattenTo( self.stage.OverridePrim(subPrimPath)) if Usd.UsesInverseLayerOffset(): self.assertEqual(self._GetDefault(dstAttr), Sdf.TimeCode(-10)) self.assertEqual( self._GetTimeSamples(dstAttr), { -10: Sdf.TimeCode(90), 0: Sdf.TimeCode(990) }) self.assertEqual( self._GetDefaultInLayer( self.subLayer, subPrimPath.AppendProperty(propName)), Sdf.TimeCode(0)) self.assertEqual( self._GetTimeSamplesInLayer( self.subLayer, subPrimPath.AppendProperty(propName)), { 0: Sdf.TimeCode(100), 10: Sdf.TimeCode(1000) }) else: self.assertEqual(self._GetDefault(dstAttr), Sdf.TimeCode(10)) self.assertEqual( self._GetTimeSamples(dstAttr), { 10: Sdf.TimeCode(110), 20: Sdf.TimeCode(1010) }) self.assertEqual( self._GetDefaultInLayer( self.subLayer, subPrimPath.AppendProperty(propName)), Sdf.TimeCode(0)) self.assertEqual( self._GetTimeSamplesInLayer( self.subLayer, subPrimPath.AppendProperty(propName)), { 0: Sdf.TimeCode(100), 10: Sdf.TimeCode(1000) })
def test_FlattenPrimDefinition(self): # Verifies that the given spec has exactly the field values enumerated # in expectedFieldValues def _VerifyExpectedFieldValues(spec, expectedFieldValues): for (expectedField, expectedValue) in expectedFieldValues.items(): self.assertEqual(spec.GetInfo(expectedField), expectedValue) for field in spec.ListInfoKeys(): self.assertIn(field, expectedFieldValues) # Verifies that there's a prim spec at path in the layer with the # given set of prim spec fields and the expected properties (with their # own expected fields. def _VerifyExpectedPrimData(layer, path, expectedPrimFields, expectedProperties): # Verify the prim spec and its expected fields. spec = layer.GetObjectAtPath(path) self.assertTrue(spec) _VerifyExpectedFieldValues(spec, expectedPrimFields) # Verify the prim spec has exactly the expected properties and # each property has the expected fields for each expected property. self.assertEqual(len(spec.properties), len(expectedProperties)) for (propName, fieldValues) in expectedProperties.items(): propSpec = spec.properties[propName] self.assertTrue(propSpec) _VerifyExpectedFieldValues(propSpec, fieldValues) # Create a new layer with a sublayer for authoring. layer = Sdf.Layer.CreateAnonymous(".usda") sublayer = Sdf.Layer.CreateAnonymous(".usda") layer.subLayerPaths.append(sublayer.identifier) # Test flattening a prim definition for a concrete schema directly # to a new path in the layer with the def specifier. A new prim spec # will be created with given specifier (as well as an over for the # not yet existent parent path). concretePrimDef = Usd.SchemaRegistry().FindConcretePrimDefinition( "MetadataTest") self.assertTrue( concretePrimDef.FlattenTo(layer, "/PrimDefs/ConcreteSchema", Sdf.SpecifierDef)) # Expected fields and properties from the concrete schema. concretePrimDefPrimFields = { "apiSchemas": Sdf.TokenListOp.CreateExplicit([]), "documentation": concretePrimDef.GetDocumentation(), "hidden": True, "testCustomMetadata": "garply", "specifier": Sdf.SpecifierDef, "typeName": "MetadataTest" } concretePrimDefProperties = { "testAttr": { "custom": False, "default": "foo", "typeName": Sdf.ValueTypeNames.String, "allowedTokens": ["bar", "baz"], "displayGroup": "Display Group", "displayName": "Display Name", "documentation": "Testing documentation metadata", "hidden": True, "testCustomMetadata": "garply", "variability": Sdf.VariabilityVarying }, "testRel": { "custom": False, "displayGroup": "Display Group", "displayName": "Display Name", "documentation": "Testing documentation metadata", "hidden": True, "testCustomMetadata": "garply", "variability": Sdf.VariabilityUniform } } # Verify the new spec exists and has the correct prim fields and # property specs. _VerifyExpectedPrimData(layer, "/PrimDefs/ConcreteSchema", concretePrimDefPrimFields, concretePrimDefProperties) # Test flattening a prim definition for an API schema directly # to a new path in the layer with the fallback over specifier. A new # overprim spec will be created. apiPrimDef = Usd.SchemaRegistry().FindAppliedAPIPrimDefinition( "CollectionAPI") self.assertTrue(apiPrimDef.FlattenTo(layer, "/PrimDefs/APISchema")) # Expected fields and properties from the CollectionAPI schema. Note # that CollectionAPI is a multiple apply schema but the expected # properties have no prefix. This is because the API prim definition is # for the CollectionAPI itself, not an applied instance of the API # schema. apiPrimDefPrimFields = { "apiSchemas": Sdf.TokenListOp.CreateExplicit([]), "documentation": apiPrimDef.GetDocumentation(), "specifier": Sdf.SpecifierOver } apiPrimDefProperties = { "expansionRule": { "custom": False, "default": "expandPrims", "typeName": Sdf.ValueTypeNames.Token, "allowedTokens": ["explicitOnly", "expandPrims", "expandPrimsAndProperties"], "documentation": apiPrimDef.GetPropertyDocumentation("expansionRule"), "variability": Sdf.VariabilityUniform }, "includeRoot": { "custom": False, "default": None, "typeName": Sdf.ValueTypeNames.Bool, "documentation": apiPrimDef.GetPropertyDocumentation("includeRoot"), "variability": Sdf.VariabilityUniform }, "includes": { "custom": False, "documentation": apiPrimDef.GetPropertyDocumentation("includes"), "variability": Sdf.VariabilityUniform }, "excludes": { "custom": False, "documentation": apiPrimDef.GetPropertyDocumentation("excludes"), "variability": Sdf.VariabilityUniform } } # Verify the new spec exists and has the correct prim fields and # property specs. _VerifyExpectedPrimData(layer, "/PrimDefs/APISchema", apiPrimDefPrimFields, apiPrimDefProperties) # Create stage from our to test the overloads of Flatten that take # a UsdPrim parent and a child name. stage = Usd.Stage.Open(layer) parentPrim = stage.GetPrimAtPath("/PrimDefs") self.assertTrue(parentPrim) # Flatten the concrete prim def to a new prim under the parent using # the current edit target (root layer). flattenPrim = concretePrimDef.FlattenTo(parentPrim, "FlattenToNewPrim") self.assertTrue(flattenPrim) # Verify the new spec exists on the root layer and has the correct prim # fields and property specs. Note that FlattenTo was called with the # default over specifier. concretePrimDefPrimFields["specifier"] = Sdf.SpecifierOver _VerifyExpectedPrimData(layer, "/PrimDefs/FlattenToNewPrim", concretePrimDefPrimFields, concretePrimDefProperties) # Flatten the API prim def to the prim we just created using the # sublayer edit target. with Usd.EditContext(stage, sublayer): flattenPrim = apiPrimDef.FlattenTo(flattenPrim) self.assertTrue(flattenPrim) # Verify the new spec exists on the sublayer with the API schema fields # and properties while the root layer still has the flattened concrete # schema spec. _VerifyExpectedPrimData(layer, "/PrimDefs/FlattenToNewPrim", concretePrimDefPrimFields, concretePrimDefProperties) _VerifyExpectedPrimData(sublayer, "/PrimDefs/FlattenToNewPrim", apiPrimDefPrimFields, apiPrimDefProperties) # Flatten the API prim def again to the same prim but now with the # root layer edit target. flattenPrim = apiPrimDef.FlattenTo(flattenPrim) self.assertTrue(flattenPrim) # Verify that the root layer specs fields and properties have been # fully replaced to match the API schema prim definition. _VerifyExpectedPrimData(layer, "/PrimDefs/FlattenToNewPrim", apiPrimDefPrimFields, apiPrimDefProperties) # Build the composed prim definition that would be created for a prim # of the type "MetadataTest" with a CollectionAPI named "foo" applied. newPrimDef = Usd.SchemaRegistry().BuildComposedPrimDefinition( "MetadataTest", ["CollectionAPI:foo"]) # Flatten the composed prim definition to the already existing root # layer spec for the parent of all the other prim's we created. self.assertTrue(layer.GetPrimAtPath("/PrimDefs")) self.assertTrue( newPrimDef.FlattenTo(layer, "/PrimDefs", Sdf.SpecifierDef)) # The prim fields for the composed prim definition will be the same # as the concrete prim definition as prim fields don't come from # applied API schemas. newPrimDefPrimFields = concretePrimDefPrimFields # The apiSchemas metadata will always be set to explicit list of applied # API schemas. newPrimDefPrimFields["apiSchemas"] = \ Sdf.TokenListOp.CreateExplicit(["CollectionAPI:foo"]) # The specifier will still be "over" even though we suggested specifier # "def" because the prim spec already existed. The suggested specifier # only applies to newly created specs. newPrimDefPrimFields["specifier"] = Sdf.SpecifierOver # The expected properties are the combined set of properties from the # concrete schema and the applied schemas. newPrimDefProperties = {} for (propName, fieldValues) in concretePrimDefProperties.items(): newPrimDefProperties[propName] = fieldValues # In this case all the properties from the applied multiple apply # will have the "collection:foo:" prefix as the schema is applied in # this prim definition. for (propName, fieldValues) in apiPrimDefProperties.items(): newPrimDefProperties["collection:foo:" + propName] = fieldValues # Verify the prim spec matches the prim definition. _VerifyExpectedPrimData(layer, "/PrimDefs", newPrimDefPrimFields, newPrimDefProperties) # Verify that the existing children of the prim spec as FlattenTo # doesn't clear or overwrite fields that can never be schema metadata. self.assertTrue(layer.GetPrimAtPath("/PrimDefs/ConcreteSchema")) self.assertTrue(layer.GetPrimAtPath("/PrimDefs/APISchema")) self.assertTrue(layer.GetPrimAtPath("/PrimDefs/FlattenToNewPrim"))
def test_UsdStageTimeMetadata(self): for fmt in allFormats: f = lambda base: base + '.' + fmt sessionLayer = Sdf.Layer.CreateNew(f('sessionLayer')) rootLayer = Sdf.Layer.CreateNew(f("rootLayer")) subLayer = Sdf.Layer.CreateNew(f("subLayer")) rootLayer.subLayerPaths = [f("./subLayer")] subLayer.Save() stage = Usd.Stage.Open(rootLayer, sessionLayer) assert (not stage.HasAuthoredTimeCodeRange()) # Test (startFrame,endFrame) in rootLayer XXX: bug 123508 Once # StartFrame,EndFrame are migrated to Sd, the test cases involving them # should be removed. stage.SetMetadata("startFrame", 10.0) stage.SetMetadata("endFrame", 20.0) assert (stage.GetStartTimeCode() == 10.0) assert (stage.GetEndTimeCode() == 20.0) assert (stage.HasAuthoredTimeCodeRange()) # Test (startFrame,endFrame) in sessionLayer with Usd.EditContext(stage, sessionLayer): stage.SetMetadata('startFrame', 30.0) stage.SetMetadata('endFrame', 40.0) assert (stage.GetStartTimeCode() == 30.0) assert (stage.GetEndTimeCode() == 40.0) assert (stage.HasAuthoredTimeCodeRange()) # Test (startTimeCode,endTimeCode) in rootLayer with (startFrame, # endFrame) in session layer This should author to the root layer. stage.SetStartTimeCode(50.0) stage.SetEndTimeCode(60.0) assert (rootLayer.startTimeCode == 50.0) assert (rootLayer.endTimeCode == 60.0) # (startFrame, endFrame) in the session layer is stronger than # (startTimeCode, endTimeCode) in the rootLayer. assert (stage.GetStartTimeCode() == 30.0) assert (stage.GetEndTimeCode() == 40.0) assert (stage.HasAuthoredTimeCodeRange()) # Clear the (startFrame, endFrame) opinions in the session layer and # verify that (startTimeCode, endTimeCode) in root layer win over the # (startFrame, endFrame) in the root layer. with Usd.EditContext(stage, sessionLayer): stage.ClearMetadata('startFrame') stage.ClearMetadata('endFrame') assert (stage.GetStartTimeCode() == 50.0) assert (stage.GetEndTimeCode() == 60.0) assert (stage.HasAuthoredTimeCodeRange()) # Test (startTimeCode,endTimeCode) in sessionLayer with # (startFrame,endFrame) in # both root and session layers. with Usd.EditContext(stage, sessionLayer): stage.SetStartTimeCode(70.0) stage.SetEndTimeCode(80.0) assert (sessionLayer.startTimeCode == 70.0) assert (sessionLayer.endTimeCode == 80.0) assert (stage.GetStartTimeCode() == 70.0) assert (stage.GetEndTimeCode() == 80.0) assert (stage.HasAuthoredTimeCodeRange()) # Test that setting start/endTimeCode in a layer that's not the root # layer or the session layer will result in a warning and no authoring # is performed. with Usd.EditContext(stage, subLayer): with self.assertRaises(Tf.ErrorException): stage.SetStartTimeCode(90.0) with self.assertRaises(Tf.ErrorException): stage.SetEndTimeCode(100.0) assert (stage.GetStartTimeCode() == 70.0) assert (stage.GetEndTimeCode() == 80.0) assert (stage.HasAuthoredTimeCodeRange()) # Now ensure that we have fallbacks for the 'perSecond' metadata, using # both generic and specific API's. SdfSchema is not wrapped to python, # so we use the psuedoRoot-spec to get fallbacks schemaSpec = rootLayer.pseudoRoot fallbackFps = schemaSpec.GetFallbackForInfo("framesPerSecond") fallbackTps = schemaSpec.GetFallbackForInfo("timeCodesPerSecond") assert (stage.GetFramesPerSecond() == fallbackFps) assert (stage.HasMetadata("framesPerSecond") and not stage.HasAuthoredMetadata("framesPerSecond")) with Usd.EditContext(stage, sessionLayer): stage.SetFramesPerSecond(48.0) assert (stage.GetMetadata("framesPerSecond") == 48.0) assert (stage.HasAuthoredMetadata("framesPerSecond")) assert (schemaSpec.GetInfo("framesPerSecond") == fallbackFps) with Usd.EditContext(stage, sessionLayer): stage.ClearMetadata("framesPerSecond") assert (stage.GetTimeCodesPerSecond() == fallbackTps) assert (stage.HasMetadata("timeCodesPerSecond") and not stage.HasAuthoredMetadata("timeCodesPerSecond")) with Usd.EditContext(stage, sessionLayer): stage.SetTimeCodesPerSecond(48.0) assert (stage.GetMetadata("timeCodesPerSecond") == 48.0) assert (stage.HasAuthoredMetadata("timeCodesPerSecond")) assert (schemaSpec.GetInfo("timeCodesPerSecond") == fallbackTps) # Test the interaction between TCPS and FPS. See the implementation # of UsdStage::GetTimeCodesPerSecond for details. with Usd.EditContext(stage, sessionLayer): stage.SetTimeCodesPerSecond(4) stage.SetFramesPerSecond(2) stage.SetTimeCodesPerSecond(3) stage.SetFramesPerSecond(1) assert (stage.GetTimeCodesPerSecond() == 4) with Usd.EditContext(stage, sessionLayer): stage.ClearMetadata("timeCodesPerSecond") assert (stage.GetTimeCodesPerSecond() == 3) stage.ClearMetadata("timeCodesPerSecond") assert (stage.GetTimeCodesPerSecond() == 2) with Usd.EditContext(stage, sessionLayer): stage.ClearMetadata("framesPerSecond") assert (stage.GetTimeCodesPerSecond() == 1) stage.ClearMetadata("framesPerSecond") assert (stage.GetTimeCodesPerSecond() == fallbackTps)
def set_up_z_axis(stage): rootLayer = stage.GetRootLayer() rootLayer.SetPermissionToEdit(True) with Usd.EditContext(stage, rootLayer): UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.z)
def test_StageEditTargetAPI(self): def OpenLayer(name): fullName = '%s.usda' % name layer = Sdf.Layer.FindOrOpen(fullName) assert layer, 'failed to open layer @%s@' % fullName return layer # Open stage. layer = OpenLayer('testAPI_root') stage = Usd.Stage.Open(layer.identifier) assert stage, 'failed to create stage for @%s@' % layer.identifier # Check GetLayerStack behavior. assert stage.GetLayerStack()[0] == stage.GetSessionLayer() # Get LayerStack without session layer. rootLayer, subLayer1, subLayer2 = \ stage.GetLayerStack(includeSessionLayers=False) assert subLayer1 and subLayer2, ('expected @%s@ to have 2 sublayers' % layer.identifier) assert rootLayer == stage.GetRootLayer() # Get Sarah prim. prim = stage.GetPrimAtPath('/Sarah') assert prim, 'failed to find prim /Sarah' # Sanity check simple composition. assert prim.GetAttribute('color').Get() == Gf.Vec3d(1, 1, 1) assert prim.GetAttribute('sub1Color').Get() == Gf.Vec3d(1, 1, 1) assert prim.GetAttribute('sub2Color').Get() == Gf.Vec3d(1, 1, 1) # Should start out with EditTarget being local & root layer. assert (stage.HasLocalLayer(stage.GetEditTarget().GetLayer()) and stage.GetEditTarget().GetLayer() == stage.GetRootLayer()) # Set EditTarget to sublayers. stage.SetEditTarget(subLayer1) assert stage.GetEditTarget() == subLayer1, 'failed to set EditTarget' stage.SetEditTarget(subLayer2) assert stage.GetEditTarget() == subLayer2, 'failed to set EditTarget' stage.SetEditTarget(stage.GetRootLayer()) assert stage.GetEditTarget() == stage.GetRootLayer(), \ 'failed to set EditTarget' # Try authoring to sublayers using context object. with Usd.EditContext(stage, subLayer2): prim.GetAttribute('sub2Color').Set(Gf.Vec3d(3, 4, 5)) assert prim.GetAttribute('sub2Color').Get() == Gf.Vec3d(3, 4, 5) assert not rootLayer.GetAttributeAtPath('/Sarah.sub2Color') assert (subLayer2.GetAttributeAtPath('/Sarah.sub2Color').default == Gf.Vec3d(3, 4, 5)) # Target should be back to root layer. assert stage.GetEditTarget() == stage.GetRootLayer(), \ 'EditContext failed to restore EditTarget' # Set to subLayer1. stage.SetEditTarget(subLayer1) # Try authoring to session layer using context object. sessionLayer = stage.GetSessionLayer() with Usd.EditContext(stage, sessionLayer): assert stage.GetEditTarget() == sessionLayer assert not sessionLayer.GetAttributeAtPath('/Sarah.color') prim.GetAttribute('color').Set(Gf.Vec3d(9, 9, 9)) assert prim.GetAttribute('color').Get() == Gf.Vec3d(9, 9, 9) assert (sessionLayer.GetAttributeAtPath('/Sarah.color').default == Gf.Vec3d(9, 9, 9)) assert (rootLayer.GetAttributeAtPath('/Sarah.color').default == Gf.Vec3d(1, 1, 1)) # Target should be back to subLayer1. assert stage.GetEditTarget() == subLayer1, \ 'EditContext failed to restore EditTarget' # Verify an error is reported for setting EditTarget as a local layer # that's not in the local LayerStack. anon = Sdf.Layer.CreateAnonymous() assert anon with self.assertRaises(RuntimeError): stage.SetEditTarget(anon)
def test_ApplyRemoveAPI(self): """ Tests the detail of the Apply and Remove API for API schemas. """ stage = Usd.Stage.CreateInMemory() rootLayer = stage.GetRootLayer() sessionLayer = stage.GetSessionLayer() self.assertTrue(rootLayer) self.assertTrue(sessionLayer) # Add a basic prim with no type. It has no applied schemas or properties. prim = stage.DefinePrim("/Prim") self.assertEqual(prim.GetAppliedSchemas(), []) self.assertEqual(prim.GetPrimTypeInfo().GetAppliedAPISchemas(), []) # Helper function for verifying the state of the 'apiSchemas' list op # field in the prim spec for the test prim on the specified layer. def _VerifyListOp(layer, explicit=[], prepended=[], appended=[], deleted=[]): spec = layer.GetPrimAtPath('/Prim') listOp = spec.GetInfo('apiSchemas') self.assertEqual(listOp.explicitItems, explicit) self.assertEqual(listOp.prependedItems, prepended) self.assertEqual(listOp.appendedItems, appended) self.assertEqual(listOp.deletedItems, deleted) # Apply a single api schema withe default edit target. Adds to the end # prepend list. prim.ApplyAPI(self.SingleApplyAPIType) self.assertEqual(prim.GetAppliedSchemas(), ["TestSingleApplyAPI"]) self.assertTrue(prim.HasAPI(self.SingleApplyAPIType)) _VerifyListOp(rootLayer, prepended=["TestSingleApplyAPI"]) # Apply the same API schema again. This will not update the list. prim.ApplyAPI(self.SingleApplyAPIType) self.assertEqual(prim.GetAppliedSchemas(), ["TestSingleApplyAPI"]) self.assertTrue(prim.HasAPI(self.SingleApplyAPIType)) _VerifyListOp(rootLayer, prepended=["TestSingleApplyAPI"]) # Remove the API schema. This removes the schema from the prepend and # puts in it the deleted list. prim.RemoveAPI(self.SingleApplyAPIType) self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer, deleted=["TestSingleApplyAPI"]) # Remove the same API again. This is a no op. prim.RemoveAPI(self.SingleApplyAPIType) self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer, deleted=["TestSingleApplyAPI"]) # Remove a multi apply schema which is not currently in the list. The # This schema instance name is still added to the deleted list. prim.RemoveAPI(self.MultiApplyAPIType, "foo") self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer, deleted=["TestSingleApplyAPI", "TestMultiApplyAPI:foo"]) # Apply the same instance of the multi-apply schema we just deleted. It # is added to the prepended but is NOT removed from the deleted list. # It still ends up in the composed API schemas since deletes are # processed before prepends in the same list op. prim.ApplyAPI(self.MultiApplyAPIType, "foo") self.assertEqual(prim.GetAppliedSchemas(), ["TestMultiApplyAPI:foo"]) _VerifyListOp(rootLayer, prepended=["TestMultiApplyAPI:foo"], deleted=["TestSingleApplyAPI", "TestMultiApplyAPI:foo"]) # Apply a different instance of the multi-apply schema. Its is added to # the end of the prepends list. prim.ApplyAPI(self.MultiApplyAPIType, "bar") self.assertEqual(prim.GetAppliedSchemas(), ["TestMultiApplyAPI:foo", "TestMultiApplyAPI:bar"]) _VerifyListOp( rootLayer, prepended=["TestMultiApplyAPI:foo", "TestMultiApplyAPI:bar"], deleted=["TestSingleApplyAPI", "TestMultiApplyAPI:foo"]) # Remove the "bar" instance of the multi-apply schema on the session # layer. The schema is added to the deleted list on the session layer # and root layer remains the same. It does not show up in the composed # API schemas after composition with Usd.EditContext(stage, sessionLayer): prim.RemoveAPI(self.MultiApplyAPIType, "bar") self.assertEqual(prim.GetAppliedSchemas(), ["TestMultiApplyAPI:foo"]) _VerifyListOp( rootLayer, prepended=["TestMultiApplyAPI:foo", "TestMultiApplyAPI:bar"], deleted=["TestSingleApplyAPI", "TestMultiApplyAPI:foo"]) _VerifyListOp(sessionLayer, deleted=["TestMultiApplyAPI:bar"]) # Re-apply the "bar" instance of the multi-apply schema on the session # layer. It is added to the prepend list in the session layer but still # remains in the delete list. Note that the "bar" instance is back in # the composed API schemas list but now it is first instead of second # like it was before as it get deleted and prepended by the session # layer. with Usd.EditContext(stage, sessionLayer): prim.ApplyAPI(self.MultiApplyAPIType, "bar") self.assertEqual(prim.GetAppliedSchemas(), ["TestMultiApplyAPI:bar", "TestMultiApplyAPI:foo"]) _VerifyListOp( rootLayer, prepended=["TestMultiApplyAPI:foo", "TestMultiApplyAPI:bar"], deleted=["TestSingleApplyAPI", "TestMultiApplyAPI:foo"]) _VerifyListOp(sessionLayer, prepended=["TestMultiApplyAPI:bar"], deleted=["TestMultiApplyAPI:bar"]) # These next few cases verifies the behavior when the list op has # appends or explicit entries. (Note that we don't define behaviors for # add or reorder). # Update the session layer to have an appended API schema. with Usd.EditContext(stage, sessionLayer): appendedListOp = Sdf.TokenListOp() appendedListOp.appendedItems = ["TestMultiApplyAPI:bar"] prim.SetMetadata('apiSchemas', appendedListOp) # Update the root layer to have an explicit list op. explicitListOp = Sdf.TokenListOp() explicitListOp.explicitItems = ["TestMultiApplyAPI:foo"] prim.SetMetadata('apiSchemas', explicitListOp) # Verify the initial authored and composed lists. self.assertEqual(prim.GetAppliedSchemas(), ["TestMultiApplyAPI:foo", "TestMultiApplyAPI:bar"]) _VerifyListOp(rootLayer, explicit=["TestMultiApplyAPI:foo"]) _VerifyListOp(sessionLayer, appended=["TestMultiApplyAPI:bar"]) # On the session and root layers, try to apply the API schema that # is already in each respective list. This will be a no op even though # the schemas aren't in the prepended lists. with Usd.EditContext(stage, sessionLayer): prim.ApplyAPI(self.MultiApplyAPIType, "bar") prim.ApplyAPI(self.MultiApplyAPIType, "foo") self.assertEqual(prim.GetAppliedSchemas(), ["TestMultiApplyAPI:foo", "TestMultiApplyAPI:bar"]) _VerifyListOp(rootLayer, explicit=["TestMultiApplyAPI:foo"]) _VerifyListOp(sessionLayer, appended=["TestMultiApplyAPI:bar"]) # Apply the single apply schema to both layers. The root layer adds it # to the end of its explicit list while the session layer will add it # the prepends. The composed API schemas will only contain the schema # once with the prepend from the stronger session layer winning for # ordering. with Usd.EditContext(stage, sessionLayer): prim.ApplyAPI(self.SingleApplyAPIType) prim.ApplyAPI(self.SingleApplyAPIType) self.assertEqual(prim.GetAppliedSchemas(), [ "TestSingleApplyAPI", "TestMultiApplyAPI:foo", "TestMultiApplyAPI:bar" ]) _VerifyListOp(rootLayer, explicit=["TestMultiApplyAPI:foo", "TestSingleApplyAPI"]) _VerifyListOp(sessionLayer, prepended=["TestSingleApplyAPI"], appended=["TestMultiApplyAPI:bar"]) # Remove the starting API schemas from the root and session layers. In # the root layer it is just removed from the explicit list. In the # session layer it is removed from appends and added to the deletes. with Usd.EditContext(stage, sessionLayer): prim.RemoveAPI(self.MultiApplyAPIType, "bar") prim.RemoveAPI(self.MultiApplyAPIType, "foo") self.assertEqual(prim.GetAppliedSchemas(), ["TestSingleApplyAPI"]) _VerifyListOp(rootLayer, explicit=["TestSingleApplyAPI"]) _VerifyListOp(sessionLayer, prepended=["TestSingleApplyAPI"], deleted=["TestMultiApplyAPI:bar"]) # Clear the apiSchemas in both layers for the next tests. # XXX: Should we have additional API for clearing the list op like we # do for other list op fields? with Usd.EditContext(stage, sessionLayer): prim.SetMetadata('apiSchemas', Sdf.TokenListOp()) prim.SetMetadata('apiSchemas', Sdf.TokenListOp()) self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer) _VerifyListOp(sessionLayer) # Trying to apply or remove a multi-apply schema with no instance name # is an error. with self.assertRaises(Tf.ErrorException): prim.ApplyAPI(self.MultiApplyAPIType) self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer) with self.assertRaises(Tf.ErrorException): prim.RemoveAPI(self.MultiApplyAPIType) self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer) # Trying to apply or remove a single apply schema with an instance name # is an error. with self.assertRaises(Tf.ErrorException): prim.ApplyAPI(self.SingleApplyAPIType, "foo") self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer) with self.assertRaises(Tf.ErrorException): prim.RemoveAPI(self.SingleApplyAPIType, "foo") self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer) # Trying to apply or remove a no apply schema is an error. with self.assertRaises(Tf.ErrorException): prim.ApplyAPI(Usd.ModelAPI) self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer) with self.assertRaises(Tf.ErrorException): prim.RemoveAPI(Usd.ModelAPI) self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer) # AddAPITypeName will just add by schema type name with no validity # checks. But it still won't add duplicates. # # Valid type names prim.AddAppliedSchema("TestSingleApplyAPI") prim.AddAppliedSchema("TestMultiApplyAPI:bar") # Invalid type names. prim.AddAppliedSchema("BogusTypeName") prim.AddAppliedSchema("TestMultiApplyAPI") # Duplicate. prim.AddAppliedSchema("TestSingleApplyAPI") self.assertEqual(prim.GetAppliedSchemas(), [ "TestSingleApplyAPI", "TestMultiApplyAPI:bar", "BogusTypeName", "TestMultiApplyAPI" ]) _VerifyListOp(rootLayer, prepended=[ "TestSingleApplyAPI", "TestMultiApplyAPI:bar", "BogusTypeName", "TestMultiApplyAPI" ]) # RemoveAPITypeName will just delete by schema type name with no # validity checks. But it still won't add duplicate delete entries. # # Valid type names prim.RemoveAppliedSchema("TestSingleApplyAPI") prim.RemoveAppliedSchema("TestMultiApplyAPI:bar") # Invalid type names. prim.RemoveAppliedSchema("BogusTypeName") prim.RemoveAppliedSchema("TestMultiApplyAPI") # Duplicate. prim.RemoveAppliedSchema("TestSingleApplyAPI") self.assertEqual(prim.GetAppliedSchemas(), []) _VerifyListOp(rootLayer, deleted=[ "TestSingleApplyAPI", "TestMultiApplyAPI:bar", "BogusTypeName", "TestMultiApplyAPI" ])
def _TestOrder(s, parentPath): f = s.DefinePrim(parentPath) if parentPath else s.GetPseudoRoot() s.SetEditTarget(s.GetRootLayer()) for name in l('abcd'): s.DefinePrim(parentPath + '/' + name) s.SetEditTarget(s.GetSessionLayer()) for name in l('defg'): s.OverridePrim(parentPath + '/' + name) # Start with no primOrder set. Default order. self.assertIsNone(f.GetMetadata("primOrder")) self.assertEqual(f.GetChildrenReorder(), []) _TestAllChildren(f, l('abcdefg')) _TestChildren(f, l('abcd')) # Set partial ordering. f.SetChildrenReorder(l('edc')) self.assertEqual(f.GetMetadata("primOrder"), l('edc')) self.assertEqual(f.GetChildrenReorder(), l('edc')) _TestAllChildren(f, l('abefgdc')) _TestChildren(f, l('abdc')) # Empty ordering. Back to default order. f.SetChildrenReorder([]) self.assertEqual(f.GetMetadata("primOrder"), []) self.assertEqual(f.GetChildrenReorder(), []) _TestAllChildren(f, l('abcdefg')) _TestChildren(f, l('abcd')) # Single entry in order. Still maintains default ordering. f.SetChildrenReorder(l('d')) self.assertEqual(f.GetMetadata("primOrder"), l('d')) self.assertEqual(f.GetChildrenReorder(), l('d')) _TestAllChildren(f, l('abcdefg')) _TestChildren(f, l('abcd')) # Set ordering with no valid names. Default ordering. f.SetChildrenReorder(l('xyz')) self.assertEqual(f.GetMetadata("primOrder"), l('xyz')) self.assertEqual(f.GetChildrenReorder(), l('xyz')) _TestAllChildren(f, l('abcdefg')) _TestChildren(f, l('abcd')) # Set reorder with interspersed invalid names. Reorders with just # the valid names. f.SetChildrenReorder(l('xeydzc')) self.assertEqual(f.GetMetadata("primOrder"), l('xeydzc')) self.assertEqual(f.GetChildrenReorder(), l('xeydzc')) _TestAllChildren(f, l('abefgdc')) _TestChildren(f, l('abdc')) # Full reorder containing all the child prims. f.SetChildrenReorder(l('gfedcba')) self.assertEqual(f.GetMetadata("primOrder"), l('gfedcba')) self.assertEqual(f.GetChildrenReorder(), l('gfedcba')) _TestAllChildren(f, l('gfedcba')) _TestChildren(f, l('dcba')) # Clear the reorder on the session layer. Return to original order. f.ClearChildrenReorder() self.assertIsNone(f.GetMetadata("primOrder")) self.assertEqual(f.GetChildrenReorder(), []) _TestAllChildren(f, l('abcdefg')) _TestChildren(f, l('abcd')) # Do a full reorder on the root layer. with Usd.EditContext(s, s.GetRootLayer()): f.SetChildrenReorder(l('gfedcba')) self.assertEqual(f.GetMetadata("primOrder"), l('gfedcba')) self.assertEqual(f.GetChildrenReorder(), l('gfedcba')) # Because the reorder is authored on the root layer, it only # reorders the prims that are defined on the root layer because # prim order is processed during composition. The prims defined on # the session layer are not reordered. _TestAllChildren(f, l('dcbaefg')) _TestChildren(f, l('dcba')) # Set an empty ordering on session layer. The strongest resolved # metadata is now empty, but the reordering from the root layer # metadata still takes place. f.SetChildrenReorder([]) self.assertEqual(f.GetMetadata("primOrder"), []) self.assertEqual(f.GetChildrenReorder(), []) _TestAllChildren(f, l('dcbaefg')) _TestChildren(f, l('dcba'))