//========= 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 layering tests...\n" ); #ifdef _DEBUG int nStartingCount = g_pDataModel->GetAllocatedElementCount(); #endif CUtlVector< CDmeChannel * > channels; DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( "" ); 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 layering UNDO tests...\n" ); #ifdef _DEBUG int nStartingCount = g_pDataModel->GetAllocatedElementCount(); #endif CUtlVector< CDmeChannel * > channels; DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( "" ); 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 }