909 lines
26 KiB
C++
909 lines
26 KiB
C++
//========= 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
|
|
}
|