@@ -4595,5 +4595,44 @@ def testUsdVolVolumeWithEmptyField( self ) :
4595
4595
root = IECoreScene .SceneInterface .create ( fileName , IECore .IndexedIO .OpenMode .Read )
4596
4596
self .assertIsNone ( root .child ( "volume" ).readObject ( 0 ) )
4597
4597
4598
+ def testTimeCodeClamping ( self ) :
4599
+
4600
+ fileName = os .path .join ( self .temporaryDirectory (), "test.usda" )
4601
+ fileName = "test.usda"
4602
+
4603
+ # Create a stage with a fairly common timesampling setup.
4604
+ # TimeCodesPerSecond and FramesPerSecond are equal, so that integer
4605
+ # timecodes correspond to whole frames.
4606
+
4607
+ framesPerSecond = 30.0
4608
+
4609
+ stage = pxr .Usd .Stage .CreateNew ( fileName )
4610
+ stage .SetTimeCodesPerSecond ( framesPerSecond )
4611
+ stage .SetFramesPerSecond ( framesPerSecond )
4612
+
4613
+ # Keyframe a boolean value, alternating on and off each frame.
4614
+
4615
+ prim = pxr .UsdGeom .Xform .Define ( stage , "/child" )
4616
+ primVar = pxr .UsdGeom .PrimvarsAPI ( prim ).CreatePrimvar ( "test" , pxr .Sdf .ValueTypeNames .Bool )
4617
+
4618
+ frameRange = range ( 1 , 50000 )
4619
+ for frame in frameRange :
4620
+ primVar .Set ( bool ( frame % 2 ), frame )
4621
+
4622
+ stage .GetRootLayer ().Save ()
4623
+ del stage
4624
+
4625
+ # Read back the values for each frame, asserting they are as expected.
4626
+ # Because boolean values can't be interpolated, we have to hit the
4627
+ # _exact_ timecode for the frame - if we're under, then we'll get the
4628
+ # held value from the previous frame.
4629
+
4630
+ scene = IECoreScene .SceneInterface .create ( fileName , IECore .IndexedIO .OpenMode .Read )
4631
+ child = scene .child ( "child" )
4632
+
4633
+ for frame in frameRange :
4634
+ timeInSeconds = frame / framesPerSecond
4635
+ self .assertEqual ( child .readAttribute ( "render:test" , timeInSeconds ), IECore .BoolData ( frame % 2 ) )
4636
+
4598
4637
if __name__ == "__main__" :
4599
4638
unittest .main ()
0 commit comments