@@ -4595,5 +4595,44 @@ def testUsdVolVolumeWithEmptyField( self ) :
45954595 root = IECoreScene .SceneInterface .create ( fileName , IECore .IndexedIO .OpenMode .Read )
45964596 self .assertIsNone ( root .child ( "volume" ).readObject ( 0 ) )
45974597
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+
45984637if __name__ == "__main__" :
45994638 unittest .main ()
0 commit comments