def test_Basic(self): # Create a PcpCache for a reference chain, but do not perform any actual # composition before querying its used layers. Verify that this does not crash. file = 'BasicReference/root.sdf' self.assertTrue(os.path.isfile(file)) layer = Sdf.Layer.FindOrOpen(file) self.assertTrue(layer) lsi = Pcp.LayerStackIdentifier(layer) self.assertTrue(lsi) pcpCache = Pcp.Cache(lsi) self.assertTrue(pcpCache) pcpCache.GetUsedLayers() # Create a PcpCache with a file format target, ensuring that layers # without the correct target will be marked invalid during composition. pcpCache = Pcp.Cache(lsi, fileFormatTarget='sdf') (pi, _) = pcpCache.ComputePrimIndex('/PrimWithReferences') self.assertTrue(pi.IsValid()) self.assertEqual(len(pi.localErrors), 0) # Should be two local errors corresponding to invalid asset paths, # since this prim has two references to layers with a different target. pcpCache = Pcp.Cache(lsi, fileFormatTarget='Presto') (pi, _) = pcpCache.ComputePrimIndex('/PrimWithReferences') self.assertTrue(pi.IsValid()) self.assertEqual(len(pi.localErrors), 2) self.assertTrue( all([(isinstance(e, Pcp.ErrorInvalidAssetPath) for e in pi.localErrors)]))
def test_Basic(self): rootLayer = Sdf.Layer.FindOrOpen('bug101300/root.sdf') pcpCache = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer)) # Compute the prim index for /Root/A. The relocates authored on /Root/A # should be applied, causing /Root/A/B to be renamed /Root/A/B_2. (pi, err) = pcpCache.ComputePrimIndex('/Root/A') self.assertEqual(len(err), 0) self.assertEqual(pi.ComputePrimChildNames(), (['B_2'],['B'])) self.assertEqual(pcpCache.layerStack.relocatesSourceToTarget, {Sdf.Path('/Root/A/B'): Sdf.Path('/Root/A/B_2')}) self.assertEqual(pcpCache.layerStack.pathsToPrimsWithRelocates, [Sdf.Path('/Root/A')]) # Remove the over on /Root/A that provides the relocates. with Pcp._TestChangeProcessor(pcpCache): del rootLayer.GetPrimAtPath('/Root').nameChildren['A'] # The prim at /Root/A should still exist, but there should no longer be # any relocates to apply. (pi, err) = pcpCache.ComputePrimIndex('/Root/A') self.assertEqual(len(err), 0) self.assertEqual(pi.ComputePrimChildNames(), (['B'],[])) self.assertEqual(pcpCache.layerStack.relocatesSourceToTarget, {}) self.assertEqual(pcpCache.layerStack.pathsToPrimsWithRelocates, [])
def test_Basic(self): rootLayer = Sdf.Layer.FindOrOpen('bug70951/root.sdf') refLayer = Sdf.Layer.FindOrOpen('bug70951/JoyGroup.sdf') pcpCache = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer)) # Compute the prim index for the Sim scope under JoyGroup. This index # should consist of two nodes: the direct node and the reference node. # Since there is no spec for the Sim scope in the root layer, the root node # should be marked as such. (primIndex, errors) = \ pcpCache.ComputePrimIndex('/World/anim/chars/JoyGroup/Sim') self.assertEqual(len(errors), 0) self.assertEqual(primIndex.primStack, [refLayer.GetPrimAtPath('/JoyGroup/Sim')]) self.assertFalse(primIndex.rootNode.hasSpecs) # Now create an empty over for the Sim scope in the root layer and verify # that the prim index sees this new spec after change processing. with Pcp._TestChangeProcessor(pcpCache): emptyOver = \ Sdf.CreatePrimInLayer(rootLayer, '/World/anim/chars/JoyGroup/Sim') self.assertTrue(emptyOver.IsInert()) (primIndex, errors) = \ pcpCache.ComputePrimIndex('/World/anim/chars/JoyGroup/Sim') self.assertEqual(len(errors), 0) self.assertEqual(primIndex.primStack, [ rootLayer.GetPrimAtPath('/World/anim/chars/JoyGroup/Sim'), refLayer.GetPrimAtPath('/JoyGroup/Sim') ]) self.assertTrue(primIndex.rootNode.hasSpecs)
def test_Basic(self): rootLayer = Sdf.Layer.FindOrOpen('bug90706/root.sdf') pcpCache = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer)) (index, err) = pcpCache.ComputePrimIndex('/Sarah/EmptyPrim') self.assertTrue(index) self.assertEqual(len(err), 0) # This prim index should only contain the root node; the variant # arc to /Sarah{displayColor=red}EmptyPrim will have been culled # because there's no prim spec there. self.assertEqual(len(index.rootNode.children), 0) with Pcp._TestChangeProcessor(pcpCache): p = Sdf.CreatePrimInLayer(rootLayer, '/Sarah{displayColor=red}EmptyPrim') # The addition of the inert prim should have caused the prim index # to be blown, because it needs to be re-computed to accommodate the # no-longer-inert variant node. self.assertFalse(pcpCache.FindPrimIndex('/Sarah/EmptyPrim')) (index, err) = pcpCache.ComputePrimIndex('/Sarah/EmptyPrim') self.assertTrue(index) self.assertEqual(len(err), 0) # There should now be a variant arc for /Sarah{displayColor=red}EmptyPrim # in the local layer stack. self.assertEqual(len(index.rootNode.children), 1) self.assertEqual(index.rootNode.children[0].arcType, Pcp.ArcTypeVariant) self.assertEqual(index.rootNode.children[0].layerStack, index.rootNode.layerStack) self.assertEqual(index.rootNode.children[0].path, '/Sarah{displayColor=red}EmptyPrim')
def test_Basic(self): rootLayer = Sdf.Layer.FindOrOpen('bug92955/root.sdf') pcpCache = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer)) # Populate all prims in the scene paths = [Sdf.Path('/')] while paths: path, paths = paths[0], paths[1:] primIndex, _ = pcpCache.ComputePrimIndex(path) for name in primIndex.ComputePrimChildNames()[0]: paths.append(path.AppendChild(name)) # Verify there are symmetric corresponding paths on SymRig. layerStack = pcpCache.layerStack x = pcpCache.FindSiteDependencies(layerStack, '/Model/Rig/SymRig', Pcp.DependencyTypeDirect | Pcp.DependencyTypeNonVirtual) self.assertNotEqual(len(x), 0) # Delete the unrelated class. with Pcp._TestChangeProcessor(pcpCache): del rootLayer.GetPrimAtPath('/Model/Rig').nameChildren['SymScope'] # Verify the same symmetric corresponding paths are on SymRig. y = pcpCache.FindSiteDependencies(layerStack, '/Model/Rig/SymRig', Pcp.DependencyTypeDirect | Pcp.DependencyTypeNonVirtual) self.assertEqual(x, y)
def TestResolve(expectedSourceLayer): path = "/Sphere.radius" # XXX: We create the cache from scratch each time because # Pcp doesn't yet respond to Sd notices (regarding # changes to layer ownership). When it does we # should create the cache and layer stack in # ClassSetup() and hold them as properties on self. cache = Pcp.Cache(self.layerStackId) self.assertTrue(cache) (layerStack, errors) = cache.ComputeLayerStack(self.layerStackId) self.assertEqual(len(errors), 0) self.assertTrue(layerStack) # Find the strongest layer with an opinion about the radius # default. strongestLayer = None for layer in layerStack.layers: radiusAttr = layer.GetObjectAtPath(path) if radiusAttr and radiusAttr.default: strongestLayer = layer break # Ensure the strongest layer with an opinion is the # expectedSourceLayer self.assertEqual(strongestLayer, expectedSourceLayer)
def test_EmptySublayerChanges(self): subLayer1 = Sdf.Layer.CreateAnonymous() primSpec = Sdf.CreatePrimInLayer(subLayer1, '/Test') rootLayer = Sdf.Layer.CreateAnonymous() rootLayer.subLayerPaths.append(subLayer1.identifier) layerStackId = Pcp.LayerStackIdentifier(rootLayer) pcp = Pcp.Cache(layerStackId) (pi, err) = pcp.ComputePrimIndex('/Test') self.assertFalse(err) self.assertEqual(pi.primStack, [primSpec]) subLayer2 = Sdf.Layer.CreateAnonymous() self.assertTrue(subLayer2.empty) # Adding an empty sublayer should not require recomputing any # prim indexes or change their prim stacks. with Pcp._TestChangeProcessor(pcp): rootLayer.subLayerPaths.insert(0, subLayer2.identifier) pi = pcp.FindPrimIndex('/Test') self.assertTrue(pi) self.assertEqual(pi.primStack, [primSpec]) # Same with deleting an empty sublayer. with Pcp._TestChangeProcessor(pcp): del rootLayer.subLayerPaths[0] pi = pcp.FindPrimIndex('/Test') self.assertTrue(pi) self.assertEqual(pi.primStack, [primSpec])
def _Test(referencingLayer): # Make a PcpCache. pcp = Pcp.Cache(Pcp.LayerStackIdentifier(referencingLayer)) (pi, err) = pcp.ComputePrimIndex('/source') # First child node should be the referenced target1. self.assertEqual(pi.rootNode.children[0].path, '/target1') # Now clear defaultPrim. This should issue an error and # fail to pick up the referenced prim. with Pcp._TestChangeProcessor(pcp): targLyr.ClearDefaultPrim() (pi, err) = pcp.ComputePrimIndex('/source') self.assertTrue(isinstance(err[0], Pcp.ErrorUnresolvedPrimPath)) # If the reference to the defaultPrim is an external reference, # the one child node should be the pseudoroot dependency placeholder. # If the reference is an internal reference, that dependency # placeholder is unneeded. if referencingLayer != targLyr: self.assertEqual(len(pi.rootNode.children), 1) self.assertEqual(pi.rootNode.children[0].path, '/') # Change defaultPrim to other target. This should pick # up the reference again, but to the new prim target2. with Pcp._TestChangeProcessor(pcp): targLyr.defaultPrim = 'target2' (pi, err) = pcp.ComputePrimIndex('/source') self.assertEqual(len(err), 0) self.assertEqual(pi.rootNode.children[0].path, '/target2') # Reset defaultPrim to original target targLyr.defaultPrim = 'target1'
def test_SublayerOffsetChanges(self): rootLayerPath = 'TestSublayerOffsetChanges/root.sdf' rootSublayerPath = 'TestSublayerOffsetChanges/root-sublayer.sdf' refLayerPath = 'TestSublayerOffsetChanges/ref.sdf' refSublayerPath = 'TestSublayerOffsetChanges/ref-sublayer.sdf' ref2LayerPath = 'TestSublayerOffsetChanges/ref2.sdf' rootLayer = Sdf.Layer.FindOrOpen(rootLayerPath) pcp = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer)) (pi, err) = pcp.ComputePrimIndex('/A') self.assertTrue(pi) self.assertEqual(len(err), 0) # Verify the expected structure of the test asset. It should simply be # a chain of two references, with layer offsets of 100.0 and 50.0 # respectively. refNode = pi.rootNode.children[0] self.assertEqual( refNode.layerStack.layers, [Sdf.Layer.Find(refLayerPath), Sdf.Layer.Find(refSublayerPath)]) self.assertEqual(refNode.arcType, Pcp.ArcTypeReference) self.assertEqual(refNode.mapToRoot.timeOffset, Sdf.LayerOffset(100.0)) ref2Node = refNode.children[0] self.assertEqual(ref2Node.layerStack.layers, [Sdf.Layer.Find(ref2LayerPath)]) self.assertEqual(ref2Node.arcType, Pcp.ArcTypeReference) self.assertEqual(ref2Node.mapToRoot.timeOffset, Sdf.LayerOffset(150.0)) # Change the layer offset in the local layer stack and verify that # invalidates the prim index and that the updated layer offset is # taken into account after recomputing the index. with Pcp._TestChangeProcessor(pcp): rootLayer.subLayerOffsets[0] = Sdf.LayerOffset(200.0) self.assertFalse(pcp.FindPrimIndex('/A')) (pi, err) = pcp.ComputePrimIndex('/A') refNode = pi.rootNode.children[0] ref2Node = refNode.children[0] self.assertEqual(refNode.mapToRoot.timeOffset, Sdf.LayerOffset(200.0)) self.assertEqual(ref2Node.mapToRoot.timeOffset, Sdf.LayerOffset(250.0)) # Change the layer offset in a referenced layer stack and again verify # that the prim index is invalidated and the updated layer offset is # taken into account. refLayer = refNode.layerStack.layers[0] with Pcp._TestChangeProcessor(pcp): refLayer.subLayerOffsets[0] = Sdf.LayerOffset(200.0) self.assertFalse(pcp.FindPrimIndex('/A')) (pi, err) = pcp.ComputePrimIndex('/A') refNode = pi.rootNode.children[0] ref2Node = refNode.children[0] self.assertEqual(refNode.mapToRoot.timeOffset, Sdf.LayerOffset(200.0)) self.assertEqual(ref2Node.mapToRoot.timeOffset, Sdf.LayerOffset(400.0))
def test_InertPrimRemovalChanges(self): subLayer = Sdf.Layer.CreateAnonymous() subParentSpec = Sdf.PrimSpec(subLayer, 'Parent', Sdf.SpecifierDef) subChildSpec = Sdf.PrimSpec(subParentSpec, 'Child', Sdf.SpecifierDef) subAttrSpec = Sdf.AttributeSpec(subChildSpec, 'attr', Sdf.ValueTypeNames.Double) subAttrSpec.default = 1.0 rootLayer = Sdf.Layer.CreateAnonymous() rootParentSpec = Sdf.PrimSpec(rootLayer, 'Parent', Sdf.SpecifierOver) rootChildSpec = Sdf.PrimSpec(rootParentSpec, 'Child', Sdf.SpecifierOver) rootAttrSpec = Sdf.AttributeSpec(rootChildSpec, 'attr', Sdf.ValueTypeNames.Double) rootLayer.subLayerPaths.append(subLayer.identifier) pcp = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer)) (pi, err) = pcp.ComputePrimIndex('/Parent') self.assertEqual(err, []) self.assertEqual(pi.primStack, [rootParentSpec, subParentSpec]) (pi, err) = pcp.ComputePrimIndex('/Parent/Child') self.assertEqual(err, []) self.assertEqual(pi.primStack, [rootChildSpec, subChildSpec]) (pi, err) = pcp.ComputePropertyIndex('/Parent/Child.attr') self.assertEqual(err, []) self.assertEqual(pi.propertyStack, [rootAttrSpec, subAttrSpec]) revCount = pcp.GetUsedLayersRevision() with Pcp._TestChangeProcessor(pcp) as cp: del rootLayer.pseudoRoot.nameChildren['Parent'] self.assertFalse(rootParentSpec) self.assertFalse(rootChildSpec) self.assertFalse(rootAttrSpec) self.assertEqual(cp.GetSignificantChanges(), []) self.assertEqual( cp.GetSpecChanges(), ['/Parent', '/Parent/Child', '/Parent/Child.attr']) self.assertEqual(cp.GetPrimChanges(), []) self.assertEqual(revCount, pcp.GetUsedLayersRevision()) (pi, err) = pcp.ComputePrimIndex('/Parent') self.assertEqual(err, []) self.assertEqual(pi.primStack, [subParentSpec]) (pi, err) = pcp.ComputePrimIndex('/Parent/Child') self.assertEqual(err, []) self.assertEqual(pi.primStack, [subChildSpec]) (pi, err) = pcp.ComputePropertyIndex('/Parent/Child.attr') self.assertEqual(err, []) self.assertEqual(pi.propertyStack, [subAttrSpec])
def test_InstancingChanges(self): refLayer = Sdf.Layer.CreateAnonymous() refParentSpec = Sdf.PrimSpec(refLayer, 'Parent', Sdf.SpecifierDef) refChildSpec = Sdf.PrimSpec(refParentSpec, 'RefChild', Sdf.SpecifierDef) rootLayer = Sdf.Layer.CreateAnonymous() parentSpec = Sdf.PrimSpec(rootLayer, 'Parent', Sdf.SpecifierOver) parentSpec.referenceList.Add( Sdf.Reference(refLayer.identifier, '/Parent')) childSpec = Sdf.PrimSpec(parentSpec, 'DirectChild', Sdf.SpecifierDef) # Instancing is only enabled in Usd mode. pcp = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer), usd=True) # /Parent is initially not tagged as an instance, so we should # see both RefChild and DirectChild name children. (pi, err) = pcp.ComputePrimIndex('/Parent') self.assertEqual(len(err), 0) self.assertFalse(pi.IsInstanceable()) self.assertEqual(pi.ComputePrimChildNames(), (['RefChild', 'DirectChild'], [])) with Pcp._TestChangeProcessor(pcp) as cp: parentSpec.instanceable = True self.assertEqual(cp.GetSignificantChanges(), ['/Parent']) self.assertEqual(cp.GetSpecChanges(), []) self.assertEqual(cp.GetPrimChanges(), []) # After being made an instance, DirectChild should no longer # be reported as a name child since instances may not introduce # new prims locally. (pi, err) = pcp.ComputePrimIndex('/Parent') self.assertEqual(len(err), 0) self.assertTrue(pi.IsInstanceable()) self.assertEqual(pi.ComputePrimChildNames(), (['RefChild'], [])) with Pcp._TestChangeProcessor(pcp) as cp: parentSpec.instanceable = False self.assertEqual(cp.GetSignificantChanges(), ['/Parent']) self.assertEqual(cp.GetSpecChanges(), []) self.assertEqual(cp.GetPrimChanges(), []) # Flipping the instance flag back should restore us to the # original state. (pi, err) = pcp.ComputePrimIndex('/Parent') self.assertEqual(len(err), 0) self.assertFalse(pi.IsInstanceable()) self.assertEqual(pi.ComputePrimChildNames(), (['RefChild', 'DirectChild'], []))
def test_Basic(self): # Create a PcpCache for a reference chain, but do not perform any actual # composition before querying its used layers. Verify that this does not crash. file = 'BasicReference/root.sdf' self.assertTrue(os.path.isfile(file)) layer = Sdf.Layer.FindOrOpen(file) self.assertTrue(layer) lsi = Pcp.LayerStackIdentifier(layer) self.assertTrue(lsi) pcpCache = Pcp.Cache(lsi) self.assertTrue(pcpCache) pcpCache.GetUsedLayers() # Create a PcpCache with a target schema, ensuring that layers # without the correct target will be marked invalid during composition. pcpCache = Pcp.Cache(lsi, targetSchema='sdf') (pi, _) = pcpCache.ComputePrimIndex('/PrimWithReferences') self.assertTrue(pi.IsValid()) self.assertEqual(len(pi.localErrors), 0) # XXX: Sdf currently emits coding errors when it cannot find a file format # for the given target. I'm not sure this should be the case; it # probably should treat it as though the file didn't exist, which # does not emit errors. pcpCache = Pcp.Cache(lsi, targetSchema='Presto') with self.assertRaises(Tf.ErrorException): pcpCache.ComputePrimIndex('/PrimWithReferences') # Should be two local errors corresponding to invalid asset paths, # since this prim has two references to layers with a different target # schema. (pi, _) = pcpCache.ComputePrimIndex('/PrimWithReferences') self.assertTrue(pi.IsValid()) self.assertEqual(len(pi.localErrors), 2) self.assertTrue(all([(isinstance(e, Pcp.ErrorInvalidAssetPath) for e in pi.localErrors)]))
def test_Basic(self): rootLayer = Sdf.Layer.FindOrOpen('bug82180/root.sdf') sessionLayer = Sdf.Layer.CreateAnonymous() pcpCache = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer, sessionLayer)) # Compute the cache's root layer stack and verify its contents. (layerStack, errors) = \ pcpCache.ComputeLayerStack(pcpCache.GetLayerStackIdentifier()) self.assertTrue(layerStack) self.assertEqual(layerStack.layers, [sessionLayer, rootLayer]) self.assertEqual( layerStack.relocatesSourceToTarget, {Sdf.Path('/ModelGroup/Model'): Sdf.Path('/ModelGroup/Model_1')}) self.assertEqual( layerStack.relocatesTargetToSource, {Sdf.Path('/ModelGroup/Model_1'): Sdf.Path('/ModelGroup/Model')}) self.assertEqual(len(errors), 0) # Now add an empty sublayer to the session layer, which should be regarded # as an insignificant layer stack change. # # Note that this bug isn't specific to the session layer; it occurred with # any insignificant layer stack change. The test just uses the session layer # since that's the repro steps from the bug report. emptyLayer = Sdf.Layer.FindOrOpen('bug82180/empty.sdf') with Pcp._TestChangeProcessor(pcpCache): sessionLayer.subLayerPaths.insert(0, emptyLayer.identifier) # Verify that the layer stack's contents are still as expect; in particular, # the relocations should be unaffected. (layerStack, errors) = \ pcpCache.ComputeLayerStack(pcpCache.GetLayerStackIdentifier()) self.assertTrue(layerStack) self.assertEqual(layerStack.layers, [sessionLayer, emptyLayer, rootLayer]) self.assertEqual( layerStack.relocatesSourceToTarget, {Sdf.Path('/ModelGroup/Model'): Sdf.Path('/ModelGroup/Model_1')}) self.assertEqual( layerStack.relocatesTargetToSource, {Sdf.Path('/ModelGroup/Model_1'): Sdf.Path('/ModelGroup/Model')}) self.assertEqual(len(errors), 0)
def test_VariantChanges(self): rootLayer = Sdf.Layer.CreateAnonymous() modelSpec = Sdf.PrimSpec(rootLayer, 'Variant', Sdf.SpecifierDef) pcp = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer), usd=True) # Test changes that are emitted as a variant set and variant # are created. pcp.ComputePrimIndex('/Variant') with Pcp._TestChangeProcessor(pcp) as cp: varSetSpec = Sdf.VariantSetSpec(modelSpec, 'test') self.assertEqual(cp.GetSignificantChanges(), ['/Variant']) self.assertEqual(cp.GetSpecChanges(), []) self.assertEqual(cp.GetPrimChanges(), []) pcp.ComputePrimIndex('/Variant') with Pcp._TestChangeProcessor(pcp) as cp: modelSpec.variantSelections['test'] = 'A' self.assertEqual(cp.GetSignificantChanges(), ['/Variant']) self.assertEqual(cp.GetSpecChanges(), []) self.assertEqual(cp.GetPrimChanges(), []) pcp.ComputePrimIndex('/Variant') with Pcp._TestChangeProcessor(pcp) as cp: modelSpec.variantSetNameList.Add('test') self.assertEqual(cp.GetSignificantChanges(), ['/Variant']) self.assertEqual(cp.GetSpecChanges(), []) self.assertEqual(cp.GetPrimChanges(), []) pcp.ComputePrimIndex('/Variant') with Pcp._TestChangeProcessor(pcp) as cp: varSpec = Sdf.VariantSpec(varSetSpec, 'A') self.assertEqual(cp.GetSignificantChanges(), []) self.assertEqual(cp.GetSpecChanges(), ['/Variant']) # Creating the variant spec adds an inert spec to /Variant's prim # stack but does not require rebuilding /Variant's prim index to # account for the new variant node. self.assertEqual(cp.GetPrimChanges(), []) pcp.ComputePrimIndex('/Variant') with Pcp._TestChangeProcessor(pcp) as cp: varSpec.primSpec.referenceList.Add( Sdf.Reference('./dummy.sdf', '/Dummy')) self.assertEqual(cp.GetSignificantChanges(), ['/Variant']) self.assertEqual(cp.GetSpecChanges(), []) self.assertEqual(cp.GetPrimChanges(), [])
def test_InvalidSublayerRemoval(self): invalidSublayerId = "/tmp/testPcpChanges_invalidSublayer.sdf" layer = Sdf.Layer.CreateAnonymous() layer.subLayerPaths.append(invalidSublayerId) layerStackId = Pcp.LayerStackIdentifier(layer) pcp = Pcp.Cache(layerStackId) self.assertEqual(len(pcp.ComputeLayerStack(layerStackId)[1]), 1) self.assertTrue(pcp.IsInvalidSublayerIdentifier(invalidSublayerId)) with Pcp._TestChangeProcessor(pcp): layer.subLayerPaths.remove(invalidSublayerId) self.assertEqual(len(pcp.ComputeLayerStack(layerStackId)[1]), 0) self.assertFalse(pcp.IsInvalidSublayerIdentifier(invalidSublayerId))
def _FindSiteDeps(self, rootLayerPath, siteLayerPath, sitePath, depMask = Pcp.DependencyTypeAnyNonVirtual, recurseOnSite = False, recurseOnIndex = False): sitePath = Sdf.Path(sitePath) self.assertFalse(sitePath.isEmpty) rootLayer = Sdf.Layer.FindOrOpen(rootLayerPath) self.assertTrue(rootLayer) siteLayer = Sdf.Layer.FindOrOpen(siteLayerPath) self.assertTrue(siteLayer) cache = Pcp.Cache( Pcp.LayerStackIdentifier(rootLayer) ) siteLayerStack = cache.ComputeLayerStack( Pcp.LayerStackIdentifier(siteLayer))[0] self.assertTrue(siteLayerStack) self._ForcePopulateCache(cache) return cache.FindSiteDependencies( siteLayerStack, sitePath, depMask, recurseOnSite, recurseOnIndex, False )
def test_UnusedVariantChanges(self): layer = Sdf.Layer.CreateAnonymous() parent = Sdf.PrimSpec(layer, 'Root', Sdf.SpecifierDef, 'Scope') vA = Sdf.CreateVariantInLayer(layer, parent.path, 'var', 'A') vB = Sdf.CreateVariantInLayer(layer, parent.path, 'var', 'B') parent.variantSelections['var'] = 'A' layerStackId = Pcp.LayerStackIdentifier(layer) pcp = Pcp.Cache(layerStackId) (pi, err) = pcp.ComputePrimIndex('/Root') self.assertTrue(pi) self.assertEqual(len(err), 0) # Add a new prim spec inside the unused variant and verify that this # does not cause the cached prim index to be blown. with Pcp._TestChangeProcessor(pcp): newPrim = Sdf.PrimSpec(vB.primSpec, 'Child', Sdf.SpecifierDef, 'Scope') self.assertTrue(pcp.FindPrimIndex('/Root'))
def test_InternalReferenceChanges(self): rootLayer = Sdf.Layer.CreateAnonymous() Sdf.PrimSpec(rootLayer, 'target1', Sdf.SpecifierDef) Sdf.PrimSpec(rootLayer, 'target2', Sdf.SpecifierDef) srcPrimSpec = Sdf.PrimSpec(rootLayer, 'source', Sdf.SpecifierDef) srcPrimSpec.referenceList.Add(Sdf.Reference(primPath='/target1')) # Initially, the prim index for /source should contain a single # reference node to /target1 in rootLayer. pcp = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer)) (pi, err) = pcp.ComputePrimIndex('/source') self.assertEqual(len(err), 0) self.assertEqual( pi.rootNode.children[0].layerStack.identifier.rootLayer, rootLayer) self.assertEqual(pi.rootNode.children[0].path, '/target1') # Modify the internal reference to point to /target2 and verify the # reference node is updated. with Pcp._TestChangeProcessor(pcp): srcPrimSpec.referenceList.addedItems[0] = \ Sdf.Reference(primPath = '/target2') (pi, err) = pcp.ComputePrimIndex('/source') self.assertEqual(len(err), 0) self.assertEqual( pi.rootNode.children[0].layerStack.identifier.rootLayer, rootLayer) self.assertEqual(pi.rootNode.children[0].path, '/target2') # Clear out all references and verify that the prim index contains no # reference nodes. with Pcp._TestChangeProcessor(pcp): srcPrimSpec.referenceList.ClearEdits() (pi, err) = pcp.ComputePrimIndex('/source') self.assertEqual(len(err), 0) self.assertEqual(len(pi.rootNode.children), 0)
def test_InvalidSublayerAdd(self): invalidSublayerId = "/tmp/testPcpChanges_invalidSublayer.sdf" layer = Sdf.Layer.CreateAnonymous() layerStackId = Pcp.LayerStackIdentifier(layer) pcp = Pcp.Cache(layerStackId) (layerStack, errs) = pcp.ComputeLayerStack(layerStackId) self.assertEqual(len(errs), 0) self.assertEqual(len(layerStack.localErrors), 0) with Pcp._TestChangeProcessor(pcp): layer.subLayerPaths.append(invalidSublayerId) (layerStack, errs) = pcp.ComputeLayerStack(layerStackId) # This is potentially surprising. Layer stacks are recomputed # immediately during change processing, so any composition # errors generated during that process won't be reported # during the call to ComputeLayerStack. The errors will be # stored in the layer stack's localErrors field, however. self.assertEqual(len(errs), 0) self.assertEqual(len(layerStack.localErrors), 1)
def test_InertPrimChanges(self): refLayer = Sdf.Layer.CreateAnonymous() refParentSpec = Sdf.PrimSpec(refLayer, 'Parent', Sdf.SpecifierDef) refChildSpec = Sdf.PrimSpec(refParentSpec, 'Child', Sdf.SpecifierDef) rootLayer = Sdf.Layer.CreateAnonymous() parentSpec = Sdf.PrimSpec(rootLayer, 'Parent', Sdf.SpecifierOver) parentSpec.referenceList.Add( Sdf.Reference(refLayer.identifier, '/Parent')) pcp = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer)) # Adding an empty over to a prim that already exists (has specs) # is an insignificant change. (pi, err) = pcp.ComputePrimIndex('/Parent/Child') self.assertEqual(err, []) with Pcp._TestChangeProcessor(pcp) as cp: Sdf.CreatePrimInLayer(rootLayer, '/Parent/Child') self.assertEqual(cp.GetSignificantChanges(), []) self.assertEqual(cp.GetSpecChanges(), ['/Parent/Child']) self.assertEqual(cp.GetPrimChanges(), []) # Adding an empty over as the first spec for a prim is a # a significant change, even if we haven't computed a prim index # for that path yet. with Pcp._TestChangeProcessor(pcp) as cp: Sdf.CreatePrimInLayer(rootLayer, '/Parent/NewChild') self.assertEqual(cp.GetSignificantChanges(), ['/Parent/NewChild']) self.assertEqual(cp.GetSpecChanges(), []) self.assertEqual(cp.GetPrimChanges(), []) (pi, err) = pcp.ComputePrimIndex('/Parent/NewChild2') self.assertEqual(err, []) with Pcp._TestChangeProcessor(pcp) as cp: Sdf.CreatePrimInLayer(rootLayer, '/Parent/NewChild2') self.assertEqual(cp.GetSignificantChanges(), ['/Parent/NewChild2']) self.assertEqual(cp.GetSpecChanges(), []) self.assertEqual(cp.GetPrimChanges(), [])
def test_PcpCacheReloadSessionLayers(self): rootLayer = Sdf.Layer.CreateAnonymous() sessionRootLayer = Sdf.Layer.CreateAnonymous() self.assertTrue(sessionRootLayer) sessionSubLayer = Sdf.Layer.CreateAnonymous() self.assertTrue(sessionSubLayer) sessionRootLayer.subLayerPaths.append(sessionSubLayer.identifier) # Author something to the sublayer primSpec = Sdf.PrimSpec(sessionSubLayer, "Root", Sdf.SpecifierDef) self.assertTrue(sessionSubLayer.GetPrimAtPath("/Root")) # Create the Pcp structures lsi = Pcp.LayerStackIdentifier(rootLayer, sessionRootLayer) self.assertTrue(lsi) pcpCache = Pcp.Cache(lsi) self.assertTrue(pcpCache) pcpCache.ComputeLayerStack(lsi) # Now reload and make sure that the spec on the sublayer stays intact pcpCache.Reload() self.assertTrue(sessionSubLayer.GetPrimAtPath("/Root"))
def test_Basic(self): rootLayer = Sdf.Layer.FindOrOpen('bug90508/root.sdf') pcpCache = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer)) for p in [ Sdf.Path('/Model'), Sdf.Path('/Model/Child'), Sdf.Path('/Model/Child/Child2') ]: self.assertTrue(pcpCache.ComputePrimIndex(p)) self.assertTrue(pcpCache.FindPrimIndex(p)) # The prim index at /Model/Child should have an an implied inherit arc to # the site @root.sdf@</_class_Model/Child>; however, this node is culled # because there are no prim specs at that location. Adding a spec there # should cause the PcpCache to evict the prim index, since it needs to be # regenerated to accommodate the new node. However, this change doesn't # affect any other prim index, so those should remain in the cache. with Pcp._TestChangeProcessor(pcpCache): Sdf.CreatePrimInLayer(rootLayer, '/_class_Model/Child') self.assertTrue(pcpCache.FindPrimIndex('/Model')) self.assertFalse(pcpCache.FindPrimIndex('/Model/Child')) self.assertTrue(pcpCache.FindPrimIndex('/Model/Child/Child2'))
def _GetPcpCacheForLayer(self, rootLayerPath): rootLayer = Sdf.Layer.FindOrOpen(rootLayerPath) self.assertTrue(rootLayer, "Cannot open layer %s" % (rootLayerPath)) return Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer))
def _CreatePcpCache(self, rootLayer): return Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer))
# Convert backslashes to forward slashes so comparisons # against baselines work on Windows return (os.path.relpath(layer.realPath, os.path.dirname(rootLayer.realPath)).replace( "\\", "/")) def WalkNodes(node): yield node for child in node.children: for descendant in WalkNodes(child): yield descendant # Dump the layer stack. errors = [] layerStackId = Pcp.LayerStackIdentifier(rootLayer, sessionLayer) pcpCache = Pcp.Cache(layerStackId) assert pcpCache.GetVariantFallbacks() == {} pcpCache.SetVariantFallbacks(variantFallbacks) assert pcpCache.GetVariantFallbacks() == variantFallbacks (layerStackData, errors) = pcpCache.ComputeLayerStack(layerStackId) layerStack = layerStackData.layers print '-' * 72 print 'Layer Stack:' for layer in layerStack: print ' ', GetLayerLabel(layer) print '' if len(layerStackData.localErrors) > 0: PrintErrorMessage(errorFile, '-' * 72) PrintErrorMessage(errorFile, 'Errors while computing Layer Stack\n')
def _LoadPcpCache(self, layerPath): rootLayer = Sdf.Layer.FindOrOpen(layerPath) cache = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer), usd=True) return cache
def _CreatePcpCache(self, rootLayer, decorator): layerStackId = Pcp.LayerStackIdentifier(rootLayer) return Pcp.Cache(layerStackId, payloadDecorator=decorator)
def test_InstancingChangesForSubrootArcs(self): # First layer: Build up the first reference structure refLayer = Sdf.Layer.CreateAnonymous() # Base spec name space hierarchy: /Base/Child/BaseLeaf. baseSpec = Sdf.PrimSpec(refLayer, 'Base', Sdf.SpecifierDef) baseChildSpec = Sdf.PrimSpec(baseSpec, 'Child', Sdf.SpecifierDef) baseLeafSpec = Sdf.PrimSpec(baseChildSpec, 'BaseLeaf', Sdf.SpecifierDef) # /A references /Base refASpec = Sdf.PrimSpec(refLayer, 'A', Sdf.SpecifierDef) refASpec.referenceList.Add(Sdf.Reference('', '/Base')) # /B references /A refBSpec = Sdf.PrimSpec(refLayer, 'B', Sdf.SpecifierDef) refBSpec.referenceList.Add(Sdf.Reference('', '/A')) # Second layer: Same structure as layer with incmented names for clarity # when both layers have prims referenced refLayer2 = Sdf.Layer.CreateAnonymous() base2Spec = Sdf.PrimSpec(refLayer2, 'Base2', Sdf.SpecifierDef) base2ChildSpec = Sdf.PrimSpec(base2Spec, 'Child', Sdf.SpecifierDef) base2LeafSpec = Sdf.PrimSpec(base2ChildSpec, 'Base2Leaf', Sdf.SpecifierDef) # /A2 references /Base2 refA2Spec = Sdf.PrimSpec(refLayer2, 'A2', Sdf.SpecifierDef) refA2Spec.referenceList.Add(Sdf.Reference('', '/Base2')) # /B2 references /A2 refB2Spec = Sdf.PrimSpec(refLayer2, 'B2', Sdf.SpecifierDef) refB2Spec.referenceList.Add(Sdf.Reference('', '/A2')) # Root layer: # Instance spec namespace hierarchy: /Instance/Child/InstanceLeaf # /Instance references /B2. # /Instance/Child subroot references /B/Child # # What this gives us is the following prim index graph for # /Instance/Child: # # /Instance/Child --> /B/Child -a-> /A/Child -a-> /Base/Child # | # +-a-> /B2/Child -a-> /A2/Child -a-> /Base2/Child # # All reference arcs are "ancestral" except the direct reference from # /Instance/Child to /B/Child. Ancestral arcs under a direct arc are # treated differently for instancing than normal ancestral arcs. layer = Sdf.Layer.CreateAnonymous() instanceSpec = Sdf.PrimSpec(layer, 'Instance', Sdf.SpecifierDef) instanceSpec.referenceList.Add( Sdf.Reference(refLayer2.identifier, '/B2')) instanceChildSpec = Sdf.PrimSpec(instanceSpec, 'Child', Sdf.SpecifierDef) instanceChildSpec.referenceList.Add( Sdf.Reference(refLayer.identifier, '/B/Child')) instanceLeafSpec = Sdf.PrimSpec(instanceChildSpec, 'InstanceLeaf', Sdf.SpecifierDef) # Instancing is only enabled in Usd mode. pcp = Pcp.Cache(Pcp.LayerStackIdentifier(layer), usd=True) # Compute our initial prim index. It is not yet instanceable and # all leaf nodes appear when computing prim child names. (pi, err) = pcp.ComputePrimIndex('/Instance/Child') self.assertEqual(len(err), 0) self.assertFalse(pi.IsInstanceable()) self.assertEqual(pi.ComputePrimChildNames(), (['Base2Leaf', 'BaseLeaf', 'InstanceLeaf'], [])) # Helper context for verifying the change processing of the changes # affecting /Instance/Child @contextmanager def _VerifyChanges(significant=False, spec=False, prim=False): primIndexPath = '/Instance/Child' # Verify that we have a computed prim index for /Instance/Child # before making the change . self.assertTrue(pcp.FindPrimIndex(primIndexPath)) with Pcp._TestChangeProcessor(pcp) as cp: try: yield cp finally: self.assertEqual(cp.GetSignificantChanges(), [primIndexPath] if significant else []) self.assertEqual(cp.GetSpecChanges(), [primIndexPath] if spec else []) self.assertEqual(cp.GetPrimChanges(), [primIndexPath] if prim else []) # Significant and prim changes do invalidate the prim index. if significant or prim: self.assertFalse(pcp.FindPrimIndex(primIndexPath)) else: self.assertTrue(pcp.FindPrimIndex(primIndexPath)) # Add Child spec to /A. This is just a spec change to /Instance/Child # as /Instance/Child is not instanceable yet. with _VerifyChanges(spec=True): Sdf.PrimSpec(refASpec, 'Child', Sdf.SpecifierOver) # Add Child spec to /A2. This is just a spec change to /Instance/Child. with _VerifyChanges(spec=True): Sdf.PrimSpec(refA2Spec, 'Child', Sdf.SpecifierOver) # Delete both Child specs we just added. with _VerifyChanges(spec=True): del refASpec.nameChildren['Child'] with _VerifyChanges(spec=True): del refA2Spec.nameChildren['Child'] # Now set /Base/Child to instanceable which is always a significant # change. with _VerifyChanges(significant=True): baseChildSpec.instanceable = True # /Instance/Child is now instanceable. BaseLeaf is still returned by # ComputePrimChildren because the ancestral node that provides it comes # from a subtree composed for a direct subroot reference arc so it is # part of the instance. Base2Leaf comes from an actual ancestral arc so # it gets skipped when computing children as does the local child # opinion for InstanceLeaf. (pi, err) = pcp.ComputePrimIndex('/Instance/Child') self.assertEqual(len(err), 0) self.assertTrue(pi.IsInstanceable()) self.assertEqual(pi.ComputePrimChildNames(), (['BaseLeaf'], [])) # Add Child spec to /A2 again now that /Instance/Child is instanceable. # This is still just a spec change to /Instance/Child as true ancestral # nodes are ignored by the instance key. with _VerifyChanges(spec=True): Sdf.PrimSpec(refA2Spec, 'Child', Sdf.SpecifierOver) # Add Child spec to /A again. This is a significant change as /A/Child # is an ancestral node that's part of a direct arc's subtree and is # part of the instance key. with _VerifyChanges(significant=True): Sdf.PrimSpec(refASpec, 'Child', Sdf.SpecifierOver) (pi, err) = pcp.ComputePrimIndex('/Instance/Child') self.assertEqual(len(err), 0) self.assertTrue(pi.IsInstanceable()) self.assertEqual(pi.ComputePrimChildNames(), (['BaseLeaf'], []))
def test_OwnerBasics(self): """Test basic composition behaviors related to layer ownership. Note that we don't normally expect these values to be changed at runtime, but the system should still respond correctly.""" def TestResolve(expectedSourceLayer): path = "/Sphere.radius" # XXX: We create the cache from scratch each time because # Pcp doesn't yet respond to Sd notices (regarding # changes to layer ownership). When it does we # should create the cache and layer stack in # ClassSetup() and hold them as properties on self. cache = Pcp.Cache(self.layerStackId) self.assertTrue(cache) (layerStack, errors) = cache.ComputeLayerStack(self.layerStackId) self.assertEqual(len(errors), 0) self.assertTrue(layerStack) # Find the strongest layer with an opinion about the radius # default. strongestLayer = None for layer in layerStack.layers: radiusAttr = layer.GetObjectAtPath(path) if radiusAttr and radiusAttr.default: strongestLayer = layer break # Ensure the strongest layer with an opinion is the # expectedSourceLayer self.assertEqual(strongestLayer, expectedSourceLayer) # Verify that this field was read correctly, then clear it. self.assertEqual(self.userLayer.owner, "_PLACEHOLDER_") self.userLayer.owner = "" # Initially, the strongest layer's opinion should win, as usual. TestResolve(self.strongerLayer) # Make the owner of the "owned" layer the same as the owner denoted by # the session layer. Now the "owned" layer's opinion should win. self.userLayer.owner = self.sessionLayer.sessionOwner TestResolve(self.userLayer) # If we change the session's owner, the "stronger" layer should win # once again. Setting it back should produce the previous result. self.sessionLayer.sessionOwner = "_bogus_user_" TestResolve(self.strongerLayer) self.sessionLayer.sessionOwner = self.userLayer.owner TestResolve(self.userLayer) # Similarly, changing the owner of a sublayer should also let the # "stronger" layer win once again. self.userLayer.owner = "_other_bogus_user_" TestResolve(self.strongerLayer) self.userLayer.owner = self.sessionLayer.sessionOwner TestResolve(self.userLayer) # Changing both the session owner and the layer's owner to another # value should still produce the expected result. self.sessionLayer.sessionOwner = "_foo_" self.weakerLayer.owner = "_foo_" TestResolve(self.weakerLayer) # Changing the required "hasOwnedSubLayers" bit on the parent layer # (anim) should affect the results. self.assertTrue(self.animLayer.hasOwnedSubLayers) self.animLayer.hasOwnedSubLayers = False self.assertTrue(not self.animLayer.hasOwnedSubLayers) TestResolve(self.strongerLayer) self.animLayer.hasOwnedSubLayers = True self.assertTrue(self.animLayer.hasOwnedSubLayers) TestResolve(self.weakerLayer) # Having more than one sibling layer with the same owner should # be detected as an error. self.sessionLayer.sessionOwner = "_foo_" self.weakerLayer.owner = "_foo_" self.strongerLayer.owner = "_foo_" # XXX: Force the layer stack creation because Pcp doesn't # respond to Sd notices. cache = Pcp.Cache(self.layerStackId) self.assertTrue(cache) (layerStack, errors) = cache.ComputeLayerStack(self.layerStackId) for err in errors: print(err, file=sys.stderr) self.assertTrue(isinstance(err, Pcp.ErrorInvalidSublayerOwnership), "Unexpected Error: %s" % err) self.assertEqual(len(errors), 1)
def test_TcpsChanges(self): """ Tests change processing for changes that affect the time codes per second of all layers in the layer stacks of a PcpCache. """ # Use the same layers as the sublayer offset test case. rootLayerPath = 'TestSublayerOffsetChanges/root.sdf' rootSublayerPath = 'TestSublayerOffsetChanges/root-sublayer.sdf' refLayerPath = 'TestSublayerOffsetChanges/ref.sdf' refSublayerPath = 'TestSublayerOffsetChanges/ref-sublayer.sdf' ref2LayerPath = 'TestSublayerOffsetChanges/ref2.sdf' rootLayer = Sdf.Layer.FindOrOpen(rootLayerPath) sessionLayer = Sdf.Layer.CreateAnonymous() pcp = Pcp.Cache(Pcp.LayerStackIdentifier(rootLayer, sessionLayer)) (pi, err) = pcp.ComputePrimIndex('/A') self.assertTrue(pi) self.assertEqual(len(err), 0) rootSublayer = Sdf.Layer.Find(rootSublayerPath) refLayer = Sdf.Layer.Find(refLayerPath) refSublayer = Sdf.Layer.Find(refSublayerPath) ref2Layer = Sdf.Layer.Find(ref2LayerPath) # Verify the expected structure of the test asset. It should simply be # a chain of two references, with layer offsets of 100.0 and 50.0 # respectively. self.assertEqual(pi.rootNode.layerStack.layers, [sessionLayer, rootLayer, rootSublayer]) refNode = pi.rootNode.children[0] self.assertEqual(refNode.layerStack.layers, [refLayer, refSublayer]) self.assertEqual(refNode.arcType, Pcp.ArcTypeReference) self.assertEqual(refNode.mapToRoot.timeOffset, Sdf.LayerOffset(100.0)) for layer in refNode.layerStack.layers: self.assertFalse(layer.HasTimeCodesPerSecond()) self.assertEqual(layer.timeCodesPerSecond, 24.0) ref2Node = refNode.children[0] self.assertEqual(ref2Node.layerStack.layers, [ref2Layer]) self.assertEqual(ref2Node.arcType, Pcp.ArcTypeReference) self.assertEqual(ref2Node.mapToRoot.timeOffset, Sdf.LayerOffset(150.0)) for layer in ref2Node.layerStack.layers: self.assertFalse(layer.HasTimeCodesPerSecond()) self.assertEqual(layer.timeCodesPerSecond, 24.0) # Run the TCPS change suite on the root layer. tcpsToOffsets = { 12.0: (Sdf.LayerOffset(100.0, 0.5), Sdf.LayerOffset(125.0, 0.5)), 24.0: (Sdf.LayerOffset(100.0), Sdf.LayerOffset(150.0)), 48.0: (Sdf.LayerOffset(100.0, 2.0), Sdf.LayerOffset(200.0, 2.0)) } self._RunTcpsChangesForLayer(pcp, rootLayer, tcpsToOffsets, ['/']) # Run the TCPS change suite on the first reference layer. tcpsToOffsets = { 12.0: (Sdf.LayerOffset(100.0, 2.0), Sdf.LayerOffset(200.0)), 24.0: (Sdf.LayerOffset(100.0), Sdf.LayerOffset(150.0)), 48.0: (Sdf.LayerOffset(100.0, 0.5), Sdf.LayerOffset(125.0)) } self._RunTcpsChangesForLayer(pcp, refLayer, tcpsToOffsets, ['/A']) # Run the TCPS change suite on the second reference layer. tcpsToOffsets = { 12.0: (Sdf.LayerOffset(100.0), Sdf.LayerOffset(150.0, 2.0)), 24.0: (Sdf.LayerOffset(100.0), Sdf.LayerOffset(150.0)), 48.0: (Sdf.LayerOffset(100.0), Sdf.LayerOffset(150.0, 0.5)) } self._RunTcpsChangesForLayer(pcp, ref2Layer, tcpsToOffsets, ['/A']) # Run the TCPS change suite on the sublayers of the root and reference # layers. In the particular setup of these layer, TCPS of either # sublayer doesn't change the layer offsets applied to the reference # nodes, but will still cause change management to report significant # changes to prim indexes. tcpsToOffsets = { 12.0: (Sdf.LayerOffset(100.0), Sdf.LayerOffset(150.0)), 24.0: (Sdf.LayerOffset(100.0), Sdf.LayerOffset(150.0)), 48.0: (Sdf.LayerOffset(100.0), Sdf.LayerOffset(150.0)) } self._RunTcpsChangesForLayer(pcp, rootSublayer, tcpsToOffsets, ['/']) self._RunTcpsChangesForLayer(pcp, refSublayer, tcpsToOffsets, ['/A']) # Run the TCPS change suite on the session layer. tcpsToOffsets = { 12.0: (Sdf.LayerOffset(50.0, 0.5), Sdf.LayerOffset(75.0, 0.5)), 24.0: (Sdf.LayerOffset(100.0), Sdf.LayerOffset(150.0)), 48.0: (Sdf.LayerOffset(200.0, 2.0), Sdf.LayerOffset(300.0, 2.0)) } self._RunTcpsChangesForLayer(pcp, sessionLayer, tcpsToOffsets, ['/']) # Special cases for the session layer when root layer has a tcps value rootLayer.timeCodesPerSecond = 24.0 self.assertTrue(rootLayer.HasTimeCodesPerSecond()) self.assertFalse(sessionLayer.HasTimeCodesPerSecond()) with Pcp._TestChangeProcessor(pcp) as cp: # Set the session layer's FPS. This will change the session layer's # computed TCPS and is a significant change even though the overall # TCPS of the root layer stack is 24 as it is authored on the root # layer. sessionLayer.framesPerSecond = 48.0 self.assertEqual(sessionLayer.timeCodesPerSecond, 48.0) self.assertEqual(cp.GetSignificantChanges(), ['/']) self.assertFalse(pcp.FindPrimIndex('/A')) # Recompute the new prim index (pi, err) = pcp.ComputePrimIndex('/A') refNode = pi.rootNode.children[0] ref2Node = refNode.children[0] # The reference layer offsets are still the same as authored as # the root layer TCPS still matches its layer stack's overall TCPS self.assertEqual(refNode.mapToRoot.timeOffset, Sdf.LayerOffset(100.0)) self.assertEqual(ref2Node.mapToRoot.timeOffset, Sdf.LayerOffset(150.0)) # Continuing from the previous case, root layer has TCPS set to 24 and # session layer has FPS set to 48. Now we set the session TCPS to 48. # While this does not cause a TCPS change to session layer taken by # itself, this does mean that the session now overrides the overall # TCPS of the layer stack which used to come the root. We verify here # that this is a significant change and that it scales the layer offsets # to the references. self.assertFalse(sessionLayer.HasTimeCodesPerSecond()) with Pcp._TestChangeProcessor(pcp) as cp: sessionLayer.timeCodesPerSecond = 48.0 self.assertEqual(sessionLayer.timeCodesPerSecond, 48.0) self.assertEqual(cp.GetSignificantChanges(), ['/']) self.assertFalse(pcp.FindPrimIndex('/A')) # Recompute the new prim index (pi, err) = pcp.ComputePrimIndex('/A') refNode = pi.rootNode.children[0] ref2Node = refNode.children[0] self.assertEqual(refNode.mapToRoot.timeOffset, Sdf.LayerOffset(200.0, 2.0)) self.assertEqual(ref2Node.mapToRoot.timeOffset, Sdf.LayerOffset(300.0, 2.0)) # And as a parallel to the previous case, we now clear the session TCPS # again. This is still no effective change to the session layer TCPS # itself, but root layer's TCPS is once again the overall layer stack # TCPS. This is significant changes and the layer offsets return to # their original values. with Pcp._TestChangeProcessor(pcp) as cp: sessionLayer.ClearTimeCodesPerSecond() self.assertEqual(sessionLayer.timeCodesPerSecond, 48.0) self.assertEqual(cp.GetSignificantChanges(), ['/']) self.assertFalse(pcp.FindPrimIndex('/A')) # Recompute the new prim index (pi, err) = pcp.ComputePrimIndex('/A') refNode = pi.rootNode.children[0] ref2Node = refNode.children[0] # The reference layer offsets are still the same as authored as # the root layer TCPS still matches its layer stack's overall TCPS self.assertEqual(refNode.mapToRoot.timeOffset, Sdf.LayerOffset(100.0)) self.assertEqual(ref2Node.mapToRoot.timeOffset, Sdf.LayerOffset(150.0)) # One more special case. Neither session or root layers have TCPS set. # Root layer has FPS set to 48, session layer has FPS set to 24. Overall # computed TCPS of the layer stack will be 24, matching session FPS. # We then author a TCPS value of 48 to the root layer, matching its FPS # value. There is no effective change to the root layer's TCPS itself # but we do end up with a significant change as the overall layer stack # TCPS will now compute to 48. sessionLayer.ClearTimeCodesPerSecond() rootLayer.ClearTimeCodesPerSecond() sessionLayer.framesPerSecond = 24.0 rootLayer.framesPerSecond = 48.0 with Pcp._TestChangeProcessor(pcp) as cp: rootLayer.timeCodesPerSecond = 48.0 self.assertEqual(rootLayer.timeCodesPerSecond, 48.0) self.assertEqual(cp.GetSignificantChanges(), ['/']) self.assertFalse(pcp.FindPrimIndex('/A')) # Recompute the new prim index (pi, err) = pcp.ComputePrimIndex('/A') refNode = pi.rootNode.children[0] ref2Node = refNode.children[0] self.assertEqual(refNode.mapToRoot.timeOffset, Sdf.LayerOffset(100.0, 2.0)) self.assertEqual(ref2Node.mapToRoot.timeOffset, Sdf.LayerOffset(200.0, 2.0))