#include "movieobjects/dmetimeselection.h" #include "interpolatortypes.h" #include "datamodel/dmelementfactoryhelper.h" // #include "dme_controls/RecordingState.h" float ComputeInterpolationFactor( float flFactor, int nInterpolatorType ); float GetAmountForTime( DmeTime_t dmetime, const TimeSelection_t ×, const int nInterpolationTypes[ 2 ] ); IMPLEMENT_ELEMENT_FACTORY( DmeTimeSelection, CDmeTimeSelection ); void CDmeTimeSelection::OnConstruction() { m_bEnabled.InitAndSet( this, "enabled", false ); m_bRelative.InitAndSet( this, "relative", false ); DmeTime_t one( 1.0f ); m_falloff[ 0 ].InitAndSet( this, "falloff_left", -one ); m_falloff[ 1 ].InitAndSet( this, "falloff_right", one ); m_hold[ 0 ].Init( this, "hold_left" ); m_hold[ 1 ].Init( this, "hold_right" ); m_nFalloffInterpolatorType[ 0 ].InitAndSet( this, "interpolator_left", INTERPOLATE_LINEAR_INTERP ); m_nFalloffInterpolatorType[ 1 ].InitAndSet( this, "interpolator_right", INTERPOLATE_LINEAR_INTERP ); m_threshold.InitAndSet( this, "threshold", 0.0005f ); m_resampleInterval.InitAndSet( this, "resampleinterval", DmeTime_t( 100 ) ); // 10 ms m_nRecordingState.InitAndSet( this, "recordingstate", 3 /*AS_PLAYBACK : HACK THIS SHOULD MOVE TO A PUBLIC HEADER*/ ); } void CDmeTimeSelection::OnDestruction() { } float CDmeTimeSelection::AdjustFactorForInterpolatorType( float factor, int side ) { return ComputeInterpolationFactor( factor, GetFalloffInterpolatorType( side ) ); } //----------------------------------------------------------------------------- // per-type averaging methods //----------------------------------------------------------------------------- float CDmeTimeSelection::GetAmountForTime( DmeTime_t t, DmeTime_t curtime ) { Assert( IsEnabled() ); TimeSelection_t times; times[ 0 ] = GetAbsFalloff( curtime, 0 ); times[ 1 ] = GetAbsHold( curtime, 0 ); times[ 2 ] = GetAbsHold( curtime, 1 ); times[ 3 ] = GetAbsFalloff( curtime, 1 ); int nInterpolatorTypes[ 2 ] = { m_nFalloffInterpolatorType[0], m_nFalloffInterpolatorType[1] }; return ::GetAmountForTime( t, times, nInterpolatorTypes ); } void CDmeTimeSelection::GetAlphaForTime( DmeTime_t t, DmeTime_t curtime, byte& alpha ) { Assert( IsEnabled() ); byte minAlpha = 31; if ( alpha <= minAlpha ) return; float f = GetAmountForTime( t, curtime ); alpha = ( byte )( f * ( alpha - minAlpha ) + minAlpha ); alpha = clamp( alpha, minAlpha, 255 ); } int CDmeTimeSelection::GetFalloffInterpolatorType( int side ) const { return m_nFalloffInterpolatorType[ side ]; } void CDmeTimeSelection::SetFalloffInterpolatorType( int side, int interpolatorType ) { m_nFalloffInterpolatorType[ side ] = interpolatorType; } bool CDmeTimeSelection::IsEnabled() const { return m_bEnabled; } void CDmeTimeSelection::SetEnabled( bool state ) { m_bEnabled = state; } bool CDmeTimeSelection::IsRelative() const { return m_bRelative; } void CDmeTimeSelection::SetRelative( DmeTime_t time, bool state ) { Assert( !IsSuspicious( true ) ); bool changed = m_bRelative != state; m_bRelative = state; if ( changed ) { if ( state ) ConvertToRelative( time ); else ConvertToAbsolute( time ); } Assert( !IsSuspicious( true ) ); } DmeTime_t CDmeTimeSelection::GetAbsFalloff( DmeTime_t time, int side ) const { if ( IsInfinite( side ) ) { return m_falloff[ side ]; } return m_bRelative ? m_falloff[ side ].Get() + time : m_falloff[ side ]; } DmeTime_t CDmeTimeSelection::GetAbsHold( DmeTime_t time, int side ) const { if ( IsInfinite( side ) ) { return m_hold[ side ]; } return m_bRelative ? m_hold[ side ].Get() + time : m_hold[ side ]; } DmeTime_t CDmeTimeSelection::GetRelativeFalloff( DmeTime_t time, int side ) const { if ( IsInfinite( side ) ) { return m_falloff[ side ]; } return m_bRelative ? m_falloff[ side ] : m_falloff[ side ].Get() - time; } DmeTime_t CDmeTimeSelection::GetRelativeHold( DmeTime_t time, int side ) const { if ( IsInfinite( side ) ) { return m_hold[ side ]; } return m_bRelative ? m_hold[ side ] : m_hold[ side ].Get() - time; } void CDmeTimeSelection::ConvertToRelative( DmeTime_t time ) { Assert( !IsSuspicious( true ) ); for ( int side = 0; side < 2; ++side ) { if ( !IsInfinite( side ) ) { m_falloff[ side ] -= time; m_hold[ side ] -= time; } } Assert( !IsSuspicious( true ) ); } void CDmeTimeSelection::ConvertToAbsolute( DmeTime_t time ) { Assert( !IsSuspicious( true ) ); for ( int side = 0; side < 2; ++side ) { if ( !IsInfinite( side ) ) { m_falloff[ side ] += time; m_hold[ side ] += time; } } Assert( !IsSuspicious( true ) ); } void CDmeTimeSelection::SetAbsFalloff( DmeTime_t time, int side, DmeTime_t absfallofftime ) { // If going to infinite edge, don't need to remember the time delta in relative mode, so zero it if ( absfallofftime == DMETIME_MAXTIME || absfallofftime == DMETIME_MINTIME ) { time = DMETIME_ZERO; } m_falloff[ side ] = m_bRelative ? absfallofftime - time : absfallofftime; Assert( !IsSuspicious() ); } void CDmeTimeSelection::SetAbsHold( DmeTime_t time, int side, DmeTime_t absholdtime ) { // If going to infinite edge, don't need to remember the time delta in relative mode, so zero it if ( absholdtime == DMETIME_MAXTIME || absholdtime == DMETIME_MINTIME ) { time = DMETIME_ZERO; } m_hold[ side ] = m_bRelative ? absholdtime - time : absholdtime; Assert( !IsSuspicious() ); } void CDmeTimeSelection::CopyFrom( const CDmeTimeSelection& src ) { m_bEnabled = src.m_bEnabled; m_bRelative = src.m_bRelative; m_threshold = src.m_threshold; for ( int i = 0 ; i < 2; ++i ) { m_falloff[ i ] = src.m_falloff[ i ]; m_hold[ i ] = src.m_hold[ i ]; m_nFalloffInterpolatorType[ i ] = src.m_nFalloffInterpolatorType[ i ]; } Assert( !IsSuspicious( true ) ); m_nRecordingState = src.m_nRecordingState; } void CDmeTimeSelection::GetAbsTimes( DmeTime_t time, DmeTime_t pTimes[TS_TIME_COUNT] ) const { if ( m_bRelative ) { pTimes[TS_LEFT_FALLOFF ] = GetRelativeFalloff( time, 0 ); pTimes[TS_LEFT_HOLD ] = GetRelativeHold( time, 0 ); pTimes[TS_RIGHT_HOLD ] = GetRelativeHold( time, 1 ); pTimes[TS_RIGHT_FALLOFF] = GetRelativeFalloff( time, 1 ); return; } pTimes[TS_LEFT_FALLOFF ] = m_falloff[ 0 ]; pTimes[TS_LEFT_HOLD ] = m_hold [ 0 ]; pTimes[TS_RIGHT_HOLD ] = m_hold [ 1 ]; pTimes[TS_RIGHT_FALLOFF] = m_falloff[ 1 ]; } void CDmeTimeSelection::GetCurrent( DmeTime_t pTimes[TS_TIME_COUNT] ) const { pTimes[TS_LEFT_FALLOFF ] = m_falloff[ 0 ]; pTimes[TS_LEFT_HOLD ] = m_hold [ 0 ]; pTimes[TS_RIGHT_HOLD ] = m_hold [ 1 ]; pTimes[TS_RIGHT_FALLOFF] = m_falloff[ 1 ]; } void CDmeTimeSelection::SetCurrent( const TimeSelection_t × ) { m_falloff[ 0 ] = times[ TS_LEFT_FALLOFF ]; m_hold [ 0 ] = times[ TS_LEFT_HOLD ]; m_hold [ 1 ] = times[ TS_RIGHT_HOLD ]; m_falloff[ 1 ] = times[ TS_RIGHT_FALLOFF ]; Assert( !IsSuspicious( true ) ); } float CDmeTimeSelection::GetThreshold() const { return m_threshold; } void CDmeTimeSelection::SetThreshold( float threshold ) { m_threshold = threshold; } DmeTime_t CDmeTimeSelection::GetResampleInterval() const { return m_resampleInterval.Get(); } void CDmeTimeSelection::SetResampleInterval( DmeTime_t resampleInterval ) { m_resampleInterval.Set( resampleInterval ); } void CDmeTimeSelection::SetRecordingState( RecordingState_t state ) { m_nRecordingState = ( int )state; } RecordingState_t CDmeTimeSelection::GetRecordingState() const { return ( RecordingState_t )m_nRecordingState.Get(); } void CDmeTimeSelection::GetTimeSelectionTimes( DmeTime_t curtime, DmeTime_t t[ TS_TIME_COUNT ] ) const { t[0] = GetAbsFalloff( curtime, 0 ); t[1] = GetAbsHold ( curtime, 0 ); t[2] = GetAbsHold ( curtime, 1 ); t[3] = GetAbsFalloff( curtime, 1 ); } void CDmeTimeSelection::SetTimeSelectionTimes( DmeTime_t curtime, DmeTime_t t[ TS_TIME_COUNT ] ) { SetAbsFalloff( curtime, 0, t[0] ); SetAbsHold ( curtime, 0, t[1] ); SetAbsHold ( curtime, 1, t[2] ); SetAbsFalloff( curtime, 1, t[3] ); Assert( !IsSuspicious( true ) ); } bool CDmeTimeSelection::IsInfinite( int side ) const { if ( side == 0 ) { return m_hold[ side ] == DMETIME_MINTIME; } else if ( side == 1 ) { return m_hold[ side ] == DMETIME_MAXTIME; } // Shouldn't get here Assert( 0 ); return false; } void CDmeTimeSelection::GetInfinite( bool bInfinite[ 2 ] ) const { bInfinite[ 0 ] = IsInfinite( 0 ); bInfinite[ 1 ] = IsInfinite( 1 ); } bool CDmeTimeSelection::IsFullyInfinite() const { return ( m_hold[ 0 ] == DMETIME_MINTIME ) && ( m_hold[ 1 ] == DMETIME_MAXTIME ); } bool CDmeTimeSelection::IsEitherInfinite() const { return ( m_hold[ 0 ] == DMETIME_MINTIME ) || ( m_hold[ 1 ] == DMETIME_MAXTIME ); } void CDmeTimeSelection::SetInfinite( int side ) { if ( side == 0 ) { m_hold[ side ] = DMETIME_MINTIME; m_falloff[ side ] = DMETIME_MINTIME; } else if ( side == 1 ) { m_hold[ side ] = DMETIME_MAXTIME; m_falloff[ side ] = DMETIME_MAXTIME; } else { Assert( 0 ); } } bool CDmeTimeSelection::IsSuspicious( bool bCheckHoldAndFalloff /*= false*/ ) { DmeTime_t t[ TS_TIME_COUNT ]; GetAbsTimes( DMETIME_ZERO, t ); DmeTime_t bounds[ 2 ] = { ( DMETIME_MINTIME + DmeTime_t( 1000.0f ) ), ( DMETIME_MAXTIME - DmeTime_t( 1000.0f ) ) }; for ( int i = 0; i < 4 ; ++i ) { if ( t[ i ] == DMETIME_MINTIME || t[ i ] == DMETIME_MAXTIME ) continue; if ( t[ i ] < bounds[ 0 ] || t[ i ] > bounds[ 1 ] ) return true; } if ( bCheckHoldAndFalloff ) { // Also check for mismatched edges if infinite bool bEdgesInfinite[ 4 ] = { t[ TS_LEFT_FALLOFF ] == DMETIME_MINTIME, t[ TS_LEFT_HOLD ] == DMETIME_MINTIME, t[ TS_RIGHT_HOLD ] == DMETIME_MAXTIME, t[ TS_RIGHT_FALLOFF ] == DMETIME_MAXTIME, }; if ( ( bEdgesInfinite[ 0 ] ^ bEdgesInfinite[ 1 ] ) || ( bEdgesInfinite[ 2 ] ^ bEdgesInfinite[ 3 ] ) ) { return true; } } return false; } DmeTime_t CDmeTimeSelection::GetAbsTime( DmeTime_t time, int tsType ) const { switch ( tsType ) { default: break; case TS_LEFT_FALLOFF: return GetAbsFalloff( time, 0 ); case TS_LEFT_HOLD: return GetAbsHold( time, 0 ); case TS_RIGHT_HOLD: return GetAbsHold( time, 1 ); case TS_RIGHT_FALLOFF: return GetAbsFalloff( time, 1 ); } Assert( 0 ); return DMETIME_ZERO; } DmeTime_t CDmeTimeSelection::GetRelativeTime( DmeTime_t time, int tsType ) const { switch ( tsType ) { default: break; case TS_LEFT_FALLOFF: return GetRelativeFalloff( time, 0 ); case TS_LEFT_HOLD: return GetRelativeHold( time, 0 ); case TS_RIGHT_HOLD: return GetRelativeHold( time, 1 ); case TS_RIGHT_FALLOFF: return GetRelativeFalloff( time, 1 ); } Assert( 0 ); return DMETIME_ZERO; } void CDmeTimeSelection::SetAbsTime( DmeTime_t time, int tsType, DmeTime_t absTime ) { switch ( tsType ) { default: Assert( 0 ); break; case TS_LEFT_FALLOFF: SetAbsFalloff( time, 0, absTime ); break; case TS_LEFT_HOLD: SetAbsHold( time, 0, absTime ); break; case TS_RIGHT_HOLD: SetAbsHold( time, 1, absTime ); break; case TS_RIGHT_FALLOFF: SetAbsFalloff( time, 1, absTime ); break; } Assert( !IsSuspicious() ); }