diff options
Diffstat (limited to 'unittests/dmxtest/dmxtest_dmeloglayers.cpp')
| -rw-r--r-- | unittests/dmxtest/dmxtest_dmeloglayers.cpp | 908 |
1 files changed, 908 insertions, 0 deletions
diff --git a/unittests/dmxtest/dmxtest_dmeloglayers.cpp b/unittests/dmxtest/dmxtest_dmeloglayers.cpp new file mode 100644 index 0000000..77626b1 --- /dev/null +++ b/unittests/dmxtest/dmxtest_dmeloglayers.cpp @@ -0,0 +1,908 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "unitlib/unitlib.h" +#include "datamodel/dmelement.h" +#include "movieobjects/movieobjects.h" +#include "datamodel/idatamodel.h" + +#include "movieobjects/dmechannel.h" +#include "movieobjects/dmelog.h" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define NUM_CHANNELS 1 +#define NUM_LOG_ENTRIES 10 + +enum +{ + SPEW_DIFFS = (1<<0), + SPEW_VALUES= (1<<1), + SPEW_KEYS= (1<<2), +}; + +static void ValidateDataSets( int spew, char const *testname, CUtlVector< CUtlVector< float > >& values, CUtlVector< CUtlVector< float > >& valuesbaked ) +{ + int i, j; + // Compare baked, unbaked values + Assert( values.Count() == valuesbaked.Count() ); + int c = values.Count(); + bool differs = false; + bool spewvalues = ( spew & SPEW_VALUES ) ? true : false; + + float tol = 0.0001f; + + for ( i = 0; i < c; ++i ) + { + CUtlVector< float >& v = values[ i ]; + CUtlVector< float >& vb = valuesbaked[ i ]; + + Assert( v.Count() == vb.Count() ); + + // Now get the values of the samples in the log + for ( j = 0; j < v.Count(); ++j ) + { + Assert( vb.IsValidIndex( j ) ); + if ( !vb.IsValidIndex( j ) ) + continue; + + float v1 = v[ j ]; + float v2 = vb[ j ]; + if ( fabs( v1 - v2 ) > tol ) + { + differs = true; + } + + if ( spewvalues ) + { + Msg( "%d %f %f\n", j, v[ j ], vb[ j ] ); + } + } + } + + Msg( " %s\n", differs ? "FAILED" : "OK" ); + + if ( !(spew & SPEW_DIFFS ) ) + return; + + for ( i = 0; i < c; ++i ) + { + CUtlVector< float >& v = values[ i ]; + CUtlVector< float >& vb = valuesbaked[ i ]; + + Assert( v.Count() == vb.Count() ); + + // Now get the values of the samples in the log + for ( j = 0; j < v.Count(); ++j ) + { + Assert( vb.IsValidIndex( j ) ); + if ( !vb.IsValidIndex( j ) ) + continue; + + if ( v[ j ] == vb[ j ] ) + { + if ( differs ) + { + Msg( "%d found %f to equal %f\n", j, v[ j ], vb[ j ] ); + } + continue; + } + + Msg( "%d expected %f to equal %f\n", j, v[ j ], vb[ j ] ); + } + } + + if ( differs ) + { + Msg( "End Test '%s'\n---------------\n", testname ); + } +} + +static void CreateChannels( int num, CUtlVector< CDmeChannel * >& channels, DmFileId_t fileid ) +{ + CDisableUndoScopeGuard guard; + + for ( int i = 0; i < num; ++i ) + { + CDmeChannel *channel = NULL; + + channel = CreateElement< CDmeChannel >( "channel1", fileid ); + channels.AddToTail( channel ); + channel->CreateLog( AT_FLOAT ); // only care about float logs for now + channel->SetMode( CM_PLAY );// Make sure it's in playback mode + } +} + +struct TestLayer_t +{ + enum + { + TYPE_SIMPLESLOPE = 0, // value == time + TYPE_SINE, // sinusoidal + TYPE_CONSTANT, + }; + + TestLayer_t() : + startTime( 0 ), + endTime( 0 ), + timeStep( 0 ), + usecurvetype( false ), + curvetype( CURVE_DEFAULT ), + type( TYPE_SIMPLESLOPE ), + constantvalue( 0.0f ) + { + } + + float ValueForTime( DmeTime_t time ) const + { + float t = (float)time.GetSeconds(); + switch ( type ) + { + default: + case TYPE_SIMPLESLOPE: + return t; + case TYPE_SINE: + return constantvalue * ( 1.0f + sin( ( t * 0.002f ) * 2 * M_PI ) ) * 0.5f; + case TYPE_CONSTANT: + return constantvalue; + } + + return t; + } + + int type; + DmeTime_t startTime; + DmeTime_t endTime; + DmeTime_t timeStep; + + bool usecurvetype; + int curvetype; + + float constantvalue; +}; + +struct TestParams_t +{ + TestParams_t() : + testundo( false ), + usecurves( false ), + purgevalues( true ), + testabort( false ), + spew( 0 ), + spewnontopmostlayers( false ), + defaultcurve( CURVE_DEFAULT ), + mintime( DmeTime_t( 0 ) ), + maxtime( DmeTime_t( 100 ) ) + { + } + int spew; + bool usecurves; + bool purgevalues; + bool testundo; + bool testabort; + bool spewnontopmostlayers; + int defaultcurve; + DmeTime_t mintime; + DmeTime_t maxtime; + CUtlVector< TestLayer_t > layers; + + void Reset() + { + purgevalues = true; + usecurves = false; + testundo = false; + testabort = false; + spewnontopmostlayers = false; + spew = 0; + mintime = DmeTime_t( 0 ); + maxtime = DmeTime_t( 100 ); + defaultcurve = CURVE_DEFAULT; + layers.RemoveAll(); + } + + void AddLayer( DmeTime_t start, DmeTime_t end, DmeTime_t step, int curvetype, int valuetype, float constantvalue = 0.0f ) + { + TestLayer_t tl; + tl.startTime = start; + tl.endTime = end; + tl.timeStep = step; + tl.curvetype = curvetype; + tl.type = valuetype; + tl.constantvalue = constantvalue; + + layers.AddToTail( tl ); + } +}; + +static void RunLayerTest( char const *testname, CUtlVector< CDmeChannel * >& channels, const TestParams_t& params ) +{ + if ( params.layers.Count() == 0 ) + { + Assert( 0 ); + return; + } + + Msg( "Test '%s'...\n", testname ); + + g_pDataModel->StartUndo( testname, testname ); + + int i; + int c = channels.Count(); + + { + CDisableUndoScopeGuard guard; + + for ( i = 0; i < NUM_CHANNELS; ++i ) + { + CDmeChannel *channel = channels[ i ]; + CDmeTypedLog< float > *pLog = CastElement< CDmeTypedLog< float > >( channel->GetLog() ); + Assert( pLog ); + pLog->ClearKeys(); // reset it + + CDmeCurveInfo *pCurveInfo = NULL; + if ( params.usecurves ) + { + pCurveInfo = pLog->GetOrCreateCurveInfo(); + pCurveInfo->SetDefaultCurveType( params.defaultcurve ); + pCurveInfo->SetMinValue( 0.0f ); + pCurveInfo->SetMaxValue( 1000.0f ); + } + else + { + if ( pLog->GetCurveInfo() ) + { + g_pDataModel->DestroyElement( pLog->GetCurveInfo()->GetHandle() ); + } + pLog->SetCurveInfo( NULL ); + } + + const TestLayer_t& tl = params.layers[ 0 ]; + // Now add entries + DmeTime_t logStep = tl.timeStep; + DmeTime_t logStart = tl.startTime; + + for ( DmeTime_t t = logStart; t <= tl.endTime + logStep - DmeTime_t( 1 ); t += logStep ) + { + DmeTime_t useTime = t; + if ( useTime > tl.endTime ) + { + useTime = tl.endTime; + } + float value = tl.ValueForTime( useTime ); + if ( tl.usecurvetype ) + { + pLog->SetKey( useTime, value, tl.curvetype ); + } + else + { + pLog->SetKey( useTime, value ); + } + } + } + } + + for ( int layer = 1; layer < params.layers.Count(); ++layer ) + { + const TestLayer_t& tl = params.layers[ layer ]; + + // Test creating a layer and collapsing it back down + g_pChannelRecordingMgr->StartLayerRecording( "layer operations" ); + for ( i = 0; i < c; ++i ) + { + g_pChannelRecordingMgr->AddChannelToRecordingLayer( channels[ i ] ); // calls log->CreateNewLayer() + } + + // Now add values to channel logs + for ( i = 0; i < c; ++i ) + { + CDmeChannel *channel = channels[ i ]; + CDmeTypedLog< float > *pLog = CastElement< CDmeTypedLog< float > >( channel->GetLog() ); + Assert( pLog ); + + // Now add entries + DmeTime_t logStep = tl.timeStep; + DmeTime_t logStart = tl.startTime; + + for ( DmeTime_t t = logStart; t <= tl.endTime + logStep - DmeTime_t( 1 ); t += logStep ) + { + DmeTime_t useTime = t; + if ( useTime > tl.endTime ) + { + useTime = tl.endTime; + } + float value = tl.ValueForTime( useTime ); + if ( tl.usecurvetype ) + { + pLog->SetKey( useTime, value, tl.curvetype ); + } + else + { + pLog->SetKey( useTime, value ); + } + } + } + + g_pChannelRecordingMgr->FinishLayerRecording( 0.0f, false ); // don't flatten layers here, we'll do it manually + } + + // Now sample values + CUtlVector< CUtlVector< float > > values; + CUtlVector< CUtlVector< float > > valuesbaked; + + for ( i = 0; i < c; ++i ) + { + CDmeChannel *channel = channels[ i ]; + CDmeTypedLog< float > *pLog = CastElement< CDmeTypedLog< float > >( channel->GetLog() ); + Assert( pLog ); + + int idx = values.AddToTail(); + + CUtlVector< float >& v = values[ idx ]; + + // Now get the values of the samples in the log + for ( DmeTime_t j = params.mintime; j <= params.maxtime; j += DmeTime_t( 1 ) ) + { + float fval = pLog->GetValue( j ); + v.AddToTail( fval ); + } + } + + if ( params.spewnontopmostlayers ) + { + for ( i = 0; i < c; ++i ) + { + CDmeChannel *channel = channels[ i ]; + CDmeTypedLog< float > *pLog = CastElement< CDmeTypedLog< float > >( channel->GetLog() ); + Assert( pLog ); + + // Now get the values of the samples in the log + for ( DmeTime_t j = params.mintime; j <= params.maxtime; j += DmeTime_t( 1 ) ) + { + float topValue = pLog->GetValue( j ); + float underlyingValue = pLog->GetValueSkippingTopmostLayer( j ); + + Msg( "t(%d) top [%f] rest [%f]\n", + j.GetTenthsOfMS(), topValue, underlyingValue ); + } + } + } + + // Now test creating a layer and "undo/redo" of the layer + if ( params.testundo ) + { + g_pDataModel->FinishUndo(); + g_pDataModel->Undo(); + g_pDataModel->Redo(); + g_pDataModel->StartUndo( testname, testname ); + } + + { + CUndoScopeGuard guard( "Bake Layers" ); + // Now bake down and resample values + for ( i = 0; i < c; ++i ) + { + CDmeChannel *channel = channels[ i ]; + CDmeTypedLog< float > *pLog = CastElement< CDmeTypedLog< float > >( channel->GetLog() ); + Assert( pLog ); + + pLog->FlattenLayers( 0.0f, params.spew & SPEW_DIFFS ); + + int idx = valuesbaked.AddToTail(); + + CUtlVector< float >& v = valuesbaked[ idx ]; + + // Now get the values of the samples in the log + for ( DmeTime_t j = params.mintime; j <= params.maxtime; j += DmeTime_t( 1 ) ) + { + float fval = pLog->GetValue( j ); + v.AddToTail( fval ); + } + } + } + + ValidateDataSets( params.spew, testname, values, valuesbaked ); + + // Now test creating a layer and "undo/redo" of the layer + if ( params.testundo ) + { + g_pDataModel->FinishUndo(); + g_pDataModel->Undo(); + g_pDataModel->Redo(); + g_pDataModel->StartUndo( testname, testname ); + } + + if ( params.testabort ) + { + g_pDataModel->AbortUndoableOperation(); + } + else + { + g_pDataModel->FinishUndo(); + } +} + +static void RunTimeSelectionTest( char const *testname, CUtlVector< CDmeChannel * >& channels, + const TestParams_t& params, DmeTime_t tHeadPosition, DmeLog_TimeSelection_t& ts, float value ) +{ + if ( params.layers.Count() == 0 ) + { + Assert( 0 ); + return; + } + + Msg( "Test '%s'...\n", testname ); + + int i, j; + int c = channels.Count(); + + if ( params.purgevalues ) + { + CDisableUndoScopeGuard guard; + + for ( i = 0; i < NUM_CHANNELS; ++i ) + { + CDmeChannel *channel = channels[ i ]; + CDmeTypedLog< float > *pLog = CastElement< CDmeTypedLog< float > >( channel->GetLog() ); + Assert( pLog ); + pLog->ClearKeys(); // reset it + + CDmeCurveInfo *pCurveInfo = params.usecurves ? pLog->GetOrCreateCurveInfo() : pLog->GetCurveInfo(); + if ( params.usecurves ) + { + pCurveInfo->SetDefaultCurveType( params.defaultcurve ); + pCurveInfo->SetMinValue( 0.0f ); + pCurveInfo->SetMaxValue( 1000.0f ); + } + else if ( !params.usecurves && pCurveInfo ) + { + g_pDataModel->DestroyElement( pCurveInfo->GetHandle() ); + pLog->SetCurveInfo( NULL ); + } + + const TestLayer_t& tl = params.layers[ 0 ]; + // Now add entries + DmeTime_t logStep = tl.timeStep; + DmeTime_t logStart = tl.startTime; + + for ( DmeTime_t t = logStart; t <= tl.endTime + logStep - DmeTime_t( 1 ); t += logStep ) + { + DmeTime_t useTime = t; + if ( useTime > tl.endTime ) + useTime = tl.endTime; + + float value = tl.ValueForTime( useTime ); + if ( tl.usecurvetype ) + { + pLog->SetKey( useTime, value, tl.curvetype ); + } + else + { + pLog->SetKey( useTime, value ); + } + } + } + } + + // Test creating a layer and collapsing it back down + g_pChannelRecordingMgr->StartLayerRecording( "layer operations", &ts ); + for ( i = 0; i < c; ++i ) + { + g_pChannelRecordingMgr->AddChannelToRecordingLayer( channels[ i ] ); // calls log->CreateNewLayer() + } + + // Now add values to channel logs + for ( i = 0; i < c; ++i ) + { + CDmeChannel *channel = channels[ i ]; + CDmeTypedLog< float > *pLog = CastElement< CDmeTypedLog< float > >( channel->GetLog() ); + Assert( pLog ); + + pLog->StampKeyAtHead( tHeadPosition, tHeadPosition, ts, value ); + } + + // Flattens the layers + g_pChannelRecordingMgr->FinishLayerRecording( 0.0f, true ); + + if ( params.spew & SPEW_VALUES ) + { + for ( i = 0; i < c; ++i ) + { + CDmeChannel *channel = channels[ i ]; + CDmeTypedLog< float > *pLog = CastElement< CDmeTypedLog< float > >( channel->GetLog() ); + Assert( pLog ); + Assert( pLog->GetNumLayers() == 1 ); + + for ( DmeTime_t j = params.mintime; j <= params.maxtime; j += DmeTime_t( 1 ) ) + { + float fval = pLog->GetValue( j ); + Msg( "%d %f\n", j.GetTenthsOfMS(), fval ); + } + } + } + + if ( params.spew & SPEW_KEYS ) + { + for ( i = 0; i < c; ++i ) + { + CDmeChannel *channel = channels[ i ]; + CDmeTypedLog< float > *pLog = CastElement< CDmeTypedLog< float > >( channel->GetLog() ); + Assert( pLog ); + Assert( pLog->GetNumLayers() == 1 ); + + int kc = pLog->GetKeyCount(); + for ( j = 0; j < kc; ++j ) + { + DmeTime_t time = pLog->GetKeyTime( j ); + + float fval = pLog->GetValue( time ); + Msg( "%d %f %f\n", j, time.GetSeconds(), fval ); + } + } + } + + // Now test creating a layer and "undo/redo" of the layer + if ( params.testundo ) + { + g_pDataModel->Undo(); + g_pDataModel->Redo(); + } +} + +DEFINE_TESTCASE_NOSUITE( DmxTestDmeLogLayers ) +{ + Msg( "Running CDmeTypedLog<float> layering tests...\n" ); + +#ifdef _DEBUG + int nStartingCount = g_pDataModel->GetAllocatedElementCount(); +#endif + + CUtlVector< CDmeChannel * > channels; + + DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( "<DmxTestDmeLogLayers>" ); + + CreateChannels( NUM_CHANNELS, channels, fileid ); + + TestParams_t params; + { + params.testundo = false; + params.usecurves = false; + params.defaultcurve = CURVE_DEFAULT; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_DEFAULT, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 5 ), DmeTime_t( 95 ), DmeTime_t( 10 ), CURVE_DEFAULT, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "One-Layer", channels, params ); + params.Reset(); + } + + // Single layer using lerp everywhere + // ----------------------- + { + params.testundo = false; + params.usecurves = true; + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "One-Layer Lerp", channels, params ); + params.Reset(); + } + + // Two layers using lerp + // ---------------------------- + // ------------------------ + { + params.testundo = false; + params.usecurves = true; + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 5 ), DmeTime_t( 95 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Two-Layer Lerp (contained)", channels, params ); + params.Reset(); + } + + // Two layers using CURVE_EASE_IN_TO_EASE_OUT, there should be some disparity + // ---------------------------- + // ------------------------ + { + params.testundo = false; + params.usecurves = true; + params.defaultcurve = CURVE_EASE_IN_TO_EASE_OUT; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_EASE_IN_TO_EASE_OUT, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 5 ), DmeTime_t( 95 ), DmeTime_t( 10 ), CURVE_EASE_IN_TO_EASE_OUT, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Two-Layer Ease In/Out (contained)", channels, params ); + params.Reset(); + } + + // Two layers using lerp + // ---------------------------- + // --------- + { + params.testundo = false; + params.usecurves = true; + params.mintime = DmeTime_t( -20 ); + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( -20 ), DmeTime_t( 20 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Two-Layer Lerp (overhang start)", channels, params ); + params.Reset(); + } + + // Two layers using lerp + // ---------------------------- + // ------------ + { + params.testundo = false; + params.usecurves = true; + params.maxtime = DmeTime_t( 120 ); + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 80 ), DmeTime_t( 120 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Two-Layer Lerp (overhang end)", channels, params ); + params.Reset(); + } + // Three layers using lerp + // ------------- + // ----- ----- + { + params.testundo = false; + params.usecurves = true; + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.mintime = DmeTime_t( -12 ); + params.maxtime = DmeTime_t( 115 ); + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( -12 ), DmeTime_t( 12 ), DmeTime_t( 4 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 85 ), DmeTime_t( 115 ), DmeTime_t( 5 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Three-Layer Lerp (overhang start + end)", channels, params ); + params.Reset(); + } + + // Three layers using lerp + // ------------- + // ----- + // -- + { + params.testundo = false; + params.usecurves = true; + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 25 ), DmeTime_t( 75 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 40 ), DmeTime_t( 60 ), DmeTime_t( 5 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Three-Layer Lerp (layer inside layer)", channels, params ); + params.Reset(); + } + + // Three layers using lerp + // ------------- + // ----- + // -- + { + params.testundo = false; + params.usecurves = true; + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 25 ), DmeTime_t( 75 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 70 ), DmeTime_t( 80 ), DmeTime_t( 2 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Three-Layer Lerp (first layer contained, second layer overlapping first at end)", channels, params ); + params.Reset(); + } + + // Three layers using lerp + // ------------- + // ----- + // -- + { + params.testundo = false; + params.usecurves = true; + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 25 ), DmeTime_t( 75 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 15 ), DmeTime_t( 35 ), DmeTime_t( 5 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Three-Layer Lerp (first layer contained, second layer overlapping first at start)", channels, params ); + params.Reset(); + } + + // Four layers using lerp + // --------------- + // ----- + // ---- + // ------- + { + params.testundo = false; + params.usecurves = true; + // params.spewnontopmostlayers = true; + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 100 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_CONSTANT, 20.0f ); + params.AddLayer( DmeTime_t( 15 ), DmeTime_t( 40 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 60 ), DmeTime_t( 85 ), DmeTime_t( 5 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + params.AddLayer( DmeTime_t( 35 ), DmeTime_t( 79 ), DmeTime_t( 5 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Four-Layer Lerp (top overlapping end of 1st and start of 2nd layer)", channels, params ); + params.Reset(); + } + + // Single layer using lerp everywhere + // ----------------------- + { + params.testundo = false; + params.usecurves = true; + params.spew = 0; //SPEW_VALUES | SPEW_KEYS; + params.mintime = DmeTime_t( 0 ); + params.maxtime = DmeTime_t( 10000 ); + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 10000 ), DmeTime_t( 20 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SINE, 100.0f ); + + DmeTime_t tHeadPosition = DmeTime_t( 5000 ); + + DmeLog_TimeSelection_t ts; + ts.m_nTimes[ TS_LEFT_FALLOFF ] = tHeadPosition + DmeTime_t( -987 ); + ts.m_nTimes[ TS_LEFT_HOLD ] = ts.m_nTimes[ TS_RIGHT_HOLD ] = tHeadPosition; + ts.m_nTimes[ TS_RIGHT_FALLOFF ] = tHeadPosition + DmeTime_t( 1052 ); + ts.m_nFalloffInterpolatorTypes[ 0 ] = ts.m_nFalloffInterpolatorTypes[ 1 ] = INTERPOLATE_EASE_INOUT; + + // Resample at 50 msec intervals + ts.m_bResampleMode = true; + ts.m_nResampleInterval = DmeTime_t( 50 ); + + ///params.spew |= SPEW_KEYS | SPEW_VALUES; + + RunTimeSelectionTest( "One-Layer Time Selection at 50, falloff 25, EASE_INOUT interp", channels, params, tHeadPosition, ts, 250 ); + + params.purgevalues = false; + // params.spew |= SPEW_VALUES; + + // Shift the head and do it all again + tHeadPosition = DmeTime_t( 2000 ); + ts.m_nTimes[ TS_LEFT_FALLOFF ] = DmeTime_t( 1487 ); + ts.m_nTimes[ TS_LEFT_HOLD ] = ts.m_nTimes[ TS_RIGHT_HOLD ] = tHeadPosition; + ts.m_nTimes[ TS_RIGHT_FALLOFF ] = tHeadPosition + DmeTime_t( 631 ); + + RunTimeSelectionTest( "2nd layer", channels, params, tHeadPosition, ts, 500 ); + params.Reset(); + } + // Single layer using lerp everywhere + // ----------------------- + { + params.testundo = true; + params.usecurves = true; + params.spew = 0; //SPEW_VALUES | SPEW_KEYS; + params.mintime = DmeTime_t( 0 ); + params.maxtime = DmeTime_t( 1000 ); + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 1000 ), DmeTime_t( 20 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_CONSTANT, 100.0f ); + + DmeTime_t tHeadPosition = DmeTime_t( 500 ); + DmeLog_TimeSelection_t ts; + ts.m_nTimes[ TS_LEFT_FALLOFF ] = tHeadPosition + DmeTime_t( -100 ); + ts.m_nTimes[ TS_LEFT_HOLD ] = ts.m_nTimes[ TS_RIGHT_HOLD ] = tHeadPosition; + ts.m_nTimes[ TS_RIGHT_FALLOFF ] = tHeadPosition + DmeTime_t( 100 ); + ts.m_nFalloffInterpolatorTypes[ 0 ] = ts.m_nFalloffInterpolatorTypes[ 1 ] = INTERPOLATE_LINEAR_INTERP; + + // Resample at 50 msec intervals + ts.m_bResampleMode = true; + ts.m_nResampleInterval = DmeTime_t( 10 ); + +// params.spew |= SPEW_VALUES; + + RunTimeSelectionTest( "Resetting layer", channels, params, tHeadPosition, ts, 200 ); + + params.purgevalues = false; + //params.spew |= SPEW_VALUES; + + // Shift the head and do it all again + //ts.m_nRelativeFalloffTimes[ 0 ] = 1487 - 2000; + //ts.m_nRelativeHoldTimes[ 0 ] = ts.m_nRelativeHoldTimes[ 1 ] = 0; + //ts.m_nRelativeFalloffTimes[ 1 ] = 631; + //ts.SetHeadPosition( 2000 ); + + RunTimeSelectionTest( "2nd layer", channels, params, tHeadPosition, ts, 110 ); + params.Reset(); + } +// g_pDataModel->TraceUndo( true ); + + // Test abort undo stuff + for ( int i = 0; i < 2; ++i ) + // Four layers using lerp + // --------------- + // ----- + // ---- + // ------- + { + params.testundo = false; + params.testabort = i != 1 ? true : false; + params.usecurves = false; + // params.spewnontopmostlayers = true; + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 10 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_CONSTANT, 20.0f ); + params.AddLayer( DmeTime_t( 5 ), DmeTime_t( 6 ), DmeTime_t( 1 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Four-Layer Lerp (top overlapping end of 1st and start of 2nd layer)", channels, params ); + params.Reset(); + } + + // g_pDataModel->TraceUndo( false ); + + + //DestroyChannels( channels ); + + g_pDataModel->ClearUndo(); + + g_pDataModel->RemoveFileId( fileid ); + +#ifdef _DEBUG + int nEndingCount = g_pDataModel->GetAllocatedElementCount(); + AssertEquals( nEndingCount, nStartingCount ); + if ( nEndingCount != nStartingCount ) + { + for ( DmElementHandle_t hElement = g_pDataModel->FirstAllocatedElement() ; + hElement != DMELEMENT_HANDLE_INVALID; + hElement = g_pDataModel->NextAllocatedElement( hElement ) ) + { + CDmElement *pElement = g_pDataModel->GetElement( hElement ); + Assert( pElement ); + if ( !pElement ) + return; + + Msg( "[%s : %s] in memory\n", pElement->GetName(), pElement->GetTypeString() ); + } + } +#endif +} + +DEFINE_TESTCASE_NOSUITE( DmxTestDmeLogLayersUndo ) +{ + Msg( "Running CDmeTypedLog<float> layering UNDO tests...\n" ); + +#ifdef _DEBUG + int nStartingCount = g_pDataModel->GetAllocatedElementCount(); +#endif + + CUtlVector< CDmeChannel * > channels; + + DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( "<DmxTestDmeLogLayersUndo>" ); + + CreateChannels( NUM_CHANNELS, channels, fileid ); + + TestParams_t params; + +// g_pDataModel->TraceUndo( true ); + + // Test abort undo stuff + for ( int i = 0; i < 2; ++i ) + { + params.testundo = false; + params.testabort = true; + params.usecurves = false; + // params.spewnontopmostlayers = true; + params.defaultcurve = CURVE_LINEAR_INTERP_TO_LINEAR_INTERP; + params.AddLayer( DmeTime_t( 0 ), DmeTime_t( 1000 ), DmeTime_t( 10 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_CONSTANT, 20.0f ); + params.AddLayer( DmeTime_t( 100 ), DmeTime_t( 900 ), DmeTime_t( 5 ), CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, TestLayer_t::TYPE_SIMPLESLOPE ); + RunLayerTest( "Abort undo", channels, params ); + params.Reset(); + } + +// g_pDataModel->TraceUndo( false ); + + g_pDataModel->ClearUndo(); + g_pDataModel->RemoveFileId( fileid ); + +#ifdef _DEBUG + int nEndingCount = g_pDataModel->GetAllocatedElementCount(); + AssertEquals( nEndingCount, nStartingCount ); + if ( nEndingCount != nStartingCount ) + { + for ( DmElementHandle_t hElement = g_pDataModel->FirstAllocatedElement() ; + hElement != DMELEMENT_HANDLE_INVALID; + hElement = g_pDataModel->NextAllocatedElement( hElement ) ) + { + CDmElement *pElement = g_pDataModel->GetElement( hElement ); + Assert( pElement ); + if ( !pElement ) + return; + + Msg( "[%s : %s] in memory\n", pElement->GetName(), pElement->GetTypeString() ); + } + } +#endif +} |