From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/game/shared/choreoevent.cpp | 9028 ++++++++++++++++++------------------ 1 file changed, 4514 insertions(+), 4514 deletions(-) (limited to 'mp/src/game/shared/choreoevent.cpp') diff --git a/mp/src/game/shared/choreoevent.cpp b/mp/src/game/shared/choreoevent.cpp index ef9058c8..50755f04 100644 --- a/mp/src/game/shared/choreoevent.cpp +++ b/mp/src/game/shared/choreoevent.cpp @@ -1,4514 +1,4514 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "tier0/dbg.h" -#include -#include -#include -#include "choreoevent.h" -#include "choreoactor.h" -#include "choreochannel.h" -#include "minmax.h" -#include "mathlib/mathlib.h" -#include "tier1/strtools.h" -#include "choreoscene.h" -#include "ichoreoeventcallback.h" -#include "tier1/utlbuffer.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -int CChoreoEvent::s_nGlobalID = 1; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *owner - -// *name - -// percentage - -//----------------------------------------------------------------------------- -CEventRelativeTag::CEventRelativeTag( CChoreoEvent *owner, const char *name, float percentage ) -{ - Assert( owner ); - Assert( name ); - Assert( percentage >= 0.0f ); - Assert( percentage <= 1.0f ); - - m_Name = name; - m_flPercentage = percentage; - m_pOwner = owner; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -CEventRelativeTag::CEventRelativeTag( const CEventRelativeTag& src ) -{ - m_Name = src.m_Name; - m_flPercentage = src.m_flPercentage; - m_pOwner = src.m_pOwner; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CEventRelativeTag::GetName( void ) -{ - return m_Name.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CEventRelativeTag::GetPercentage( void ) -{ - return m_flPercentage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : percentage - -//----------------------------------------------------------------------------- -void CEventRelativeTag::SetPercentage( float percentage ) -{ - m_flPercentage = percentage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CEventRelativeTag::GetOwner( void ) -{ - return m_pOwner; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventRelativeTag::SetOwner( CChoreoEvent *event ) -{ - m_pOwner = event; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the corrected time based on the owner's length and start time -// Output : float -//----------------------------------------------------------------------------- -float CEventRelativeTag::GetStartTime( void ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return 0.0f; - } - - float ownerstart = m_pOwner->GetStartTime(); - float ownerduration = m_pOwner->GetDuration(); - - return ( ownerstart + ownerduration * m_flPercentage ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *owner - -// *name - -// percentage - -//----------------------------------------------------------------------------- -CFlexTimingTag::CFlexTimingTag( CChoreoEvent *owner, const char *name, float percentage, bool locked ) -: BaseClass( owner, name, percentage ) -{ - m_bLocked = locked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -CFlexTimingTag::CFlexTimingTag( const CFlexTimingTag& src ) -: BaseClass( src ) -{ - m_bLocked = src.m_bLocked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFlexTimingTag::GetLocked( void ) -{ - return m_bLocked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : locked - -//----------------------------------------------------------------------------- -void CFlexTimingTag::SetLocked( bool locked ) -{ - m_bLocked = locked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *owner - -// *name - -// percentage - -//----------------------------------------------------------------------------- -CEventAbsoluteTag::CEventAbsoluteTag( CChoreoEvent *owner, const char *name, float t ) -{ - Assert( owner ); - Assert( name ); - Assert( t >= 0.0f ); - - m_Name = name; - m_flPercentage = t; - m_pOwner = owner; - m_bLocked = false; - m_bLinear = false; - m_bEntry = false; - m_bExit = false; - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -CEventAbsoluteTag::CEventAbsoluteTag( const CEventAbsoluteTag& src ) -{ - m_Name = src.m_Name; - m_flPercentage = src.m_flPercentage; - m_pOwner = src.m_pOwner; - m_bLocked = src.m_bLocked; - m_bLinear = src.m_bLinear; - m_bEntry = src.m_bEntry; - m_bExit = src.m_bExit; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CEventAbsoluteTag::GetName( void ) -{ - return m_Name.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CEventAbsoluteTag::GetPercentage( void ) -{ - return m_flPercentage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : percentage - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetPercentage( float percentage ) -{ - m_flPercentage = percentage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CEventAbsoluteTag::GetEventTime( void ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return 0.0f; - } - - float ownerduration = m_pOwner->GetDuration(); - - return (m_flPercentage * ownerduration); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : percentage - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetEventTime( float t ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return; - } - - float ownerduration = m_pOwner->GetDuration(); - - m_flPercentage = (t / ownerduration); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CEventAbsoluteTag::GetAbsoluteTime( void ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return 0.0f; - } - - float ownerstart = m_pOwner->GetStartTime(); - float ownerduration = m_pOwner->GetDuration(); - - return (ownerstart + m_flPercentage * ownerduration); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : percentage - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetAbsoluteTime( float t ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return; - } - - float ownerstart = m_pOwner->GetStartTime(); - float ownerduration = m_pOwner->GetDuration(); - - m_flPercentage = (t - ownerstart) / ownerduration; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CEventAbsoluteTag::GetOwner( void ) -{ - return m_pOwner; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetOwner( CChoreoEvent *event ) -{ - m_pOwner = event; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetLocked( bool bLocked ) -{ - m_bLocked = bLocked; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -bool CEventAbsoluteTag::GetLocked( void ) -{ - return m_bLocked; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetLinear( bool bLinear ) -{ - m_bLinear = bLinear; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -bool CEventAbsoluteTag::GetLinear( void ) -{ - return m_bLinear; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetEntry( bool bEntry ) -{ - m_bEntry = bEntry; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -bool CEventAbsoluteTag::GetEntry( void ) -{ - return m_bEntry; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetExit( bool bExit ) -{ - m_bExit = bExit; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -bool CEventAbsoluteTag::GetExit( void ) -{ - return m_bExit; -} - - - - -// FLEX ANIMATIONS -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : *event - -//----------------------------------------------------------------------------- -CFlexAnimationTrack::CFlexAnimationTrack( CChoreoEvent *event ) -{ - m_pEvent = event; - m_pControllerName = NULL; - m_bActive = false; - m_bCombo = false; - m_bServerSide = false; - m_nFlexControllerIndex[ 0 ] = m_nFlexControllerIndex[ 1 ] = -1; - m_nFlexControllerIndexRaw[ 0 ] = m_nFlexControllerIndexRaw[ 1 ] = LocalFlexController_t(-1); - - // base track has range, combo is always 0..1 - m_flMin = 0.0f; - m_flMax = 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -CFlexAnimationTrack::CFlexAnimationTrack( const CFlexAnimationTrack* src ) -{ - m_pControllerName = NULL; - SetFlexControllerName( src->m_pControllerName ? src->m_pControllerName : "" ); - - m_bActive = src->m_bActive; - m_bCombo = src->m_bCombo; - m_bServerSide = src->m_bServerSide; - - for ( int t = 0; t < 2; t++ ) - { - m_Samples[ t ].Purge(); - for ( int i = 0 ;i < src->m_Samples[ t ].Size(); i++ ) - { - CExpressionSample s = src->m_Samples[ t ][ i ]; - m_Samples[ t ].AddToTail( s ); - } - } - - for ( int side = 0; side < 2; side++ ) - { - m_nFlexControllerIndex[ side ] = src->m_nFlexControllerIndex[ side ]; - m_nFlexControllerIndexRaw[ side ] = src->m_nFlexControllerIndexRaw[ side ]; - } - - m_flMin = src->m_flMin; - m_flMax = src->m_flMax; - - m_EdgeInfo[ 0 ] = src->m_EdgeInfo[ 0 ]; - m_EdgeInfo[ 1 ] = src->m_EdgeInfo[ 1 ]; - - m_pEvent = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFlexAnimationTrack::~CFlexAnimationTrack( void ) -{ - delete[] m_pControllerName; - - for ( int t = 0; t < 2; t++ ) - { - m_Samples[ t ].Purge(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetEvent( CChoreoEvent *event ) -{ - m_pEvent = event; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::Clear( void ) -{ - for ( int t = 0; t < 2; t++ ) - { - m_Samples[ t ].RemoveAll(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::RemoveSample( int index, int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - m_Samples[ type ].Remove( index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetFlexControllerName( const char *name ) -{ - delete[] m_pControllerName; - int len = Q_strlen( name ) + 1; - m_pControllerName = new char[ len ]; - Q_strncpy( m_pControllerName, name, len ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -const char *CFlexAnimationTrack::GetFlexControllerName( void ) -{ - return m_pControllerName ? m_pControllerName : ""; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CFlexAnimationTrack::GetNumSamples( int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - return m_Samples[ type ].Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : CExpressionSample -//----------------------------------------------------------------------------- -CExpressionSample *CFlexAnimationTrack::GetSample( int index, int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - if ( index < 0 || index >= GetNumSamples( type ) ) - return NULL; - return &m_Samples[ type ][ index ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFlexAnimationTrack::IsTrackActive( void ) -{ - return m_bActive; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : active - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetTrackActive( bool active ) -{ - m_bActive = active; -} - -void CFlexAnimationTrack::SetEdgeInfo( bool leftEdge, int curveType, float zero ) -{ - int idx = leftEdge ? 0 : 1; - m_EdgeInfo[ idx ].m_CurveType = curveType; - m_EdgeInfo[ idx ].m_flZeroPos = zero; -} - -void CFlexAnimationTrack::GetEdgeInfo( bool leftEdge, int& curveType, float& zero ) const -{ - int idx = leftEdge ? 0 : 1; - curveType = m_EdgeInfo[ idx ].m_CurveType; - zero = m_EdgeInfo[ idx ].m_flZeroPos; -} - -void CFlexAnimationTrack::SetEdgeActive( bool leftEdge, bool state ) -{ - int idx = leftEdge ? 0 : 1; - m_EdgeInfo[ idx ].m_bActive = state; -} - -bool CFlexAnimationTrack::IsEdgeActive( bool leftEdge ) const -{ - int idx = leftEdge ? 0 : 1; - return m_EdgeInfo[ idx ].m_bActive; -} - -int CFlexAnimationTrack::GetEdgeCurveType( bool leftEdge ) const -{ - if ( !IsEdgeActive( leftEdge ) ) - { - return CURVE_DEFAULT; - } - - int idx = leftEdge ? 0 : 1; - return m_EdgeInfo[ idx ].m_CurveType; -} - -float CFlexAnimationTrack::GetEdgeZeroValue( bool leftEdge ) const -{ - if ( !IsEdgeActive( leftEdge ) ) - { - return 0.0f; - } - - int idx = leftEdge ? 0 : 1; - return m_EdgeInfo[ idx ].m_flZeroPos; -} - -float CFlexAnimationTrack::GetDefaultEdgeZeroPos() const -{ - float zero = 0.0f; - if ( m_flMin != m_flMax ) - { - zero = ( 0.0f - m_flMin ) / ( m_flMax - m_flMin ); - } - return zero; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetZeroValue( int type, bool leftSide ) -{ - // Stereo track is always clamped to 0.5 and doesn't care about l/r settings - if ( type == 1 ) - { - return 0.5f; - } - - if ( IsEdgeActive( leftSide ) ) - { - return GetEdgeZeroValue( leftSide ); - } - - return GetDefaultEdgeZeroPos(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : number - -// Output : CExpressionSample -//----------------------------------------------------------------------------- -CExpressionSample *CFlexAnimationTrack::GetBoundedSample( int number, bool& bClamped, int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - if ( number < 0 ) - { - // Search for two samples which span time f - static CExpressionSample nullstart; - nullstart.time = 0.0f; - nullstart.value = GetZeroValue( type, true ); - if ( type == 0 ) - { - nullstart.SetCurveType( GetEdgeCurveType( true ) ); - } - else - { - nullstart.SetCurveType( CURVE_DEFAULT ); - } - bClamped = true; - return &nullstart; - } - else if ( number >= GetNumSamples( type ) ) - { - static CExpressionSample nullend; - nullend.time = m_pEvent->GetDuration(); - nullend.value = GetZeroValue( type, false ); - if ( type == 0 ) - { - nullend.SetCurveType( GetEdgeCurveType( false ) ); - } - else - { - nullend.SetCurveType( CURVE_DEFAULT ); - } - bClamped = true; - return &nullend; - } - - bClamped = false; - return GetSample( number, type ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// type - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetIntensityInternal( float time, int type ) -{ - Assert( type == 0 || type == 1 ); - - float retval = 0.0f; - - // find samples that span the time - if ( !m_pEvent || !m_pEvent->HasEndTime() || time < m_pEvent->GetStartTime() ) - { - retval = GetZeroValue( type, true );; - } - else if ( time > m_pEvent->GetEndTime() ) - { - retval = GetZeroValue( type, false );; - } - else - { - float elapsed = time - m_pEvent->GetStartTime(); - retval = GetFracIntensity( elapsed, type ); - } - - // scale - if (type == 0 && m_flMin != m_flMax) - { - retval = retval * (m_flMax - m_flMin) + m_flMin; - } - return retval; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// type - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetFracIntensity( float time, int type ) -{ - float zeroValueLeft = GetZeroValue( type, true ); - - Assert( type == 0 || type == 1 ); - - // find samples that span the time - if ( !m_pEvent || !m_pEvent->HasEndTime() ) - return zeroValueLeft; - - int rampCount = GetNumSamples( type ); - if ( rampCount < 1 ) - { - return zeroValueLeft; - } - - CExpressionSample *esStart = NULL; - CExpressionSample *esEnd = NULL; - - // do binary search for sample in time period - int j = MAX( rampCount / 2, 1 ); - int i = j; - while ( i > -2 && i < rampCount + 1 ) - { - bool dummy; - esStart = GetBoundedSample( i, dummy, type ); - esEnd = GetBoundedSample( i + 1, dummy, type ); - - j = MAX( j / 2, 1 ); - if ( time < esStart->time) - { - i -= j; - } - else if ( time > esEnd->time) - { - i += j; - } - else - { - if ( time == esEnd->time ) - { - ++i; - esStart = GetBoundedSample( i, dummy, type ); - esEnd = GetBoundedSample( i + 1, dummy, type ); - } - break; - } - } - - if (!esStart) - { - return zeroValueLeft; - } - - int prev = i - 1; - int next = i + 2; - - prev = MAX( -1, prev ); - next = MIN( next, rampCount ); - - bool bclamp[ 2 ]; - CExpressionSample *esPre = GetBoundedSample( prev, bclamp[ 0 ], type ); - CExpressionSample *esNext = GetBoundedSample( next, bclamp[ 1 ], type ); - - float dt = esEnd->time - esStart->time; - - Vector vPre( esPre->time, esPre->value, 0 ); - Vector vStart( esStart->time, esStart->value, 0 ); - Vector vEnd( esEnd->time, esEnd->value, 0 ); - Vector vNext( esNext->time, esNext->value, 0 ); - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( time - esStart->time ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - int dummy; - int earlypart, laterpart; - - // Not holding out value of previous curve... - Interpolator_CurveInterpolatorsForType( esStart->GetCurveType(), dummy, earlypart ); - Interpolator_CurveInterpolatorsForType( esEnd->GetCurveType(), laterpart, dummy ); - - if ( earlypart == INTERPOLATE_HOLD ) - { - // Hold "out" of previous sample (can cause a discontinuity) - VectorLerp( vStart, vEnd, f2, vOut ); - vOut.y = vStart.y; - } - else if ( laterpart == INTERPOLATE_HOLD ) - { - // Hold "out" of previous sample (can cause a discontinuity) - VectorLerp( vStart, vEnd, f2, vOut ); - vOut.y = vEnd.y; - } - else - { - bool sameCurveType = earlypart == laterpart ? true : false; - if ( sameCurveType ) - { - Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut ); - } - else // curves differ, sigh - { - Vector vOut1, vOut2; - - Interpolator_CurveInterpolate( earlypart, vPre, vStart, vEnd, vNext, f2, vOut1 ); - Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut2 ); - - VectorLerp( vOut1, vOut2, f2, vOut ); - } - } - - float retval = clamp( vOut.y, 0.0f, 1.0f ); - return retval; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetSampleIntensity( float time ) -{ - return GetIntensityInternal( time, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetBalanceIntensity( float time ) -{ - if ( IsComboType() ) - { - return GetIntensityInternal( time, 1 ); - } - - return 1.0f; -} - -// For a given time, computes 0->1 intensity value for the slider -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetIntensity( float time, int side ) -{ - float mag = GetSampleIntensity( time ); - - float scale = 1.0f; - - if ( IsComboType() ) - { - float balance = GetBalanceIntensity( time ); - - // Asking for left but balance is to right, then fall off as we go - // further right - if ( side == 0 && balance > 0.5f ) - { - scale = (1.0f - balance ) / 0.5f; - } - // Asking for right, but balance is left, fall off as we go left. - else if ( side == 1 && balance < 0.5f ) - { - scale = ( balance / 0.5f ); - } - } - - return mag * scale; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// value - -//----------------------------------------------------------------------------- -CExpressionSample *CFlexAnimationTrack::AddSample( float time, float value, int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - CExpressionSample sample; - sample.time = time; - sample.value = value; - sample.selected = false; - - int idx = m_Samples[ type ].AddToTail( sample ); - - // Resort( type ); - return &m_Samples[ type ][ idx ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::Resort( int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - for ( int i = 0; i < m_Samples[ type ].Size(); i++ ) - { - for ( int j = i + 1; j < m_Samples[ type ].Size(); j++ ) - { - CExpressionSample src = m_Samples[ type ][ i ]; - CExpressionSample dest = m_Samples[ type ][ j ]; - - if ( src.time > dest.time ) - { - m_Samples[ type ][ i ] = dest; - m_Samples[ type ][ j ] = src; - } - } - } - - // Make sure nothing is out of range - RemoveOutOfRangeSamples( 0 ); - RemoveOutOfRangeSamples( 1 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CFlexAnimationTrack::GetEvent( void ) -{ - return m_pEvent; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : side - -// Output : int -//----------------------------------------------------------------------------- -int CFlexAnimationTrack::GetFlexControllerIndex( int side /*= 0*/ ) -{ - Assert( side == 0 || side == 1 ); - - if ( IsComboType() ) - { - return m_nFlexControllerIndex[ side ]; - } - - return m_nFlexControllerIndex[ 0 ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : side - -// Output : int -//----------------------------------------------------------------------------- -LocalFlexController_t CFlexAnimationTrack::GetRawFlexControllerIndex( int side /*= 0*/ ) -{ - Assert( side == 0 || side == 1 ); - - if ( IsComboType() ) - { - return m_nFlexControllerIndexRaw[ side ]; - } - - return m_nFlexControllerIndexRaw[ 0 ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// side - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetFlexControllerIndex( LocalFlexController_t raw, int index, int side /*= 0*/ ) -{ - Assert( side == 0 || side == 1 ); - - m_nFlexControllerIndex[ side ] = index; - // Model specific - m_nFlexControllerIndexRaw[ side ] = raw; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : combo - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetComboType( bool combo ) -{ - m_bCombo = combo; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFlexAnimationTrack::IsComboType( void ) -{ - return m_bCombo; -} - -//----------------------------------------------------------------------------- -// Purpose: True if this should be simulated on the server side always -// Input : state - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetServerSide( bool state ) -{ - m_bServerSide = state; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFlexAnimationTrack::IsServerSide() const -{ - return m_bServerSide; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetMin( float value ) -{ - m_flMin = value; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetMax( float value ) -{ - m_flMax = value; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetMin( int type ) -{ - if (type == 0) - return m_flMin; - else - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetMax( int type ) -{ - if (type == 0) - return m_flMax; - else - return 1.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFlexAnimationTrack::IsInverted( void ) -{ - if (m_bInverted) - return true; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetInverted( bool isInverted ) -{ - m_bInverted = isInverted; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::RemoveOutOfRangeSamples( int type ) -{ - Assert( m_pEvent ); - if ( !m_pEvent ) - return; - - Assert( m_pEvent->HasEndTime() ); - float duration = m_pEvent->GetDuration(); - - int c = m_Samples[ type ].Size(); - for ( int i = c-1; i >= 0; i-- ) - { - CExpressionSample src = m_Samples[ type ][ i ]; - if ( src.time < 0 || - src.time > duration ) - { - m_Samples[ type ].Remove( i ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CChoreoEvent::CChoreoEvent( CChoreoScene *scene ) -{ - Init( scene ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *name - -//----------------------------------------------------------------------------- -CChoreoEvent::CChoreoEvent( CChoreoScene *scene, EVENTTYPE type, const char *name ) -{ - Init( scene ); - SetType( type ); - SetName( name ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *name - -// *param - -//----------------------------------------------------------------------------- -CChoreoEvent::CChoreoEvent( CChoreoScene *scene, EVENTTYPE type, const char *name, const char *param ) -{ - Init( scene ); - SetType( type ); - SetName( name ); - SetParameters( param ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CChoreoEvent::~CChoreoEvent( void ) -{ - RemoveAllTracks(); - ClearEventDependencies(); - delete m_pSubScene; -} - -//----------------------------------------------------------------------------- -// Purpose: Assignment -// Input : src - -// Output : CChoreoEvent& -//----------------------------------------------------------------------------- -CChoreoEvent& CChoreoEvent::operator=( const CChoreoEvent& src ) -{ - MEM_ALLOC_CREDIT(); - - // Copy global id when copying entity - m_nGlobalID = src.m_nGlobalID; - - m_pActor = NULL; - m_pChannel = NULL; - - m_nDefaultCurveType = src.m_nDefaultCurveType; - m_fType = src.m_fType; - m_Name = src.m_Name; - m_Parameters = src.m_Parameters; - m_Parameters2= src.m_Parameters2; - m_Parameters3= src.m_Parameters3; - m_flStartTime = src.m_flStartTime; - m_flEndTime = src.m_flEndTime; - - m_bFixedLength = src.m_bFixedLength; - m_flGestureSequenceDuration = src.m_flGestureSequenceDuration; - m_bResumeCondition = src.m_bResumeCondition; - m_bLockBodyFacing = src.m_bLockBodyFacing; - m_flDistanceToTarget = src.m_flDistanceToTarget; - m_bForceShortMovement = src.m_bForceShortMovement; - m_bSyncToFollowingGesture = src.m_bSyncToFollowingGesture; - m_bPlayOverScript = src.m_bPlayOverScript; - m_bUsesTag = src.m_bUsesTag; - m_TagName = src.m_TagName; - m_TagWavName = src.m_TagWavName; - - ClearAllRelativeTags(); - ClearAllTimingTags(); - int t; - for ( t = 0; t < NUM_ABS_TAG_TYPES; t++ ) - { - ClearAllAbsoluteTags( (AbsTagType)t ); - } - - int i; - for ( i = 0; i < src.m_RelativeTags.Size(); i++ ) - { - CEventRelativeTag newtag( src.m_RelativeTags[ i ] ); - newtag.SetOwner( this ); - m_RelativeTags.AddToTail( newtag ); - } - - for ( i = 0; i < src.m_TimingTags.Size(); i++ ) - { - CFlexTimingTag newtag( src.m_TimingTags[ i ] ); - newtag.SetOwner( this ); - m_TimingTags.AddToTail( newtag ); - } - for ( t = 0; t < NUM_ABS_TAG_TYPES; t++ ) - { - for ( i = 0; i < src.m_AbsoluteTags[ t ].Size(); i++ ) - { - CEventAbsoluteTag newtag( src.m_AbsoluteTags[ t ][ i ] ); - newtag.SetOwner( this ); - m_AbsoluteTags[ t ].AddToTail( newtag ); - } - } - - RemoveAllTracks(); - - for ( i = 0 ; i < src.m_FlexAnimationTracks.Size(); i++ ) - { - CFlexAnimationTrack *newtrack = new CFlexAnimationTrack( src.m_FlexAnimationTracks[ i ] ); - newtrack->SetEvent( this ); - m_FlexAnimationTracks.AddToTail( newtrack ); - } - - m_bTrackLookupSet = src.m_bTrackLookupSet; - - // FIXME: Use a safe handle? - //m_pSubScene = src.m_pSubScene; - - m_bProcessing = src.m_bProcessing; - m_pMixer = src.m_pMixer; - - m_pScene = src.m_pScene; - - m_nPitch = src.m_nPitch; - m_nYaw = src.m_nYaw; - - m_nNumLoops = src.m_nNumLoops; - m_nLoopsRemaining = src.m_nLoopsRemaining; - - // Copy ramp over - m_Ramp = src.m_Ramp; - - m_ccType = src.m_ccType; - m_CCToken = src.m_CCToken; - m_bUsingCombinedSoundFile = src.m_bUsingCombinedSoundFile; - m_uRequiredCombinedChecksum = src.m_uRequiredCombinedChecksum; - m_nNumSlaves = src.m_nNumSlaves; - m_flLastSlaveEndTime = src.m_flLastSlaveEndTime; - m_bCCTokenValid = src.m_bCCTokenValid; - m_bCombinedUsingGenderToken = src.m_bCombinedUsingGenderToken; - - m_bSuppressCaptionAttenuation = src.m_bSuppressCaptionAttenuation; - - m_bActive = src.m_bActive; - - return *this; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::Init( CChoreoScene *scene ) -{ - m_nGlobalID = s_nGlobalID++; - m_nDefaultCurveType = CURVE_CATMULL_ROM_TO_CATMULL_ROM; - m_fType = UNSPECIFIED; - m_Name.Set(""); - m_Parameters.Set(""); - m_Parameters2.Set(""); - m_Parameters3.Set(""); - - m_flStartTime = 0.0f; - m_flEndTime = -1.0f; - - m_pActor = NULL; - m_pChannel = NULL; - m_pScene = scene; - - m_bFixedLength = false; - m_bResumeCondition = false; - SetUsingRelativeTag( false, 0, 0 ); - - m_bTrackLookupSet = false; - - m_bLockBodyFacing = false; - m_flDistanceToTarget = 0.0f; - m_bForceShortMovement = false; - m_bSyncToFollowingGesture = false; - m_bPlayOverScript = false; - - m_pSubScene = NULL; - m_bProcessing = false; - m_pMixer = NULL; - m_flGestureSequenceDuration = 0.0f; - - m_nPitch = m_nYaw = 0; - - m_nNumLoops = -1; - m_nLoopsRemaining = 0; - - // Close captioning/localization support - m_CCToken.Set(""); - m_ccType = CC_MASTER; - m_bUsingCombinedSoundFile = false; - m_uRequiredCombinedChecksum = 0; - m_nNumSlaves = 0; - m_flLastSlaveEndTime = 0.0f; - m_bCCTokenValid = false; - m_bCombinedUsingGenderToken = false; - m_bSuppressCaptionAttenuation = false; - m_bActive = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -CChoreoEvent::EVENTTYPE CChoreoEvent::GetType( void ) -{ - return (EVENTTYPE)m_fType; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetType( EVENTTYPE type ) -{ - m_fType = type; - - if ( m_fType == SPEAK || - m_fType == SUBSCENE ) - { - m_bFixedLength = true; - } - else - { - m_bFixedLength = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetName( const char *name ) -{ - m_Name = name; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetName( void ) -{ - return m_Name.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *param - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetParameters( const char *param ) -{ - m_Parameters = param; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetParameters( void ) -{ - return m_Parameters.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *param - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetParameters2( const char *param ) -{ - int iLength = Q_strlen( param ); - m_Parameters2 = param; - - // HACK: Remove trailing " " until faceposer is fixed - if ( iLength > 0 ) - { - if ( param[iLength-1] == ' ' ) - { - char tmp[1024]; - Q_strncpy( tmp, param, sizeof(tmp) ); - tmp[iLength-1] = 0; - m_Parameters2.Set(tmp); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetParameters2( void ) -{ - return m_Parameters2.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *param - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetParameters3( const char *param ) -{ - int iLength = Q_strlen( param ); - m_Parameters3 = param; - - // HACK: Remove trailing " " until faceposer is fixed - if ( iLength > 0 ) - { - if ( param[iLength-1] == ' ' ) - { - char tmp[1024]; - Q_strncpy( tmp, param, sizeof(tmp) ); - tmp[iLength-1] = 0; - m_Parameters3.Set(tmp); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetParameters3( void ) -{ - return m_Parameters3.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: debugging description -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetDescription( void ) -{ - static char description[ 256 ]; - - description[ 0 ] = 0; - - if ( !GetActor() ) - { - Q_snprintf( description,sizeof(description), "global %s", m_Name.Get() ); - } - else - { - Assert( m_pChannel ); - Q_snprintf( description,sizeof(description), "%s : %s : %s -- %s \"%s\"", m_pActor->GetName(), m_pChannel->GetName(), GetName(), NameForType( GetType() ), GetParameters() ); - if ( GetType() == EXPRESSION ) - { - char sz[ 256 ]; - - Q_snprintf( sz,sizeof(sz), " \"%s\"", GetParameters2() ); - Q_strncat( description, sz, sizeof(description), COPY_ALL_CHARACTERS ); - } - } - - return description; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : starttime - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetStartTime( float starttime ) -{ - m_flStartTime = starttime; - if ( m_flEndTime != -1.0f ) - { - if ( m_flEndTime < m_flStartTime ) - { - m_flEndTime = m_flStartTime; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetStartTime( ) -{ - return m_flStartTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : endtime - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetEndTime( float endtime ) -{ - bool changed = m_flEndTime != endtime; - - m_flEndTime = endtime; - - if ( endtime != -1.0f ) - { - if ( m_flEndTime < m_flStartTime ) - { - m_flEndTime = m_flStartTime; - } - - if ( changed ) - { - OnEndTimeChanged(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetEndTime( ) -{ - return m_flEndTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::HasEndTime( void ) -{ - return m_flEndTime != -1.0f ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetCompletion( float time ) -{ - float t = (time - GetStartTime()) / (GetEndTime() - GetStartTime()); - - if (t < 0.0f) - return 0.0f; - else if (t > 1.0f) - return 1.0f; - - return t; -} - -// ICurveDataAccessor method -bool CChoreoEvent::CurveHasEndTime() -{ - return HasEndTime(); -} - -//----------------------------------------------------------------------------- -// Default curve type -//----------------------------------------------------------------------------- -void CChoreoEvent::SetDefaultCurveType( int nCurveType ) -{ - m_nDefaultCurveType = nCurveType; -} - -int CChoreoEvent::GetDefaultCurveType() -{ - return m_nDefaultCurveType; -} - -float CCurveData::GetIntensity( ICurveDataAccessor *data, float time ) -{ - float zeroValue = 0.0f; - - // find samples that span the time - if ( !data->CurveHasEndTime() ) - { - return zeroValue; - } - - int rampCount = GetCount(); - if ( rampCount < 1 ) - { - // Full intensity - return 1.0f; - } - - CExpressionSample *esStart = NULL; - CExpressionSample *esEnd = NULL; - - // do binary search for sample in time period - int j = MAX( rampCount / 2, 1 ); - int i = j; - while ( i > -2 && i < rampCount + 1 ) - { - bool dummy; - esStart = GetBoundedSample( data, i, dummy ); - esEnd = GetBoundedSample( data, i + 1, dummy ); - - j = MAX( j / 2, 1 ); - if ( time < esStart->time) - { - i -= j; - } - else if ( time > esEnd->time) - { - i += j; - } - else - { - break; - } - } - - if (!esStart) - { - return 1.0f; - } - - int prev = i - 1; - int next = i + 2; - - prev = MAX( -1, prev ); - next = MIN( next, rampCount ); - - bool bclamp[ 2 ]; - CExpressionSample *esPre = GetBoundedSample( data, prev, bclamp[ 0 ] ); - CExpressionSample *esNext = GetBoundedSample( data, next, bclamp[ 1 ] ); - - float dt = esEnd->time - esStart->time; - - Vector vPre( esPre->time, esPre->value, 0 ); - Vector vStart( esStart->time, esStart->value, 0 ); - Vector vEnd( esEnd->time, esEnd->value, 0 ); - Vector vNext( esNext->time, esNext->value, 0 ); - - if ( bclamp[ 0 ] ) - { - vPre.x = vStart.x; - } - - if ( bclamp[ 1 ] ) - { - vNext.x = vEnd.x; - } - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( time - esStart->time ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - int dummy; - int earlypart, laterpart; - - int startCurve = esStart->GetCurveType(); - int endCurve = esEnd->GetCurveType(); - - if ( startCurve == CURVE_DEFAULT ) - { - startCurve = data->GetDefaultCurveType(); - } - if ( endCurve == CURVE_DEFAULT ) - { - endCurve = data->GetDefaultCurveType(); - } - - // Not holding out value of previous curve... - Interpolator_CurveInterpolatorsForType( startCurve, dummy, earlypart ); - Interpolator_CurveInterpolatorsForType( endCurve, laterpart, dummy ); - - if ( earlypart == INTERPOLATE_HOLD ) - { - // Hold "out" of previous sample (can cause a discontinuity) - VectorLerp( vStart, vEnd, f2, vOut ); - vOut.y = vStart.y; - } - else if ( laterpart == INTERPOLATE_HOLD ) - { - // Hold "out" of previous sample (can cause a discontinuity) - VectorLerp( vStart, vEnd, f2, vOut ); - vOut.y = vEnd.y; - } - else - { - bool sameCurveType = earlypart == laterpart ? true : false; - if ( sameCurveType ) - { - Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut ); - } - else // curves differ, sigh - { - Vector vOut1, vOut2; - - Interpolator_CurveInterpolate( earlypart, vPre, vStart, vEnd, vNext, f2, vOut1 ); - Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut2 ); - - VectorLerp( vOut1, vOut2, f2, vOut ); - } - } - - float retval = clamp( vOut.y, 0.0f, 1.0f ); - return retval; -} - -//----------------------------------------------------------------------------- -// Purpose: Get intensity for event, bounded by scene global intensity -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetIntensity( float scenetime ) -{ - float global_intensity = 1.0f; - if ( m_pScene ) - { - global_intensity = m_pScene->GetSceneRampIntensity( scenetime ); - } - else - { - Assert( 0 ); - } - - float event_intensity = _GetIntensity( scenetime ); - - return global_intensity * event_intensity; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::_GetIntensity( float scenetime ) -{ - // Convert to event local time - float time = scenetime - GetStartTime(); - return m_Ramp.GetIntensity( this, time ); -} - - -float CChoreoEvent::GetIntensityArea( float scenetime ) -{ - // Convert to event local time - float time = scenetime - GetStartTime(); - return m_Ramp.GetIntensityArea( this, time ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CCurveData::GetIntensityArea( ICurveDataAccessor *data, float time ) -{ - float zeroValue = 0.0f; - - // find samples that span the time - if ( !data->CurveHasEndTime() ) - { - return zeroValue; - } - - int rampCount = GetCount(); - if ( rampCount < 1 ) - { - // Full intensity - return 1.0f; - } - - CExpressionSample *esStart = NULL; - CExpressionSample *esEnd = NULL; - - // do binary search for sample in time period - int j = MAX( rampCount / 2, 1 ); - int i = j; - while ( i > -2 && i < rampCount + 1 ) - { - bool dummy; - esStart = GetBoundedSample( data, i, dummy ); - esEnd = GetBoundedSample( data, i + 1, dummy ); - - j = MAX( j / 2, 1 ); - if ( time < esStart->time) - { - i -= j; - } - else if ( time > esEnd->time) - { - i += j; - } - else - { - break; - } - } - - UpdateIntensityArea( data ); - - float flTotal = 0.0f; - flTotal = m_RampAccumulator[i+1]; - - int prev = i - 1; - int next = i + 2; - - prev = MAX( -1, prev ); - next = MIN( next, rampCount ); - - bool bclamp[ 2 ]; - CExpressionSample *esPre = GetBoundedSample( data, prev, bclamp[ 0 ] ); - CExpressionSample *esNext = GetBoundedSample( data, next, bclamp[ 1 ] ); - - float dt = esEnd->time - esStart->time; - - Vector vPre( esPre->time, esPre->value, 0 ); - Vector vStart( esStart->time, esStart->value, 0 ); - Vector vEnd( esEnd->time, esEnd->value, 0 ); - Vector vNext( esNext->time, esNext->value, 0 ); - - if ( bclamp[ 0 ] ) - { - vPre.x = vStart.x; - } - - if ( bclamp[ 1 ] ) - { - vNext.x = vEnd.x; - } - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( time - esStart->time ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - int dummy; - int earlypart, laterpart; - - int startCurve = esStart->GetCurveType(); - int endCurve = esEnd->GetCurveType(); - - if ( startCurve == CURVE_DEFAULT ) - { - startCurve = data->GetDefaultCurveType(); - } - if ( endCurve == CURVE_DEFAULT ) - { - endCurve = data->GetDefaultCurveType(); - } - - // Not holding out value of previous curve... - Interpolator_CurveInterpolatorsForType( startCurve, dummy, earlypart ); - Interpolator_CurveInterpolatorsForType( endCurve, laterpart, dummy ); - - // FIXME: needs other curve types - Catmull_Rom_Spline_Integral_Normalize( - vPre, - vStart, - vEnd, - vNext, - f2, - vOut ); - - // Con_Printf( "Accum %f : Partial %f\n", flTotal, vOut.y * (vEnd.x - vStart.x) * f2 ); - flTotal = flTotal + clamp( vOut.y, 0.0f, 1.0f ) * (vEnd.x - vStart.x); - return flTotal; -} - - -void CCurveData::UpdateIntensityArea( ICurveDataAccessor *data ) -{ - int rampCount = GetCount();; - if ( rampCount < 1 ) - { - return; - } - - if (m_RampAccumulator.Count() == rampCount + 2) - { - return; - } - - m_RampAccumulator.SetCount( rampCount + 2 ); - - int i = -1; - - bool dummy; - CExpressionSample *esPre = GetBoundedSample( data, i - 1, dummy ); - CExpressionSample *esStart = GetBoundedSample( data, i, dummy ); - CExpressionSample *esEnd = GetBoundedSample( data, MIN( i + 1, rampCount ), dummy ); - - Vector vPre( esPre->time, esPre->value, 0 ); - Vector vStart( esStart->time, esStart->value, 0 ); - Vector vEnd( esEnd->time, esEnd->value, 0 ); - - Vector vOut; - for (i = -1; i < rampCount; i++) - { - CExpressionSample *esNext = GetBoundedSample( data, MIN( i + 2, rampCount ), dummy ); - Vector vNext( esNext->time, esNext->value, 0 ); - - Catmull_Rom_Spline_Integral_Normalize( - vPre, - vStart, - vEnd, - vNext, - 1.0f, - vOut ); - - m_RampAccumulator[i+1] = clamp( vOut.y, 0.0f, 1.0f ) * (vEnd.x - vStart.x); - - vPre = vStart; - vStart = vEnd; - vEnd = vNext; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : dt - -//----------------------------------------------------------------------------- -void CChoreoEvent::OffsetStartTime( float dt ) -{ - SetStartTime( GetStartTime() + dt ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : dt - -//----------------------------------------------------------------------------- -void CChoreoEvent::OffsetEndTime( float dt ) -{ - if ( HasEndTime() ) - { - SetEndTime( GetEndTime() + dt ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : dt - -//----------------------------------------------------------------------------- -void CChoreoEvent::OffsetTime( float dt ) -{ - if ( HasEndTime() ) - { - m_flEndTime += dt; - } - m_flStartTime += dt; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetActor( CChoreoActor *actor ) -{ - m_pActor = actor; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoActor -//----------------------------------------------------------------------------- -CChoreoActor *CChoreoEvent::GetActor( void ) -{ - return m_pActor; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *channel - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetChannel( CChoreoChannel *channel ) -{ - m_pChannel = channel; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoChannel -//----------------------------------------------------------------------------- -CChoreoChannel *CChoreoEvent::GetChannel( void ) -{ - return m_pChannel; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetSubScene( CChoreoScene *scene ) -{ - m_pSubScene = scene; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoScene -//----------------------------------------------------------------------------- -CChoreoScene *CChoreoEvent::GetSubScene( void ) -{ - return m_pSubScene; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct EventNameMap_t -{ - CChoreoEvent::EVENTTYPE type; - char const *name; -}; - -static EventNameMap_t g_NameMap[] = -{ - { CChoreoEvent::UNSPECIFIED, "unspecified" }, // error condition!!! - { CChoreoEvent::SECTION, "section" }, - { CChoreoEvent::EXPRESSION, "expression" }, - { CChoreoEvent::LOOKAT, "lookat" }, - { CChoreoEvent::MOVETO, "moveto" }, - { CChoreoEvent::SPEAK, "speak" }, - { CChoreoEvent::GESTURE, "gesture" }, - { CChoreoEvent::SEQUENCE, "sequence" }, - { CChoreoEvent::FACE, "face" }, - { CChoreoEvent::FIRETRIGGER, "firetrigger" }, - { CChoreoEvent::FLEXANIMATION, "flexanimation" }, - { CChoreoEvent::SUBSCENE, "subscene" }, - { CChoreoEvent::LOOP, "loop" }, - { CChoreoEvent::INTERRUPT, "interrupt" }, - { CChoreoEvent::STOPPOINT, "stoppoint" }, - { CChoreoEvent::PERMIT_RESPONSES, "permitresponses" }, - { CChoreoEvent::GENERIC, "generic" }, -}; - -//----------------------------------------------------------------------------- -// Purpose: A simple class to verify the names data above at runtime -//----------------------------------------------------------------------------- -class CCheckEventNames -{ -public: - CCheckEventNames() - { - if ( ARRAYSIZE( g_NameMap ) != CChoreoEvent::NUM_TYPES ) - { - Error( "g_NameMap contains %i entries, CChoreoEvent::NUM_TYPES == %i!", - ARRAYSIZE( g_NameMap ), CChoreoEvent::NUM_TYPES ); - } - for ( int i = 0; i < CChoreoEvent::NUM_TYPES; ++i ) - { - if ( !g_NameMap[ i ].name ) - { - Error( "g_NameMap: Event type at %i has NULL name string!", i ); - } - - if ( (CChoreoEvent::EVENTTYPE)(i) == g_NameMap[ i ].type ) - continue; - - Error( "g_NameMap: Event type at %i has wrong value (%i)!", - i, (int)g_NameMap[ i ].type ); - } - } -}; -static CCheckEventNames g_CheckNamesSingleton; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : int -//----------------------------------------------------------------------------- -CChoreoEvent::EVENTTYPE CChoreoEvent::TypeForName( const char *name ) -{ - for ( int i = 0; i < NUM_TYPES; ++i ) - { - EventNameMap_t *slot = &g_NameMap[ i ]; - if ( !Q_stricmp( name, slot->name ) ) - return slot->type; - } - - Assert( !"CChoreoEvent::TypeForName failed!!!" ); - return UNSPECIFIED; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::NameForType( EVENTTYPE type ) -{ - int i = (int)type; - if ( i < 0 || i >= NUM_TYPES ) - { - Assert( "!CChoreoEvent::NameForType: bogus type!" ); - // returns "unspecified!!!"; - return g_NameMap[ 0 ].name; - } - - return g_NameMap[ i ].name; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct CCNameMap_t -{ - CChoreoEvent::CLOSECAPTION type; - char const *name; -}; - -static CCNameMap_t g_CCNameMap[] = -{ - { CChoreoEvent::CC_MASTER, "cc_master" }, // error condition!!! - { CChoreoEvent::CC_SLAVE, "cc_slave" }, - { CChoreoEvent::CC_DISABLED, "cc_disabled" }, -}; - -//----------------------------------------------------------------------------- -// Purpose: A simple class to verify the names data above at runtime -//----------------------------------------------------------------------------- -class CCheckCCNames -{ -public: - CCheckCCNames() - { - if ( ARRAYSIZE( g_CCNameMap ) != CChoreoEvent::NUM_CC_TYPES ) - { - Error( "g_CCNameMap contains %i entries, CChoreoEvent::NUM_CC_TYPES == %i!", - ARRAYSIZE( g_CCNameMap ), CChoreoEvent::NUM_CC_TYPES ); - } - for ( int i = 0; i < CChoreoEvent::NUM_CC_TYPES; ++i ) - { - if ( !g_CCNameMap[ i ].name ) - { - Error( "g_NameMap: CC type at %i has NULL name string!", i ); - } - - if ( (CChoreoEvent::CLOSECAPTION)(i) == g_CCNameMap[ i ].type ) - continue; - - Error( "g_CCNameMap: Event type at %i has wrong value (%i)!", - i, (int)g_CCNameMap[ i ].type ); - } - } -}; -static CCheckCCNames g_CheckCCNamesSingleton; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : CLOSECAPTION -//----------------------------------------------------------------------------- -CChoreoEvent::CLOSECAPTION CChoreoEvent::CCTypeForName( const char *name ) -{ - for ( int i = 0; i < NUM_CC_TYPES; ++i ) - { - CCNameMap_t *slot = &g_CCNameMap[ i ]; - if ( !Q_stricmp( name, slot->name ) ) - return slot->type; - } - - Assert( !"CChoreoEvent::TypeForName failed!!!" ); - return CC_MASTER; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::NameForCCType( CLOSECAPTION type ) -{ - int i = (int)type; - if ( i < 0 || i >= NUM_CC_TYPES ) - { - Assert( "!CChoreoEvent::NameForType: bogus type!" ); - // returns "unspecified!!!"; - return g_CCNameMap[ 0 ].name; - } - - return g_CCNameMap[ i ].name; -} - -//----------------------------------------------------------------------------- -// Purpose: Is the event something that can be sized ( a wave file, e.g. ) -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsFixedLength( void ) -{ - return m_bFixedLength; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : isfixedlength - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetFixedLength( bool isfixedlength ) -{ - m_bFixedLength = isfixedlength; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : resumecondition - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetResumeCondition( bool resumecondition ) -{ - m_bResumeCondition = resumecondition; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsResumeCondition( void ) -{ - return m_bResumeCondition; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : lockbodyfacing - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetLockBodyFacing( bool lockbodyfacing ) -{ - m_bLockBodyFacing = lockbodyfacing; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsLockBodyFacing( void ) -{ - return m_bLockBodyFacing; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : distancetotarget - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetDistanceToTarget( float distancetotarget ) -{ - m_flDistanceToTarget = distancetotarget; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns ideal distance to target -//----------------------------------------------------------------------------- -float CChoreoEvent::GetDistanceToTarget( void ) -{ - return m_flDistanceToTarget; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set if small (sub-1/2 bbox) movements are forced -//----------------------------------------------------------------------------- - -void CChoreoEvent::SetForceShortMovement( bool bForceShortMovement ) -{ - m_bForceShortMovement = bForceShortMovement; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : get if small (sub-1/2 bbox) movements are forced -//----------------------------------------------------------------------------- - -bool CChoreoEvent::GetForceShortMovement( void ) -{ - return m_bForceShortMovement; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set if the gesture should sync its exit tag with the following gestures entry tag -//----------------------------------------------------------------------------- - -void CChoreoEvent::SetSyncToFollowingGesture( bool bSyncToFollowingGesture ) -{ - m_bSyncToFollowingGesture = bSyncToFollowingGesture; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : get if the gesture should sync its exit tag with the following gestures entry tag -//----------------------------------------------------------------------------- - -bool CChoreoEvent::GetSyncToFollowingGesture( void ) -{ - return m_bSyncToFollowingGesture; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set if the sequence should player overtop of an underlying SS -//----------------------------------------------------------------------------- - -void CChoreoEvent::SetPlayOverScript( bool bPlayOverScript ) -{ - m_bPlayOverScript = bPlayOverScript; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : get if the sequence should player overtop of an underlying SS -//----------------------------------------------------------------------------- - -bool CChoreoEvent::GetPlayOverScript( void ) -{ - return m_bPlayOverScript; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetDuration( void ) -{ - if ( HasEndTime() ) - { - return GetEndTime() - GetStartTime(); - } - - return 0.0f; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::ClearAllRelativeTags( void ) -{ - m_RelativeTags.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumRelativeTags( void ) -{ - return m_RelativeTags.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : tagnum - -// Output : CEventRelativeTag -//----------------------------------------------------------------------------- -CEventRelativeTag *CChoreoEvent::GetRelativeTag( int tagnum ) -{ - Assert( tagnum >= 0 && tagnum < m_RelativeTags.Size() ); - return &m_RelativeTags[ tagnum ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -// percentage - -//----------------------------------------------------------------------------- -void CChoreoEvent::AddRelativeTag( const char *tagname, float percentage ) -{ - CEventRelativeTag rt( this, tagname, percentage ); - m_RelativeTags.AddToTail( rt ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveRelativeTag( const char *tagname ) -{ - for ( int i = 0; i < m_RelativeTags.Size(); i++ ) - { - CEventRelativeTag *prt = &m_RelativeTags[ i ]; - if ( !prt ) - continue; - - if ( !stricmp( prt->GetName(), tagname ) ) - { - m_RelativeTags.Remove( i ); - return; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -// Output : CEventRelativeTag * -//----------------------------------------------------------------------------- -CEventRelativeTag * CChoreoEvent::FindRelativeTag( const char *tagname ) -{ - for ( int i = 0; i < m_RelativeTags.Size(); i++ ) - { - CEventRelativeTag *prt = &m_RelativeTags[ i ]; - if ( !prt ) - continue; - - if ( !stricmp( prt->GetName(), tagname ) ) - { - return prt; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsUsingRelativeTag( void ) -{ - return m_bUsesTag; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : usetag - -// 0 - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetUsingRelativeTag( bool usetag, const char *tagname /*= 0*/, - const char *wavname /* = 0 */ ) -{ - m_bUsesTag = usetag; - if ( tagname ) - { - m_TagName = tagname; - } - else - { - m_TagName.Set(""); - } - if ( wavname ) - { - m_TagWavName = wavname; - } - else - { - m_TagWavName.Set(""); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetRelativeTagName( void ) -{ - return m_TagName.Get(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetRelativeWavName( void ) -{ - return m_TagWavName.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::ClearAllTimingTags( void ) -{ - m_TimingTags.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumTimingTags( void ) -{ - return m_TimingTags.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : tagnum - -// Output : CEventRelativeTag -//----------------------------------------------------------------------------- -CFlexTimingTag *CChoreoEvent::GetTimingTag( int tagnum ) -{ - Assert( tagnum >= 0 && tagnum < m_TimingTags.Size() ); - return &m_TimingTags[ tagnum ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -// percentage - -//----------------------------------------------------------------------------- -void CChoreoEvent::AddTimingTag( const char *tagname, float percentage, bool locked ) -{ - CFlexTimingTag tt( this, tagname, percentage, locked ); - m_TimingTags.AddToTail( tt ); - - // Sort tags - CFlexTimingTag temp( (CChoreoEvent *)0x1, "", 0.0f, false ); - - // ugly bubble sort - for ( int i = 0; i < m_TimingTags.Size(); i++ ) - { - for ( int j = i + 1; j < m_TimingTags.Size(); j++ ) - { - CFlexTimingTag *t1 = &m_TimingTags[ i ]; - CFlexTimingTag *t2 = &m_TimingTags[ j ]; - - if ( t1->GetPercentage() > t2->GetPercentage() ) - { - temp = *t1; - *t1 = *t2; - *t2 = temp; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveTimingTag( const char *tagname ) -{ - for ( int i = 0; i < m_TimingTags.Size(); i++ ) - { - CFlexTimingTag *ptt = &m_TimingTags[ i ]; - if ( !ptt ) - continue; - - if ( !stricmp( ptt->GetName(), tagname ) ) - { - m_TimingTags.Remove( i ); - return; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -// Output : CEventRelativeTag * -//----------------------------------------------------------------------------- -CFlexTimingTag * CChoreoEvent::FindTimingTag( const char *tagname ) -{ - for ( int i = 0; i < m_TimingTags.Size(); i++ ) - { - CFlexTimingTag *ptt = &m_TimingTags[ i ]; - if ( !ptt ) - continue; - - if ( !stricmp( ptt->GetName(), tagname ) ) - { - return ptt; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::OnEndTimeChanged( void ) -{ - int c = GetNumFlexAnimationTracks(); - for ( int i = 0; i < c; i++ ) - { - CFlexAnimationTrack *track = GetFlexAnimationTrack( i ); - Assert( track ); - if ( !track ) - continue; - - track->Resort( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumFlexAnimationTracks( void ) -{ - return m_FlexAnimationTracks.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : CFlexAnimationTrack -//----------------------------------------------------------------------------- -CFlexAnimationTrack *CChoreoEvent::GetFlexAnimationTrack( int index ) -{ - if ( index < 0 || index >= GetNumFlexAnimationTracks() ) - return NULL; - return m_FlexAnimationTracks[ index ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *controllername - -// Output : CFlexAnimationTrack -//----------------------------------------------------------------------------- -CFlexAnimationTrack *CChoreoEvent::AddTrack( const char *controllername ) -{ - CFlexAnimationTrack *newTrack = new CFlexAnimationTrack( this ); - newTrack->SetFlexControllerName( controllername ); - - m_FlexAnimationTracks.AddToTail( newTrack ); - - return newTrack; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveTrack( int index ) -{ - CFlexAnimationTrack *track = GetFlexAnimationTrack( index ); - if ( !track ) - return; - - m_FlexAnimationTracks.Remove( index ); - delete track; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveAllTracks( void ) -{ - while ( GetNumFlexAnimationTracks() > 0 ) - { - RemoveTrack( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *controllername - -// Output : CFlexAnimationTrack -//----------------------------------------------------------------------------- -CFlexAnimationTrack *CChoreoEvent::FindTrack( const char *controllername ) -{ - for ( int i = 0; i < GetNumFlexAnimationTracks(); i++ ) - { - CFlexAnimationTrack *t = GetFlexAnimationTrack( i ); - if ( t && !stricmp( t->GetFlexControllerName(), controllername ) ) - { - return t; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::GetTrackLookupSet( void ) -{ - return m_bTrackLookupSet; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetTrackLookupSet( bool set ) -{ - m_bTrackLookupSet = set; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsProcessing( void ) const -{ - return m_bProcessing; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *cb - -// t - -//----------------------------------------------------------------------------- -void CChoreoEvent::StartProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) -{ - Assert( !m_bProcessing ); - m_bProcessing = true; - if ( cb ) - { - cb->StartEvent( t, scene, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *cb - -// t - -//----------------------------------------------------------------------------- -void CChoreoEvent::ContinueProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) -{ - Assert( m_bProcessing ); - if ( cb ) - { - cb->ProcessEvent( t, scene, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *cb - -// t - -//----------------------------------------------------------------------------- -void CChoreoEvent::StopProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) -{ - Assert( m_bProcessing ); - if ( cb ) - { - cb->EndEvent( t, scene, this ); - } - m_bProcessing = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *cb - -// t - -//----------------------------------------------------------------------------- -bool CChoreoEvent::CheckProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) -{ - //Assert( !m_bProcessing ); - if ( cb ) - { - return cb->CheckEvent( t, scene, this ); - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::ResetProcessing( void ) -{ - if ( GetType() == LOOP ) - { - m_nLoopsRemaining = m_nNumLoops; - } - - m_bProcessing = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *mixer - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetMixer( CAudioMixer *mixer ) -{ - m_pMixer = mixer; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CAudioMixer -//----------------------------------------------------------------------------- -CAudioMixer *CChoreoEvent::GetMixer( void ) const -{ - return m_pMixer; -} - -// Snap to scene framerate -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::SnapTimes() -{ - if ( HasEndTime() && !IsFixedLength() ) - { - m_flEndTime = SnapTime( m_flEndTime ); - } - float oldstart = m_flStartTime; - m_flStartTime = SnapTime( m_flStartTime ); - - // Don't snap end time for fixed length events, just set based on new start time - if ( IsFixedLength() ) - { - float dt = m_flStartTime - oldstart; - m_flEndTime += dt; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::SnapTime( float t ) -{ - CChoreoScene *scene = GetScene(); - if ( !scene) - { - Assert( 0 ); - return t; - } - - return scene->SnapTime( t ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoScene -//----------------------------------------------------------------------------- -CChoreoScene *CChoreoEvent::GetScene( void ) -{ - return m_pScene; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetScene( CChoreoScene *scene ) -{ - m_pScene = scene; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// Output : char const -//----------------------------------------------------------------------------- -const char *CChoreoEvent::NameForAbsoluteTagType( AbsTagType t ) -{ - switch ( t ) - { - case PLAYBACK: - return "playback_time"; - case ORIGINAL: - return "shifted_time"; - default: - break; - } - - return "AbsTagType(unknown)"; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : AbsTagType -//----------------------------------------------------------------------------- -CChoreoEvent::AbsTagType CChoreoEvent::TypeForAbsoluteTagName( const char *name ) -{ - if ( !Q_strcasecmp( name, "playback_time" ) ) - { - return PLAYBACK; - } - else if ( !Q_strcasecmp( name, "shifted_time" ) ) - { - return ORIGINAL; - } - - return (AbsTagType)-1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -//----------------------------------------------------------------------------- -void CChoreoEvent::ClearAllAbsoluteTags( AbsTagType type ) -{ - m_AbsoluteTags[ type ].Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumAbsoluteTags( AbsTagType type ) -{ - return m_AbsoluteTags[ type ].Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// tagnum - -// Output : CEventAbsoluteTag -//----------------------------------------------------------------------------- -CEventAbsoluteTag *CChoreoEvent::GetAbsoluteTag( AbsTagType type, int tagnum ) -{ - Assert( tagnum >= 0 && tagnum < m_AbsoluteTags[ type ].Size() ); - return &m_AbsoluteTags[ type ][ tagnum ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *tagname - -// Output : CEventAbsoluteTag -//----------------------------------------------------------------------------- -CEventAbsoluteTag *CChoreoEvent::FindAbsoluteTag( AbsTagType type, const char *tagname ) -{ - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; - if ( !ptag ) - continue; - - if ( !stricmp( ptag->GetName(), tagname ) ) - { - return ptag; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *tagname - -// t - -//----------------------------------------------------------------------------- -void CChoreoEvent::AddAbsoluteTag( AbsTagType type, const char *tagname, float t ) -{ - CEventAbsoluteTag at( this, tagname, t ); - m_AbsoluteTags[ type ].AddToTail( at ); - - // Sort tags - CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f ); - - // ugly bubble sort - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - for ( int j = i + 1; j < m_AbsoluteTags[ type ].Size(); j++ ) - { - CEventAbsoluteTag *t1 = &m_AbsoluteTags[ type ][ i ]; - CEventAbsoluteTag *t2 = &m_AbsoluteTags[ type ][ j ]; - - if ( t1->GetPercentage() > t2->GetPercentage() ) - { - temp = *t1; - *t1 = *t2; - *t2 = temp; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *tagname - -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveAbsoluteTag( AbsTagType type, const char *tagname ) -{ - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; - if ( !ptag ) - continue; - - if ( !stricmp( ptag->GetName(), tagname ) ) - { - m_AbsoluteTags[ type ].Remove( i ); - return; - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: makes sure tags in PLAYBACK are in the same order as ORIGINAL -// Input : -// Output : true if they were in order, false if it has to reorder them -//----------------------------------------------------------------------------- -bool CChoreoEvent::VerifyTagOrder( ) -{ - bool bInOrder = true; - - // Sort tags - CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f ); - - for ( int i = 0; i < m_AbsoluteTags[ CChoreoEvent::ORIGINAL ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ CChoreoEvent::ORIGINAL ][ i ]; - if ( !ptag ) - continue; - - CEventAbsoluteTag *t1 = &m_AbsoluteTags[ CChoreoEvent::PLAYBACK ][ i ]; - - if ( stricmp( ptag->GetName(), t1->GetName() ) == 0) - continue; - - bInOrder = false; - for ( int j = i + 1; j < m_AbsoluteTags[ CChoreoEvent::PLAYBACK ].Size(); j++ ) - { - CEventAbsoluteTag *t2 = &m_AbsoluteTags[ CChoreoEvent::PLAYBACK ][ j ]; - - if ( stricmp( ptag->GetName(), t2->GetName() ) == 0 ) - { - temp = *t1; - *t1 = *t2; - *t2 = temp; - break; - } - } - } - return bInOrder; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *tagname - -//----------------------------------------------------------------------------- - -float CChoreoEvent::GetBoundedAbsoluteTagPercentage( AbsTagType type, int tagnum ) -{ - if ( tagnum <= -2 ) - { - /* - if (GetNumAbsoluteTags( type ) >= 1) - { - CEventAbsoluteTag *tag = GetAbsoluteTag( type, 0 ); - Assert( tag ); - return -tag->GetTime(); - } - */ - return 0.0f; // -0.5f; - } - else if ( tagnum == -1 ) - { - return 0.0f; - } - else if ( tagnum == GetNumAbsoluteTags( type ) ) - { - return 1.0; - } - else if ( tagnum > GetNumAbsoluteTags( type ) ) - { - /* - if (GetNumAbsoluteTags( type ) >= 1) - { - CEventAbsoluteTag *tag = GetAbsoluteTag( type, tagnum - 2 ); - Assert( tag ); - return 2.0 - tag->GetTime(); - } - */ - return 1.0; // 1.5; - } - - /* - { - float duration = GetDuration(); - - if ( type == SHIFTED ) - { - float seqduration; - GetGestureSequenceDuration( seqduration ); - return seqduration; - } - return duration; - } - */ - - CEventAbsoluteTag *tag = GetAbsoluteTag( type, tagnum ); - Assert( tag ); - return tag->GetPercentage(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetOriginalPercentageFromPlaybackPercentage( float t ) -{ - Assert( GetType() == GESTURE ); - if ( GetType() != GESTURE ) - return t; - - int count = GetNumAbsoluteTags( PLAYBACK ); - - if ( count != GetNumAbsoluteTags( ORIGINAL ) ) - { - return t; - } - - if ( count <= 0 ) - { - return t; - } - - if ( t <= 0.0f ) - return 0.0f; - - float s = 0.0f, n = 0.0f; - - // find what tags this is between - int i; - for ( i = -1 ; i < count; i++ ) - { - s = GetBoundedAbsoluteTagPercentage( PLAYBACK, i ); - n = GetBoundedAbsoluteTagPercentage( PLAYBACK, i + 1 ); - - if ( t >= s && t <= n ) - { - break; - } - } - - int prev = i - 1; - int start = i; - int end = i + 1; - int next = i + 2; - - prev = MAX( -2, prev ); - start = MAX( -1, start ); - end = MIN( end, count ); - next = MIN( next, count + 1 ); - - CEventAbsoluteTag *pStartTag = NULL; - CEventAbsoluteTag *pEndTag = NULL; - - // check for linear portion of lookup - if (start >= 0 && start < count) - { - pStartTag = GetAbsoluteTag( PLAYBACK, start ); - } - if (end >= 0 && end < count) - { - pEndTag = GetAbsoluteTag( PLAYBACK, end ); - } - - if (pStartTag && pEndTag) - { - if (pStartTag->GetLinear() && pEndTag->GetLinear()) - { - CEventAbsoluteTag *pOrigStartTag = GetAbsoluteTag( ORIGINAL, start ); - CEventAbsoluteTag *pOrigEndTag = GetAbsoluteTag( ORIGINAL, end ); - - if (pOrigStartTag && pOrigEndTag) - { - s = ( t - pStartTag->GetPercentage() ) / (pEndTag->GetPercentage() - pStartTag->GetPercentage()); - return (1 - s) * pOrigStartTag->GetPercentage() + s * pOrigEndTag->GetPercentage(); - } - } - } - - float dt = n - s; - - Vector vPre( GetBoundedAbsoluteTagPercentage( PLAYBACK, prev ), GetBoundedAbsoluteTagPercentage( ORIGINAL, prev ), 0 ); - Vector vStart( GetBoundedAbsoluteTagPercentage( PLAYBACK, start ), GetBoundedAbsoluteTagPercentage( ORIGINAL, start ), 0 ); - Vector vEnd( GetBoundedAbsoluteTagPercentage( PLAYBACK, end ), GetBoundedAbsoluteTagPercentage( ORIGINAL, end ), 0 ); - Vector vNext( GetBoundedAbsoluteTagPercentage( PLAYBACK, next ), GetBoundedAbsoluteTagPercentage( ORIGINAL, next ), 0 ); - - // simulate sections of either side of "linear" portion of ramp as linear slope - if (pStartTag && pStartTag->GetLinear()) - { - vPre.Init( vStart.x - (vEnd.x - vStart.x), vStart.y - (vEnd.y - vStart.y), 0 ); - } - - if (pEndTag && pEndTag->GetLinear()) - { - vNext.Init( vEnd.x + (vEnd.x - vStart.x), vEnd.y + (vEnd.y - vStart.y), 0 ); - } - - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( t - s ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - Catmull_Rom_Spline_NormalizeX( - vPre, - vStart, - vEnd, - vNext, - f2, - vOut ); - - return vOut.y; - - /* - float duration; - GetGestureSequenceDuration( duration ); - - float retval = clamp( vOut.y, 0.0f, duration ); - return retval; - */ -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetPlaybackPercentageFromOriginalPercentage( float t ) -{ - Assert( GetType() == GESTURE ); - if ( GetType() != GESTURE ) - return t; - - int count = GetNumAbsoluteTags( PLAYBACK ); - - if ( count != GetNumAbsoluteTags( ORIGINAL ) ) - { - return t; - } - - if ( count <= 0 ) - { - return t; - } - - if ( t <= 0.0f ) - return 0.0f; - - float s = 0.0f, n = 0.0f; - - // find what tags this is between - int i; - for ( i = -1 ; i < count; i++ ) - { - s = GetBoundedAbsoluteTagPercentage( PLAYBACK, i ); - n = GetBoundedAbsoluteTagPercentage( PLAYBACK, i + 1 ); - - if ( t >= s && t <= n ) - { - break; - } - } - - int prev = i - 1; - int start = i; - int end = i + 1; - int next = i + 2; - - prev = MAX( -2, prev ); - start = MAX( -1, start ); - end = MIN( end, count ); - next = MIN( next, count + 1 ); - - CEventAbsoluteTag *pStartTag = NULL; - CEventAbsoluteTag *pEndTag = NULL; - - // check for linear portion of lookup - if (start >= 0 && start < count) - { - pStartTag = GetAbsoluteTag( ORIGINAL, start ); - } - if (end >= 0 && end < count) - { - pEndTag = GetAbsoluteTag( ORIGINAL, end ); - } - - // check for linear portion of lookup - if (pStartTag && pEndTag) - { - if (pStartTag->GetLinear() && pEndTag->GetLinear()) - { - CEventAbsoluteTag *pPlaybackStartTag = GetAbsoluteTag( PLAYBACK, start ); - CEventAbsoluteTag *pPlaybackEndTag = GetAbsoluteTag( PLAYBACK, end ); - - if (pPlaybackStartTag && pPlaybackEndTag) - { - s = ( t - pStartTag->GetPercentage() ) / (pEndTag->GetPercentage() - pStartTag->GetPercentage()); - return (1 - s) * pPlaybackStartTag->GetPercentage() + s * pPlaybackEndTag->GetPercentage(); - } - } - } - - float dt = n - s; - - Vector vPre( GetBoundedAbsoluteTagPercentage( ORIGINAL, prev ), GetBoundedAbsoluteTagPercentage( PLAYBACK, prev ), 0 ); - Vector vStart( GetBoundedAbsoluteTagPercentage( ORIGINAL, start ), GetBoundedAbsoluteTagPercentage( PLAYBACK, start ), 0 ); - Vector vEnd( GetBoundedAbsoluteTagPercentage( ORIGINAL, end ), GetBoundedAbsoluteTagPercentage( PLAYBACK, end ), 0 ); - Vector vNext( GetBoundedAbsoluteTagPercentage( ORIGINAL, next ), GetBoundedAbsoluteTagPercentage( PLAYBACK, next ), 0 ); - - // simulate sections of either side of "linear" portion of ramp as linear slope - if (pStartTag && pStartTag->GetLinear()) - { - vPre.Init( vStart.x - (vEnd.x - vStart.x), vStart.y - (vEnd.y - vStart.y), 0 ); - } - - if (pEndTag && pEndTag->GetLinear()) - { - vNext.Init( vEnd.x + (vEnd.x - vStart.x), vEnd.y + (vEnd.y - vStart.y), 0 ); - } - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( t - s ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - Catmull_Rom_Spline_NormalizeX( - vPre, - vStart, - vEnd, - vNext, - f2, - vOut ); - - return vOut.y; - - /* - float duration; - GetGestureSequenceDuration( duration ); - - float retval = clamp( vOut.y, 0.0f, duration ); - return retval; - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : duration - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetGestureSequenceDuration( float duration ) -{ - m_flGestureSequenceDuration = duration; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : duration - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::GetGestureSequenceDuration( float& duration ) -{ - bool valid = m_flGestureSequenceDuration != 0.0f; - - if ( !valid ) - { - duration = GetDuration(); - } - else - { - duration = m_flGestureSequenceDuration; - } - - return valid; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pitch - -//----------------------------------------------------------------------------- -int CChoreoEvent::GetPitch( void ) const -{ - return m_nPitch; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pitch - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetPitch( int pitch ) -{ - m_nPitch = pitch; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : yaw - -//----------------------------------------------------------------------------- -int CChoreoEvent::GetYaw( void ) const -{ - return m_nYaw; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : yaw - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetYaw( int yaw ) -{ - m_nYaw = yaw; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// -1 - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetLoopCount( int numloops ) -{ - Assert( GetType() == LOOP ); - // Never below -1 - m_nNumLoops = MAX( numloops, -1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumLoopsRemaining( void ) -{ - Assert( GetType() == LOOP ); - - return m_nLoopsRemaining; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : loops - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetNumLoopsRemaining( int loops ) -{ - Assert( GetType() == LOOP ); - - m_nLoopsRemaining = loops; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetLoopCount( void ) -{ - Assert( GetType() == LOOP ); - return m_nNumLoops; -} - -EdgeInfo_t *CCurveData::GetEdgeInfo( int idx ) -{ - return &m_RampEdgeInfo[ idx ]; -} - -int CCurveData::GetCount( void ) -{ - return m_Ramp.Count(); -} - -CExpressionSample *CCurveData::Get( int index ) -{ - if ( index < 0 || index >= GetCount() ) - return NULL; - - return &m_Ramp[ index ]; -} - -CExpressionSample *CCurveData::Add( float time, float value, bool selected ) -{ - CExpressionSample sample; - - sample.time = time; - sample.value = value; - sample.selected = selected; - - int idx = m_Ramp.AddToTail( sample ); - return &m_Ramp[ idx ]; -} - -void CCurveData::Delete( int index ) -{ - if ( index < 0 || index >= GetCount() ) - return; - - m_Ramp.Remove( index ); -} - -void CCurveData::Clear( void ) -{ - m_Ramp.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCurveData::Resort( ICurveDataAccessor *data ) -{ - for ( int i = 0; i < m_Ramp.Size(); i++ ) - { - for ( int j = i + 1; j < m_Ramp.Size(); j++ ) - { - CExpressionSample src = m_Ramp[ i ]; - CExpressionSample dest = m_Ramp[ j ]; - - if ( src.time > dest.time ) - { - m_Ramp[ i ] = dest; - m_Ramp[ j ] = src; - } - } - } - - RemoveOutOfRangeSamples( data ); - - // m_RampAccumulator.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : number - -// Output : CExpressionSample -//----------------------------------------------------------------------------- -CExpressionSample *CCurveData::GetBoundedSample( ICurveDataAccessor *data, int number, bool& bClamped ) -{ - // Search for two samples which span time f - if ( number < 0 ) - { - static CExpressionSample nullstart; - nullstart.time = 0.0f; - nullstart.value = GetEdgeZeroValue( true ); - nullstart.SetCurveType( GetEdgeCurveType( true ) ); - bClamped = true; - return &nullstart; - } - else if ( number >= GetCount() ) - { - static CExpressionSample nullend; - nullend.time = data->GetDuration(); - nullend.value = GetEdgeZeroValue( false ); - nullend.SetCurveType( GetEdgeCurveType( false ) ); - bClamped = true; - return &nullend; - } - - bClamped = false; - return Get( number ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCurveData::RemoveOutOfRangeSamples( ICurveDataAccessor *data ) -{ - float duration = data->GetDuration(); - - int c = GetCount(); - for ( int i = c-1; i >= 0; i-- ) - { - CExpressionSample src = m_Ramp[ i ]; - if ( src.time < 0 || - src.time > duration + 0.01 ) - { - m_Ramp.Remove( i ); - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::RescaleGestureTimes( float newstart, float newend, bool bMaintainAbsoluteTagPositions ) -{ - if ( GetType() != CChoreoEvent::GESTURE ) - return; - - // Did it actually change - if ( newstart == GetStartTime() && - newend == GetEndTime() ) - { - return; - } - - float newduration = newend - newstart; - - float dt = 0.0f; - //If the end is moving, leave tags stay where they are (dt == 0.0f) - if ( newstart != GetStartTime() ) - { - // Otherwise, if the new start is later, then tags need to be shifted backwards - dt -= ( newstart - GetStartTime() ); - } - - if ( bMaintainAbsoluteTagPositions ) - { - int i; - int count = GetNumAbsoluteTags( CChoreoEvent::PLAYBACK ); - for ( i = 0; i < count; i++ ) - { - CEventAbsoluteTag *tag = GetAbsoluteTag( CChoreoEvent::PLAYBACK, i ); - float tagtime = tag->GetPercentage() * GetDuration(); - - tagtime += dt; - - tagtime = clamp( tagtime / newduration, 0.0f, 1.0f ); - - tag->SetPercentage( tagtime ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Make sure tags aren't co-located or out of order -//----------------------------------------------------------------------------- -bool CChoreoEvent::PreventTagOverlap( void ) -{ - bool bHadOverlap = false; - - // FIXME: limit to single frame? - float minDp = 0.01; - - float minP = 1.00; - - int count = GetNumAbsoluteTags( CChoreoEvent::PLAYBACK ); - for ( int i = count - 1; i >= 0; i-- ) - { - CEventAbsoluteTag *tag = GetAbsoluteTag( CChoreoEvent::PLAYBACK, i ); - - if (tag->GetPercentage() > minP) - { - tag->SetPercentage( minP ); - - minDp = MIN( 0.01, minP / (i + 1) ); - bHadOverlap = true; - } - else - { - minP = tag->GetPercentage(); - } - minP = MAX( minP - minDp, 0 ); - } - - return bHadOverlap; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : CEventAbsoluteTag -//----------------------------------------------------------------------------- -CEventAbsoluteTag *CChoreoEvent::FindEntryTag( AbsTagType type ) -{ - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; - if ( !ptag ) - continue; - - if ( ptag->GetEntry() ) - { - return ptag; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : CEventAbsoluteTag -//----------------------------------------------------------------------------- -CEventAbsoluteTag *CChoreoEvent::FindExitTag( AbsTagType type ) -{ - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; - if ( !ptag ) - continue; - - if ( ptag->GetExit() ) - { - return ptag; - } - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *style - -// maxlen - -//----------------------------------------------------------------------------- -void CChoreoEvent::GetMovementStyle( char *style, int maxlen ) -{ - Assert( GetType() == MOVETO ); - - style[0] = 0; - - const char *in = m_Parameters2.Get(); - char *out = style; - - while ( *in && *in != '\0' && *in != ' ' ) - { - if ( out - style >= maxlen - 1 ) - break; - *out++ = *in++; - } - - *out = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *style - -// maxlen - -//----------------------------------------------------------------------------- -void CChoreoEvent::GetDistanceStyle( char *style, int maxlen ) -{ - Assert( GetType() == MOVETO ); - - style[0]= 0; - - const char *in = Q_strstr( m_Parameters2.Get(), " " ); - if ( !in ) - return; - - in++; - char *out = style; - - while ( *in && *in != '\0' ) - { - if ( out - style >= maxlen - 1 ) - break; - *out++ = *in++; - } - - *out = 0; -} - -void CChoreoEvent::SetCloseCaptionType( CLOSECAPTION type ) -{ - Assert( m_fType == SPEAK ); - m_ccType = type; -} - -CChoreoEvent::CLOSECAPTION CChoreoEvent::GetCloseCaptionType() const -{ - Assert( m_fType == SPEAK ); - return (CLOSECAPTION)m_ccType; -} - -void CChoreoEvent::SetCloseCaptionToken( char const *token ) -{ - Assert( m_fType == SPEAK ); - Assert( token ); - m_CCToken = token; -} - -char const *CChoreoEvent::GetCloseCaptionToken() const -{ - Assert( m_fType == SPEAK ); - return m_CCToken.Get(); -} - -bool CChoreoEvent::GetPlaybackCloseCaptionToken( char *dest, int destlen ) -{ - dest[0] = 0; - - Assert( m_fType == SPEAK ); - - switch ( m_ccType ) - { - default: - case CC_DISABLED: - { - return false; - } - case CC_SLAVE: - { - // If it's a slave, then only disable if we're not using the combined wave - if ( IsUsingCombinedFile() ) - { - return false; - } - - if ( m_CCToken[ 0 ] != 0 ) - { - Q_strncpy( dest, m_CCToken.Get(), destlen ); - } - else - { - Q_strncpy( dest, m_Parameters.Get(), destlen ); - } - return true; - } - case CC_MASTER: - { - // Always use the override if we're the master, otherwise always use the default - // parameter - if ( m_CCToken[ 0 ] != 0 ) - { - Q_strncpy( dest, m_CCToken.Get(), destlen ); - } - else - { - Q_strncpy( dest, m_Parameters.Get(), destlen ); - } - return true; - } - } - - return false; -} - - -void CChoreoEvent::SetUsingCombinedFile( bool isusing ) -{ - Assert( m_fType == SPEAK ); - m_bUsingCombinedSoundFile = isusing; -} - -bool CChoreoEvent::IsUsingCombinedFile() const -{ - Assert( m_fType == SPEAK ); - return m_bUsingCombinedSoundFile; -} - -void CChoreoEvent::SetRequiredCombinedChecksum( unsigned int checksum ) -{ - Assert( m_fType == SPEAK ); - m_uRequiredCombinedChecksum = checksum; -} - -unsigned int CChoreoEvent::GetRequiredCombinedChecksum() -{ - Assert( m_fType == SPEAK ); - return m_uRequiredCombinedChecksum; -} - -void CChoreoEvent::SetNumSlaves( int num ) -{ - Assert( m_fType == SPEAK ); - Assert( num >= 0 ); - m_nNumSlaves = num; -} - -int CChoreoEvent::GetNumSlaves() const -{ - Assert( m_fType == SPEAK ); - return m_nNumSlaves; -} - -void CChoreoEvent::SetLastSlaveEndTime( float t ) -{ - Assert( m_fType == SPEAK ); - m_flLastSlaveEndTime = t; -} - -float CChoreoEvent::GetLastSlaveEndTime() const -{ - Assert( m_fType == SPEAK ); - return m_flLastSlaveEndTime; -} - -void CChoreoEvent::SetCloseCaptionTokenValid( bool valid ) -{ - Assert( m_fType == SPEAK ); - m_bCCTokenValid = valid; -} - -bool CChoreoEvent::GetCloseCaptionTokenValid() const -{ - Assert( m_fType == SPEAK ); - return m_bCCTokenValid; -} - - -//----------------------------------------------------------------------------- -// Purpose: Removes characters which can't appear in windows filenames -// Input : *in - -// *dest - -// destlen - -// Output : static void -//----------------------------------------------------------------------------- -static void CleanupTokenName( char const *in, char *dest, int destlen ) -{ - char *out = dest; - while ( *in && ( out - dest ) < destlen ) - { - if ( V_isalnum( *in ) || // lowercase, uppercase, digits and underscore are valid - *in == '_' ) - { - *out++ = *in; - } - else - { - *out++ = '_'; // Put underscores in for bogus characters - } - in++; - } - *out = 0; -} - -bool CChoreoEvent::ComputeCombinedBaseFileName( char *dest, int destlen, bool creategenderwildcard ) -{ - if ( m_fType != SPEAK ) - return false; - - if ( m_ccType != CC_MASTER ) - return false; - - if ( GetNumSlaves() == 0 ) - return false; - - if ( !m_pScene ) - return false; - - char vcdpath[ 512 ]; - char cleanedtoken[ MAX_CCTOKEN_STRING ]; - CleanupTokenName( m_CCToken.Get(), cleanedtoken, sizeof( cleanedtoken ) ); - - if ( Q_strlen( cleanedtoken ) <= 0 ) - return false; - - Q_strncpy( vcdpath, m_pScene->GetFilename(), sizeof( vcdpath ) ); - Q_StripFilename( vcdpath ); - Q_FixSlashes( vcdpath, '/' ); - - char *pvcd = vcdpath; - - char *offset = Q_strstr( vcdpath, "scenes" ); - if ( offset ) - { - pvcd = offset + 6; - if ( *pvcd == '/' ) - { - ++pvcd; - } - } - - int len = Q_strlen( pvcd ); - - if ( len > 0 && ( len + 1 ) < ( sizeof( vcdpath ) - 1 ) ) - { - pvcd[ len ] = '/'; - pvcd[ len + 1 ] = 0; - } - - Assert( !Q_strstr( pvcd, ":" ) ); - - if ( creategenderwildcard ) - { - Q_snprintf( dest, destlen, "sound/combined/%s%s_$gender.wav", pvcd, cleanedtoken ); - } - else - { - Q_snprintf( dest, destlen, "sound/combined/%s%s.wav", pvcd, cleanedtoken ); - } - return true; -} - -bool CChoreoEvent::IsCombinedUsingGenderToken() const -{ - return m_bCombinedUsingGenderToken; -} - -void CChoreoEvent::SetCombinedUsingGenderToken( bool using_gender ) -{ - m_bCombinedUsingGenderToken = using_gender; -} - - -int CChoreoEvent::ValidateCombinedFile() -{ - - return 0; -} - -bool CChoreoEvent::IsSuppressingCaptionAttenuation() const -{ - return m_bSuppressCaptionAttenuation; -} - -void CChoreoEvent::SetSuppressingCaptionAttenuation( bool suppress ) -{ - m_bSuppressCaptionAttenuation = suppress; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::ClearEventDependencies() -{ - m_Dependencies.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *other - -//----------------------------------------------------------------------------- -void CChoreoEvent::AddEventDependency( CChoreoEvent *other ) -{ - if ( m_Dependencies.Find( other ) == m_Dependencies.InvalidIndex() ) - { - m_Dependencies.AddToTail( other ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : list - -//----------------------------------------------------------------------------- -void CChoreoEvent::GetEventDependencies( CUtlVector< CChoreoEvent * >& list ) -{ - int c = m_Dependencies.Count(); - for ( int i = 0; i < c; ++i ) - { - list.AddToTail( m_Dependencies[ i ] ); - } -} - -void CCurveData::SetEdgeInfo( bool leftEdge, int curveType, float zero ) -{ - int idx = leftEdge ? 0 : 1; - m_RampEdgeInfo[ idx ].m_CurveType = curveType; - m_RampEdgeInfo[ idx ].m_flZeroPos = zero; -} - -void CCurveData::GetEdgeInfo( bool leftEdge, int& curveType, float& zero ) const -{ - int idx = leftEdge ? 0 : 1; - curveType = m_RampEdgeInfo[ idx ].m_CurveType; - zero = m_RampEdgeInfo[ idx ].m_flZeroPos; -} - -void CCurveData::SetEdgeActive( bool leftEdge, bool state ) -{ - int idx = leftEdge ? 0 : 1; - m_RampEdgeInfo[ idx ].m_bActive = state; -} - -bool CCurveData::IsEdgeActive( bool leftEdge ) const -{ - int idx = leftEdge ? 0 : 1; - return m_RampEdgeInfo[ idx ].m_bActive; -} - -int CCurveData::GetEdgeCurveType( bool leftEdge ) const -{ - if ( !IsEdgeActive( leftEdge ) ) - { - return CURVE_DEFAULT; - } - - int idx = leftEdge ? 0 : 1; - return m_RampEdgeInfo[ idx ].m_CurveType; -} - -float CCurveData::GetEdgeZeroValue( bool leftEdge ) const -{ - if ( !IsEdgeActive( leftEdge ) ) - { - return 0.0f; - } - - int idx = leftEdge ? 0 : 1; - return m_RampEdgeInfo[ idx ].m_flZeroPos; -} - - -void CChoreoEvent::SaveToBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ) -{ - buf.PutChar( GetType() ); - buf.PutShort( pStringPool->FindOrAddString( GetName() ) ); - - float st = GetStartTime(); - buf.PutFloat( st ); - - float et = GetEndTime(); - buf.PutFloat( et ); - - buf.PutShort( pStringPool->FindOrAddString( GetParameters() ) ); - buf.PutShort( pStringPool->FindOrAddString( GetParameters2() ) ); - buf.PutShort( pStringPool->FindOrAddString( GetParameters3() ) ); - - m_Ramp.SaveToBuffer( buf, pStringPool ); - - int flags = 0; - flags |= IsResumeCondition() ? 1<<0 : 0; - flags |= IsLockBodyFacing() ? 1<<1 : 0; - flags |= IsFixedLength() ? 1<<2 : 0; - flags |= GetActive() ? 1<<3 : 0; - flags |= GetForceShortMovement() ? 1<<4 : 0; - flags |= GetPlayOverScript() ? 1<<5 : 0; - - buf.PutUnsignedChar( flags ); - - buf.PutFloat( GetDistanceToTarget() ); - - int numRelativeTags = GetNumRelativeTags(); - Assert( numRelativeTags <= 255 ); - buf.PutUnsignedChar( numRelativeTags ); - - for ( int t = 0; t < numRelativeTags; t++ ) - { - CEventRelativeTag *rt = GetRelativeTag( t ); - Assert( rt ); - buf.PutShort( pStringPool->FindOrAddString( rt->GetName() ) ); - - Assert( rt->GetPercentage() >= 0.0f && rt->GetPercentage() <= 1.0f ); - unsigned char p = rt->GetPercentage() * 255.0f; - buf.PutUnsignedChar( p ); - } - - int numTimingTags = GetNumTimingTags(); - Assert( numTimingTags <= 255 ); - buf.PutUnsignedChar( numTimingTags ); - - for ( int t = 0; t < numTimingTags; t++ ) - { - CFlexTimingTag *tt = GetTimingTag( t ); - Assert( tt ); - buf.PutShort( pStringPool->FindOrAddString( tt->GetName() ) ); - - // save as u0.8 - Assert( tt->GetPercentage() >= 0.0f && tt->GetPercentage() <= 1.0f ); - unsigned char p = tt->GetPercentage() * 255.0f; - buf.PutUnsignedChar( p ); - - // Don't save locked state, it's only used by the editor tt->GetLocked() - } - - int tagtype; - for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ ) - { - int num = GetNumAbsoluteTags( (CChoreoEvent::AbsTagType)tagtype ); - Assert( num <= 255 ); - buf.PutUnsignedChar( num ); - - for ( int i = 0; i < num ; ++i ) - { - CEventAbsoluteTag *abstag = GetAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, i ); - Assert( abstag ); - buf.PutShort( pStringPool->FindOrAddString( abstag->GetName() ) ); - - // save as u4.12 - Assert( abstag->GetPercentage() >= 0.0f && abstag->GetPercentage() <= 15.0f ); - unsigned short p = abstag->GetPercentage() * 4096.0f; - buf.PutUnsignedShort( p ); - } - } - - if ( GetType() == CChoreoEvent::GESTURE ) - { - float duration; - if ( GetGestureSequenceDuration( duration ) ) - { - buf.PutFloat( duration ); - } - else - { - buf.PutFloat( -1.0f ); - } - } - - buf.PutChar( IsUsingRelativeTag() ? 1 : 0 ); - if ( IsUsingRelativeTag() ) - { - buf.PutShort( pStringPool->FindOrAddString( GetRelativeTagName() ) ); - buf.PutShort( pStringPool->FindOrAddString( GetRelativeWavName() ) ); - } - - SaveFlexAnimationsToBuffer( buf, pStringPool ); - - if ( GetType() == LOOP ) - { - buf.PutChar( GetLoopCount() ); - } - - if ( GetType() == CChoreoEvent::SPEAK ) - { - buf.PutChar( GetCloseCaptionType() ); - buf.PutShort( pStringPool->FindOrAddString( GetCloseCaptionToken() ) ); - flags = 0; - - if ( GetCloseCaptionType() != CChoreoEvent::CC_DISABLED && - IsUsingCombinedFile() ) - { - flags |= ( 1<<0 ); - } - if ( IsCombinedUsingGenderToken() ) - { - flags |= ( 1<<1 ); - } - if ( IsSuppressingCaptionAttenuation() ) - { - flags |= ( 1<<2 ); - } - - buf.PutChar( flags ); - } -} - -bool CChoreoEvent::RestoreFromBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ) -{ - MEM_ALLOC_CREDIT(); - - SetType( (EVENTTYPE)buf.GetChar() ); - char sz[ 256 ]; - pStringPool->GetString( buf.GetShort(), sz, sizeof( sz ) ); - SetName( sz ); - - SetStartTime( buf.GetFloat() ); - SetEndTime( buf.GetFloat() ); - - char params[ 2048 ]; - pStringPool->GetString( buf.GetShort(), params, sizeof( params ) ); - SetParameters( params ); - pStringPool->GetString( buf.GetShort(), params, sizeof( params ) ); - SetParameters2( params ); - pStringPool->GetString( buf.GetShort(), params, sizeof( params ) ); - SetParameters3( params ); - - if ( !m_Ramp.RestoreFromBuffer( buf, pStringPool ) ) - return false; - - int flags = buf.GetUnsignedChar(); - SetResumeCondition( ( flags & ( 1<<0 ) ) ? true : false ); - SetLockBodyFacing( ( flags & ( 1<<1 ) ) ? true : false ); - SetFixedLength( ( flags & ( 1<<2 ) ) ? true : false ); - SetActive( ( flags & ( 1<<3 ) ) ? true : false ); - SetForceShortMovement( ( flags & ( 1<<4 ) ) ? true : false ); - SetPlayOverScript( ( flags & ( 1<<5 ) ) ? true : false ); - - SetDistanceToTarget( buf.GetFloat() ); - - int numRelTags = buf.GetUnsignedChar(); - for ( int i = 0; i < numRelTags; ++i ) - { - char tagName[ 256 ]; - pStringPool->GetString( buf.GetShort(), tagName, sizeof( tagName ) ); - float percentage = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - AddRelativeTag( tagName, percentage ); - } - - int numTimingTags = buf.GetUnsignedChar(); - for ( int i = 0; i < numTimingTags; ++i ) - { - char tagName[ 256 ]; - pStringPool->GetString( buf.GetShort(), tagName, sizeof( tagName ) ); - float percentage = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - // Don't parse locked state, only used by editors - AddTimingTag( tagName, percentage, false ); - } - - int tagtype; - for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ ) - { - int num = buf.GetUnsignedChar(); - for ( int i = 0; i < num; ++i ) - { - char tagName[ 256 ]; - pStringPool->GetString( buf.GetShort(), tagName, sizeof( tagName ) ); - float percentage = (float)buf.GetUnsignedShort() * 1.0f/4096.0f; - - // Don't parse locked state, only used by editors - AddAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, tagName, percentage ); - } - } - - if ( GetType() == CChoreoEvent::GESTURE ) - { - float duration = buf.GetFloat(); - if ( duration != -1 ) - { - SetGestureSequenceDuration( duration ); - } - } - - if ( buf.GetChar() == 1 ) - { - char tagname[ 256 ]; - char wavname[ 256 ]; - pStringPool->GetString( buf.GetShort(), tagname, sizeof( tagname ) ); - pStringPool->GetString( buf.GetShort(), wavname, sizeof( wavname ) ); - - SetUsingRelativeTag( true, tagname, wavname ); - } - - if ( !RestoreFlexAnimationsFromBuffer( buf, pStringPool ) ) - return false; - - if ( GetType() == LOOP ) - { - SetLoopCount( buf.GetChar() ); - } - - if ( GetType() == CChoreoEvent::SPEAK ) - { - SetCloseCaptionType( (CLOSECAPTION)buf.GetChar() ); - char cctoken[ 256 ]; - pStringPool->GetString( buf.GetShort(), cctoken, sizeof( cctoken ) ); - SetCloseCaptionToken( cctoken ); - int flags = buf.GetChar(); - if ( flags & ( 1<<0 ) ) - { - SetUsingCombinedFile( true ); - } - if ( flags & ( 1<<1 ) ) - { - SetCombinedUsingGenderToken( true ); - } - if ( flags & ( 1<<2 ) ) - { - SetSuppressingCaptionAttenuation( true ); - } - } - - return true; -} - -void CCurveData::SaveToBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) -{ - int c = GetCount(); - Assert( c <= 255 ); - buf.PutUnsignedChar( c ); - - for ( int i = 0; i < c; i++ ) - { - CExpressionSample *sample = Get( i ); - buf.PutFloat( sample->time ); - - Assert( sample->value >= 0.0f && sample->value <= 1.0f ); - unsigned char v = sample->value * 255.0f; - buf.PutUnsignedChar( v ); - } -} - -bool CCurveData::RestoreFromBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) -{ - int c = buf.GetUnsignedChar(); - for ( int i = 0; i < c; i++ ) - { - float t, v; - t = buf.GetFloat(); - v = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - - Add( t, v, false ); - } - - return true; -} - -void CChoreoEvent::SaveFlexAnimationsToBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) -{ - int numFlexAnimationTracks = GetNumFlexAnimationTracks(); - Assert( numFlexAnimationTracks <= 255 ); - buf.PutUnsignedChar( numFlexAnimationTracks ); - - for ( int i = 0; i < numFlexAnimationTracks; i++ ) - { - CFlexAnimationTrack *track = GetFlexAnimationTrack( i ); - - buf.PutShort( pStringPool->FindOrAddString( track->GetFlexControllerName() ) ); - - int flags = 0; - flags |= track->IsTrackActive() ? 1<<0 : 0; - flags |= track->IsComboType() ? 1<<1 : 0; - buf.PutUnsignedChar( flags ); - - buf.PutFloat( track->GetMin() ); - buf.PutFloat( track->GetMax() ); - - buf.PutShort( track->GetNumSamples( 0 ) ); - for ( int j = 0 ; j < track->GetNumSamples( 0 ) ; j++ ) - { - CExpressionSample *s = track->GetSample( j, 0 ); - if ( !s ) - continue; - - buf.PutFloat( s->time ); - - Assert( s->value >= 0.0f && s->value <= 1.0f ); - unsigned char v = s->value * 255.0f; - buf.PutUnsignedChar( v ); - - buf.PutUnsignedShort( s->GetCurveType() ); - } - - // Write out combo samples - if ( track->IsComboType() ) - { - int numSamples = track->GetNumSamples( 1 ); - Assert( numSamples <= 32767 ); - buf.PutUnsignedShort( numSamples ); - - for ( int j = 0; j < numSamples; j++ ) - { - CExpressionSample *s = track->GetSample( j, 1 ); - if ( !s ) - continue; - - buf.PutFloat( s->time ); - - Assert( s->value >= 0.0f && s->value <= 1.0f ); - unsigned char v = s->value * 255.0f; - buf.PutUnsignedChar( v ); - - buf.PutUnsignedShort( s->GetCurveType() ); - } - } - } -} - -bool CChoreoEvent::RestoreFlexAnimationsFromBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) -{ - int numTracks = buf.GetUnsignedChar(); - - for ( int i = 0; i < numTracks; i++ ) - { - char name[ 256 ]; - pStringPool->GetString( buf.GetShort(), name, sizeof( name ) ); - - CFlexAnimationTrack *track = AddTrack( name ); - - int flags = buf.GetUnsignedChar(); - track->SetTrackActive( ( flags & ( 1<<0 ) ) ? true : false ); - track->SetComboType( ( flags & ( 1<<1 ) ) ? true : false ); - - track->SetMin( buf.GetFloat() ); - track->SetMax( buf.GetFloat() ); - - int s = buf.GetShort(); - for ( int j = 0; j < s; ++j ) - { - float t, v; - t = buf.GetFloat(); - v = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - - CExpressionSample *pSample = track->AddSample( t, v, 0 ); - pSample->SetCurveType( buf.GetUnsignedShort() ); - } - - if ( track->IsComboType() ) - { - int s = buf.GetUnsignedShort(); - for ( int j = 0; j < s; ++j ) - { - float t, v; - t = buf.GetFloat(); - v = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - - CExpressionSample *pSample = track->AddSample( t, v, 1 ); - pSample->SetCurveType( buf.GetUnsignedShort() ); - } - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Marks the event as enabled/disabled -// Input : state - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetActive( bool state ) -{ - m_bActive = state; -} - -bool CChoreoEvent::GetActive() const -{ - return m_bActive; -} +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "tier0/dbg.h" +#include +#include +#include +#include "choreoevent.h" +#include "choreoactor.h" +#include "choreochannel.h" +#include "minmax.h" +#include "mathlib/mathlib.h" +#include "tier1/strtools.h" +#include "choreoscene.h" +#include "ichoreoeventcallback.h" +#include "tier1/utlbuffer.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +int CChoreoEvent::s_nGlobalID = 1; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *owner - +// *name - +// percentage - +//----------------------------------------------------------------------------- +CEventRelativeTag::CEventRelativeTag( CChoreoEvent *owner, const char *name, float percentage ) +{ + Assert( owner ); + Assert( name ); + Assert( percentage >= 0.0f ); + Assert( percentage <= 1.0f ); + + m_Name = name; + m_flPercentage = percentage; + m_pOwner = owner; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : src - +//----------------------------------------------------------------------------- +CEventRelativeTag::CEventRelativeTag( const CEventRelativeTag& src ) +{ + m_Name = src.m_Name; + m_flPercentage = src.m_flPercentage; + m_pOwner = src.m_pOwner; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *CEventRelativeTag::GetName( void ) +{ + return m_Name.Get(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CEventRelativeTag::GetPercentage( void ) +{ + return m_flPercentage; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : percentage - +//----------------------------------------------------------------------------- +void CEventRelativeTag::SetPercentage( float percentage ) +{ + m_flPercentage = percentage; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoEvent +//----------------------------------------------------------------------------- +CChoreoEvent *CEventRelativeTag::GetOwner( void ) +{ + return m_pOwner; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *event - +//----------------------------------------------------------------------------- +void CEventRelativeTag::SetOwner( CChoreoEvent *event ) +{ + m_pOwner = event; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the corrected time based on the owner's length and start time +// Output : float +//----------------------------------------------------------------------------- +float CEventRelativeTag::GetStartTime( void ) +{ + Assert( m_pOwner ); + if ( !m_pOwner ) + { + return 0.0f; + } + + float ownerstart = m_pOwner->GetStartTime(); + float ownerduration = m_pOwner->GetDuration(); + + return ( ownerstart + ownerduration * m_flPercentage ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *owner - +// *name - +// percentage - +//----------------------------------------------------------------------------- +CFlexTimingTag::CFlexTimingTag( CChoreoEvent *owner, const char *name, float percentage, bool locked ) +: BaseClass( owner, name, percentage ) +{ + m_bLocked = locked; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : src - +//----------------------------------------------------------------------------- +CFlexTimingTag::CFlexTimingTag( const CFlexTimingTag& src ) +: BaseClass( src ) +{ + m_bLocked = src.m_bLocked; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CFlexTimingTag::GetLocked( void ) +{ + return m_bLocked; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : locked - +//----------------------------------------------------------------------------- +void CFlexTimingTag::SetLocked( bool locked ) +{ + m_bLocked = locked; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *owner - +// *name - +// percentage - +//----------------------------------------------------------------------------- +CEventAbsoluteTag::CEventAbsoluteTag( CChoreoEvent *owner, const char *name, float t ) +{ + Assert( owner ); + Assert( name ); + Assert( t >= 0.0f ); + + m_Name = name; + m_flPercentage = t; + m_pOwner = owner; + m_bLocked = false; + m_bLinear = false; + m_bEntry = false; + m_bExit = false; + +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : src - +//----------------------------------------------------------------------------- +CEventAbsoluteTag::CEventAbsoluteTag( const CEventAbsoluteTag& src ) +{ + m_Name = src.m_Name; + m_flPercentage = src.m_flPercentage; + m_pOwner = src.m_pOwner; + m_bLocked = src.m_bLocked; + m_bLinear = src.m_bLinear; + m_bEntry = src.m_bEntry; + m_bExit = src.m_bExit; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *CEventAbsoluteTag::GetName( void ) +{ + return m_Name.Get(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CEventAbsoluteTag::GetPercentage( void ) +{ + return m_flPercentage; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : percentage - +//----------------------------------------------------------------------------- +void CEventAbsoluteTag::SetPercentage( float percentage ) +{ + m_flPercentage = percentage; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CEventAbsoluteTag::GetEventTime( void ) +{ + Assert( m_pOwner ); + if ( !m_pOwner ) + { + return 0.0f; + } + + float ownerduration = m_pOwner->GetDuration(); + + return (m_flPercentage * ownerduration); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : percentage - +//----------------------------------------------------------------------------- +void CEventAbsoluteTag::SetEventTime( float t ) +{ + Assert( m_pOwner ); + if ( !m_pOwner ) + { + return; + } + + float ownerduration = m_pOwner->GetDuration(); + + m_flPercentage = (t / ownerduration); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CEventAbsoluteTag::GetAbsoluteTime( void ) +{ + Assert( m_pOwner ); + if ( !m_pOwner ) + { + return 0.0f; + } + + float ownerstart = m_pOwner->GetStartTime(); + float ownerduration = m_pOwner->GetDuration(); + + return (ownerstart + m_flPercentage * ownerduration); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : percentage - +//----------------------------------------------------------------------------- +void CEventAbsoluteTag::SetAbsoluteTime( float t ) +{ + Assert( m_pOwner ); + if ( !m_pOwner ) + { + return; + } + + float ownerstart = m_pOwner->GetStartTime(); + float ownerduration = m_pOwner->GetDuration(); + + m_flPercentage = (t - ownerstart) / ownerduration; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoEvent +//----------------------------------------------------------------------------- +CChoreoEvent *CEventAbsoluteTag::GetOwner( void ) +{ + return m_pOwner; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *event - +//----------------------------------------------------------------------------- +void CEventAbsoluteTag::SetOwner( CChoreoEvent *event ) +{ + m_pOwner = event; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *event - +//----------------------------------------------------------------------------- +void CEventAbsoluteTag::SetLocked( bool bLocked ) +{ + m_bLocked = bLocked; +} + + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoEvent +//----------------------------------------------------------------------------- +bool CEventAbsoluteTag::GetLocked( void ) +{ + return m_bLocked; +} + + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *event - +//----------------------------------------------------------------------------- +void CEventAbsoluteTag::SetLinear( bool bLinear ) +{ + m_bLinear = bLinear; +} + + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoEvent +//----------------------------------------------------------------------------- +bool CEventAbsoluteTag::GetLinear( void ) +{ + return m_bLinear; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *event - +//----------------------------------------------------------------------------- +void CEventAbsoluteTag::SetEntry( bool bEntry ) +{ + m_bEntry = bEntry; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoEvent +//----------------------------------------------------------------------------- +bool CEventAbsoluteTag::GetEntry( void ) +{ + return m_bEntry; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *event - +//----------------------------------------------------------------------------- +void CEventAbsoluteTag::SetExit( bool bExit ) +{ + m_bExit = bExit; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoEvent +//----------------------------------------------------------------------------- +bool CEventAbsoluteTag::GetExit( void ) +{ + return m_bExit; +} + + + + +// FLEX ANIMATIONS +//----------------------------------------------------------------------------- +// Purpose: Constructor +// Input : *event - +//----------------------------------------------------------------------------- +CFlexAnimationTrack::CFlexAnimationTrack( CChoreoEvent *event ) +{ + m_pEvent = event; + m_pControllerName = NULL; + m_bActive = false; + m_bCombo = false; + m_bServerSide = false; + m_nFlexControllerIndex[ 0 ] = m_nFlexControllerIndex[ 1 ] = -1; + m_nFlexControllerIndexRaw[ 0 ] = m_nFlexControllerIndexRaw[ 1 ] = LocalFlexController_t(-1); + + // base track has range, combo is always 0..1 + m_flMin = 0.0f; + m_flMax = 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : src - +//----------------------------------------------------------------------------- +CFlexAnimationTrack::CFlexAnimationTrack( const CFlexAnimationTrack* src ) +{ + m_pControllerName = NULL; + SetFlexControllerName( src->m_pControllerName ? src->m_pControllerName : "" ); + + m_bActive = src->m_bActive; + m_bCombo = src->m_bCombo; + m_bServerSide = src->m_bServerSide; + + for ( int t = 0; t < 2; t++ ) + { + m_Samples[ t ].Purge(); + for ( int i = 0 ;i < src->m_Samples[ t ].Size(); i++ ) + { + CExpressionSample s = src->m_Samples[ t ][ i ]; + m_Samples[ t ].AddToTail( s ); + } + } + + for ( int side = 0; side < 2; side++ ) + { + m_nFlexControllerIndex[ side ] = src->m_nFlexControllerIndex[ side ]; + m_nFlexControllerIndexRaw[ side ] = src->m_nFlexControllerIndexRaw[ side ]; + } + + m_flMin = src->m_flMin; + m_flMax = src->m_flMax; + + m_EdgeInfo[ 0 ] = src->m_EdgeInfo[ 0 ]; + m_EdgeInfo[ 1 ] = src->m_EdgeInfo[ 1 ]; + + m_pEvent = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CFlexAnimationTrack::~CFlexAnimationTrack( void ) +{ + delete[] m_pControllerName; + + for ( int t = 0; t < 2; t++ ) + { + m_Samples[ t ].Purge(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *event - +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::SetEvent( CChoreoEvent *event ) +{ + m_pEvent = event; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::Clear( void ) +{ + for ( int t = 0; t < 2; t++ ) + { + m_Samples[ t ].RemoveAll(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : index - +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::RemoveSample( int index, int type /*=0*/ ) +{ + Assert( type == 0 || type == 1 ); + + m_Samples[ type ].Remove( index ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::SetFlexControllerName( const char *name ) +{ + delete[] m_pControllerName; + int len = Q_strlen( name ) + 1; + m_pControllerName = new char[ len ]; + Q_strncpy( m_pControllerName, name, len ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : char const +//----------------------------------------------------------------------------- +const char *CFlexAnimationTrack::GetFlexControllerName( void ) +{ + return m_pControllerName ? m_pControllerName : ""; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CFlexAnimationTrack::GetNumSamples( int type /*=0*/ ) +{ + Assert( type == 0 || type == 1 ); + + return m_Samples[ type ].Size(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : index - +// Output : CExpressionSample +//----------------------------------------------------------------------------- +CExpressionSample *CFlexAnimationTrack::GetSample( int index, int type /*=0*/ ) +{ + Assert( type == 0 || type == 1 ); + + if ( index < 0 || index >= GetNumSamples( type ) ) + return NULL; + return &m_Samples[ type ][ index ]; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CFlexAnimationTrack::IsTrackActive( void ) +{ + return m_bActive; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : active - +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::SetTrackActive( bool active ) +{ + m_bActive = active; +} + +void CFlexAnimationTrack::SetEdgeInfo( bool leftEdge, int curveType, float zero ) +{ + int idx = leftEdge ? 0 : 1; + m_EdgeInfo[ idx ].m_CurveType = curveType; + m_EdgeInfo[ idx ].m_flZeroPos = zero; +} + +void CFlexAnimationTrack::GetEdgeInfo( bool leftEdge, int& curveType, float& zero ) const +{ + int idx = leftEdge ? 0 : 1; + curveType = m_EdgeInfo[ idx ].m_CurveType; + zero = m_EdgeInfo[ idx ].m_flZeroPos; +} + +void CFlexAnimationTrack::SetEdgeActive( bool leftEdge, bool state ) +{ + int idx = leftEdge ? 0 : 1; + m_EdgeInfo[ idx ].m_bActive = state; +} + +bool CFlexAnimationTrack::IsEdgeActive( bool leftEdge ) const +{ + int idx = leftEdge ? 0 : 1; + return m_EdgeInfo[ idx ].m_bActive; +} + +int CFlexAnimationTrack::GetEdgeCurveType( bool leftEdge ) const +{ + if ( !IsEdgeActive( leftEdge ) ) + { + return CURVE_DEFAULT; + } + + int idx = leftEdge ? 0 : 1; + return m_EdgeInfo[ idx ].m_CurveType; +} + +float CFlexAnimationTrack::GetEdgeZeroValue( bool leftEdge ) const +{ + if ( !IsEdgeActive( leftEdge ) ) + { + return 0.0f; + } + + int idx = leftEdge ? 0 : 1; + return m_EdgeInfo[ idx ].m_flZeroPos; +} + +float CFlexAnimationTrack::GetDefaultEdgeZeroPos() const +{ + float zero = 0.0f; + if ( m_flMin != m_flMax ) + { + zero = ( 0.0f - m_flMin ) / ( m_flMax - m_flMin ); + } + return zero; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CFlexAnimationTrack::GetZeroValue( int type, bool leftSide ) +{ + // Stereo track is always clamped to 0.5 and doesn't care about l/r settings + if ( type == 1 ) + { + return 0.5f; + } + + if ( IsEdgeActive( leftSide ) ) + { + return GetEdgeZeroValue( leftSide ); + } + + return GetDefaultEdgeZeroPos(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : number - +// Output : CExpressionSample +//----------------------------------------------------------------------------- +CExpressionSample *CFlexAnimationTrack::GetBoundedSample( int number, bool& bClamped, int type /*=0*/ ) +{ + Assert( type == 0 || type == 1 ); + + if ( number < 0 ) + { + // Search for two samples which span time f + static CExpressionSample nullstart; + nullstart.time = 0.0f; + nullstart.value = GetZeroValue( type, true ); + if ( type == 0 ) + { + nullstart.SetCurveType( GetEdgeCurveType( true ) ); + } + else + { + nullstart.SetCurveType( CURVE_DEFAULT ); + } + bClamped = true; + return &nullstart; + } + else if ( number >= GetNumSamples( type ) ) + { + static CExpressionSample nullend; + nullend.time = m_pEvent->GetDuration(); + nullend.value = GetZeroValue( type, false ); + if ( type == 0 ) + { + nullend.SetCurveType( GetEdgeCurveType( false ) ); + } + else + { + nullend.SetCurveType( CURVE_DEFAULT ); + } + bClamped = true; + return &nullend; + } + + bClamped = false; + return GetSample( number, type ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : time - +// type - +// Output : float +//----------------------------------------------------------------------------- +float CFlexAnimationTrack::GetIntensityInternal( float time, int type ) +{ + Assert( type == 0 || type == 1 ); + + float retval = 0.0f; + + // find samples that span the time + if ( !m_pEvent || !m_pEvent->HasEndTime() || time < m_pEvent->GetStartTime() ) + { + retval = GetZeroValue( type, true );; + } + else if ( time > m_pEvent->GetEndTime() ) + { + retval = GetZeroValue( type, false );; + } + else + { + float elapsed = time - m_pEvent->GetStartTime(); + retval = GetFracIntensity( elapsed, type ); + } + + // scale + if (type == 0 && m_flMin != m_flMax) + { + retval = retval * (m_flMax - m_flMin) + m_flMin; + } + return retval; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : time - +// type - +// Output : float +//----------------------------------------------------------------------------- +float CFlexAnimationTrack::GetFracIntensity( float time, int type ) +{ + float zeroValueLeft = GetZeroValue( type, true ); + + Assert( type == 0 || type == 1 ); + + // find samples that span the time + if ( !m_pEvent || !m_pEvent->HasEndTime() ) + return zeroValueLeft; + + int rampCount = GetNumSamples( type ); + if ( rampCount < 1 ) + { + return zeroValueLeft; + } + + CExpressionSample *esStart = NULL; + CExpressionSample *esEnd = NULL; + + // do binary search for sample in time period + int j = MAX( rampCount / 2, 1 ); + int i = j; + while ( i > -2 && i < rampCount + 1 ) + { + bool dummy; + esStart = GetBoundedSample( i, dummy, type ); + esEnd = GetBoundedSample( i + 1, dummy, type ); + + j = MAX( j / 2, 1 ); + if ( time < esStart->time) + { + i -= j; + } + else if ( time > esEnd->time) + { + i += j; + } + else + { + if ( time == esEnd->time ) + { + ++i; + esStart = GetBoundedSample( i, dummy, type ); + esEnd = GetBoundedSample( i + 1, dummy, type ); + } + break; + } + } + + if (!esStart) + { + return zeroValueLeft; + } + + int prev = i - 1; + int next = i + 2; + + prev = MAX( -1, prev ); + next = MIN( next, rampCount ); + + bool bclamp[ 2 ]; + CExpressionSample *esPre = GetBoundedSample( prev, bclamp[ 0 ], type ); + CExpressionSample *esNext = GetBoundedSample( next, bclamp[ 1 ], type ); + + float dt = esEnd->time - esStart->time; + + Vector vPre( esPre->time, esPre->value, 0 ); + Vector vStart( esStart->time, esStart->value, 0 ); + Vector vEnd( esEnd->time, esEnd->value, 0 ); + Vector vNext( esNext->time, esNext->value, 0 ); + + float f2 = 0.0f; + if ( dt > 0.0f ) + { + f2 = ( time - esStart->time ) / ( dt ); + } + f2 = clamp( f2, 0.0f, 1.0f ); + + Vector vOut; + int dummy; + int earlypart, laterpart; + + // Not holding out value of previous curve... + Interpolator_CurveInterpolatorsForType( esStart->GetCurveType(), dummy, earlypart ); + Interpolator_CurveInterpolatorsForType( esEnd->GetCurveType(), laterpart, dummy ); + + if ( earlypart == INTERPOLATE_HOLD ) + { + // Hold "out" of previous sample (can cause a discontinuity) + VectorLerp( vStart, vEnd, f2, vOut ); + vOut.y = vStart.y; + } + else if ( laterpart == INTERPOLATE_HOLD ) + { + // Hold "out" of previous sample (can cause a discontinuity) + VectorLerp( vStart, vEnd, f2, vOut ); + vOut.y = vEnd.y; + } + else + { + bool sameCurveType = earlypart == laterpart ? true : false; + if ( sameCurveType ) + { + Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut ); + } + else // curves differ, sigh + { + Vector vOut1, vOut2; + + Interpolator_CurveInterpolate( earlypart, vPre, vStart, vEnd, vNext, f2, vOut1 ); + Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut2 ); + + VectorLerp( vOut1, vOut2, f2, vOut ); + } + } + + float retval = clamp( vOut.y, 0.0f, 1.0f ); + return retval; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : time - +// Output : float +//----------------------------------------------------------------------------- +float CFlexAnimationTrack::GetSampleIntensity( float time ) +{ + return GetIntensityInternal( time, 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : time - +// Output : float +//----------------------------------------------------------------------------- +float CFlexAnimationTrack::GetBalanceIntensity( float time ) +{ + if ( IsComboType() ) + { + return GetIntensityInternal( time, 1 ); + } + + return 1.0f; +} + +// For a given time, computes 0->1 intensity value for the slider +//----------------------------------------------------------------------------- +// Purpose: +// Input : time - +// Output : float +//----------------------------------------------------------------------------- +float CFlexAnimationTrack::GetIntensity( float time, int side ) +{ + float mag = GetSampleIntensity( time ); + + float scale = 1.0f; + + if ( IsComboType() ) + { + float balance = GetBalanceIntensity( time ); + + // Asking for left but balance is to right, then fall off as we go + // further right + if ( side == 0 && balance > 0.5f ) + { + scale = (1.0f - balance ) / 0.5f; + } + // Asking for right, but balance is left, fall off as we go left. + else if ( side == 1 && balance < 0.5f ) + { + scale = ( balance / 0.5f ); + } + } + + return mag * scale; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : time - +// value - +//----------------------------------------------------------------------------- +CExpressionSample *CFlexAnimationTrack::AddSample( float time, float value, int type /*=0*/ ) +{ + Assert( type == 0 || type == 1 ); + + CExpressionSample sample; + sample.time = time; + sample.value = value; + sample.selected = false; + + int idx = m_Samples[ type ].AddToTail( sample ); + + // Resort( type ); + return &m_Samples[ type ][ idx ]; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::Resort( int type /*=0*/ ) +{ + Assert( type == 0 || type == 1 ); + + for ( int i = 0; i < m_Samples[ type ].Size(); i++ ) + { + for ( int j = i + 1; j < m_Samples[ type ].Size(); j++ ) + { + CExpressionSample src = m_Samples[ type ][ i ]; + CExpressionSample dest = m_Samples[ type ][ j ]; + + if ( src.time > dest.time ) + { + m_Samples[ type ][ i ] = dest; + m_Samples[ type ][ j ] = src; + } + } + } + + // Make sure nothing is out of range + RemoveOutOfRangeSamples( 0 ); + RemoveOutOfRangeSamples( 1 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoEvent +//----------------------------------------------------------------------------- +CChoreoEvent *CFlexAnimationTrack::GetEvent( void ) +{ + return m_pEvent; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : side - +// Output : int +//----------------------------------------------------------------------------- +int CFlexAnimationTrack::GetFlexControllerIndex( int side /*= 0*/ ) +{ + Assert( side == 0 || side == 1 ); + + if ( IsComboType() ) + { + return m_nFlexControllerIndex[ side ]; + } + + return m_nFlexControllerIndex[ 0 ]; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : side - +// Output : int +//----------------------------------------------------------------------------- +LocalFlexController_t CFlexAnimationTrack::GetRawFlexControllerIndex( int side /*= 0*/ ) +{ + Assert( side == 0 || side == 1 ); + + if ( IsComboType() ) + { + return m_nFlexControllerIndexRaw[ side ]; + } + + return m_nFlexControllerIndexRaw[ 0 ]; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : index - +// side - +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::SetFlexControllerIndex( LocalFlexController_t raw, int index, int side /*= 0*/ ) +{ + Assert( side == 0 || side == 1 ); + + m_nFlexControllerIndex[ side ] = index; + // Model specific + m_nFlexControllerIndexRaw[ side ] = raw; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : combo - +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::SetComboType( bool combo ) +{ + m_bCombo = combo; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CFlexAnimationTrack::IsComboType( void ) +{ + return m_bCombo; +} + +//----------------------------------------------------------------------------- +// Purpose: True if this should be simulated on the server side always +// Input : state - +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::SetServerSide( bool state ) +{ + m_bServerSide = state; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CFlexAnimationTrack::IsServerSide() const +{ + return m_bServerSide; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::SetMin( float value ) +{ + m_flMin = value; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::SetMax( float value ) +{ + m_flMax = value; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CFlexAnimationTrack::GetMin( int type ) +{ + if (type == 0) + return m_flMin; + else + return 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CFlexAnimationTrack::GetMax( int type ) +{ + if (type == 0) + return m_flMax; + else + return 1.0f; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CFlexAnimationTrack::IsInverted( void ) +{ + if (m_bInverted) + return true; + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::SetInverted( bool isInverted ) +{ + m_bInverted = isInverted; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +void CFlexAnimationTrack::RemoveOutOfRangeSamples( int type ) +{ + Assert( m_pEvent ); + if ( !m_pEvent ) + return; + + Assert( m_pEvent->HasEndTime() ); + float duration = m_pEvent->GetDuration(); + + int c = m_Samples[ type ].Size(); + for ( int i = c-1; i >= 0; i-- ) + { + CExpressionSample src = m_Samples[ type ][ i ]; + if ( src.time < 0 || + src.time > duration ) + { + m_Samples[ type ].Remove( i ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CChoreoEvent::CChoreoEvent( CChoreoScene *scene ) +{ + Init( scene ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// *name - +//----------------------------------------------------------------------------- +CChoreoEvent::CChoreoEvent( CChoreoScene *scene, EVENTTYPE type, const char *name ) +{ + Init( scene ); + SetType( type ); + SetName( name ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// *name - +// *param - +//----------------------------------------------------------------------------- +CChoreoEvent::CChoreoEvent( CChoreoScene *scene, EVENTTYPE type, const char *name, const char *param ) +{ + Init( scene ); + SetType( type ); + SetName( name ); + SetParameters( param ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CChoreoEvent::~CChoreoEvent( void ) +{ + RemoveAllTracks(); + ClearEventDependencies(); + delete m_pSubScene; +} + +//----------------------------------------------------------------------------- +// Purpose: Assignment +// Input : src - +// Output : CChoreoEvent& +//----------------------------------------------------------------------------- +CChoreoEvent& CChoreoEvent::operator=( const CChoreoEvent& src ) +{ + MEM_ALLOC_CREDIT(); + + // Copy global id when copying entity + m_nGlobalID = src.m_nGlobalID; + + m_pActor = NULL; + m_pChannel = NULL; + + m_nDefaultCurveType = src.m_nDefaultCurveType; + m_fType = src.m_fType; + m_Name = src.m_Name; + m_Parameters = src.m_Parameters; + m_Parameters2= src.m_Parameters2; + m_Parameters3= src.m_Parameters3; + m_flStartTime = src.m_flStartTime; + m_flEndTime = src.m_flEndTime; + + m_bFixedLength = src.m_bFixedLength; + m_flGestureSequenceDuration = src.m_flGestureSequenceDuration; + m_bResumeCondition = src.m_bResumeCondition; + m_bLockBodyFacing = src.m_bLockBodyFacing; + m_flDistanceToTarget = src.m_flDistanceToTarget; + m_bForceShortMovement = src.m_bForceShortMovement; + m_bSyncToFollowingGesture = src.m_bSyncToFollowingGesture; + m_bPlayOverScript = src.m_bPlayOverScript; + m_bUsesTag = src.m_bUsesTag; + m_TagName = src.m_TagName; + m_TagWavName = src.m_TagWavName; + + ClearAllRelativeTags(); + ClearAllTimingTags(); + int t; + for ( t = 0; t < NUM_ABS_TAG_TYPES; t++ ) + { + ClearAllAbsoluteTags( (AbsTagType)t ); + } + + int i; + for ( i = 0; i < src.m_RelativeTags.Size(); i++ ) + { + CEventRelativeTag newtag( src.m_RelativeTags[ i ] ); + newtag.SetOwner( this ); + m_RelativeTags.AddToTail( newtag ); + } + + for ( i = 0; i < src.m_TimingTags.Size(); i++ ) + { + CFlexTimingTag newtag( src.m_TimingTags[ i ] ); + newtag.SetOwner( this ); + m_TimingTags.AddToTail( newtag ); + } + for ( t = 0; t < NUM_ABS_TAG_TYPES; t++ ) + { + for ( i = 0; i < src.m_AbsoluteTags[ t ].Size(); i++ ) + { + CEventAbsoluteTag newtag( src.m_AbsoluteTags[ t ][ i ] ); + newtag.SetOwner( this ); + m_AbsoluteTags[ t ].AddToTail( newtag ); + } + } + + RemoveAllTracks(); + + for ( i = 0 ; i < src.m_FlexAnimationTracks.Size(); i++ ) + { + CFlexAnimationTrack *newtrack = new CFlexAnimationTrack( src.m_FlexAnimationTracks[ i ] ); + newtrack->SetEvent( this ); + m_FlexAnimationTracks.AddToTail( newtrack ); + } + + m_bTrackLookupSet = src.m_bTrackLookupSet; + + // FIXME: Use a safe handle? + //m_pSubScene = src.m_pSubScene; + + m_bProcessing = src.m_bProcessing; + m_pMixer = src.m_pMixer; + + m_pScene = src.m_pScene; + + m_nPitch = src.m_nPitch; + m_nYaw = src.m_nYaw; + + m_nNumLoops = src.m_nNumLoops; + m_nLoopsRemaining = src.m_nLoopsRemaining; + + // Copy ramp over + m_Ramp = src.m_Ramp; + + m_ccType = src.m_ccType; + m_CCToken = src.m_CCToken; + m_bUsingCombinedSoundFile = src.m_bUsingCombinedSoundFile; + m_uRequiredCombinedChecksum = src.m_uRequiredCombinedChecksum; + m_nNumSlaves = src.m_nNumSlaves; + m_flLastSlaveEndTime = src.m_flLastSlaveEndTime; + m_bCCTokenValid = src.m_bCCTokenValid; + m_bCombinedUsingGenderToken = src.m_bCombinedUsingGenderToken; + + m_bSuppressCaptionAttenuation = src.m_bSuppressCaptionAttenuation; + + m_bActive = src.m_bActive; + + return *this; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CChoreoEvent::Init( CChoreoScene *scene ) +{ + m_nGlobalID = s_nGlobalID++; + m_nDefaultCurveType = CURVE_CATMULL_ROM_TO_CATMULL_ROM; + m_fType = UNSPECIFIED; + m_Name.Set(""); + m_Parameters.Set(""); + m_Parameters2.Set(""); + m_Parameters3.Set(""); + + m_flStartTime = 0.0f; + m_flEndTime = -1.0f; + + m_pActor = NULL; + m_pChannel = NULL; + m_pScene = scene; + + m_bFixedLength = false; + m_bResumeCondition = false; + SetUsingRelativeTag( false, 0, 0 ); + + m_bTrackLookupSet = false; + + m_bLockBodyFacing = false; + m_flDistanceToTarget = 0.0f; + m_bForceShortMovement = false; + m_bSyncToFollowingGesture = false; + m_bPlayOverScript = false; + + m_pSubScene = NULL; + m_bProcessing = false; + m_pMixer = NULL; + m_flGestureSequenceDuration = 0.0f; + + m_nPitch = m_nYaw = 0; + + m_nNumLoops = -1; + m_nLoopsRemaining = 0; + + // Close captioning/localization support + m_CCToken.Set(""); + m_ccType = CC_MASTER; + m_bUsingCombinedSoundFile = false; + m_uRequiredCombinedChecksum = 0; + m_nNumSlaves = 0; + m_flLastSlaveEndTime = 0.0f; + m_bCCTokenValid = false; + m_bCombinedUsingGenderToken = false; + m_bSuppressCaptionAttenuation = false; + m_bActive = true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +CChoreoEvent::EVENTTYPE CChoreoEvent::GetType( void ) +{ + return (EVENTTYPE)m_fType; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetType( EVENTTYPE type ) +{ + m_fType = type; + + if ( m_fType == SPEAK || + m_fType == SUBSCENE ) + { + m_bFixedLength = true; + } + else + { + m_bFixedLength = false; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetName( const char *name ) +{ + m_Name = name; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *CChoreoEvent::GetName( void ) +{ + return m_Name.Get(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *param - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetParameters( const char *param ) +{ + m_Parameters = param; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *CChoreoEvent::GetParameters( void ) +{ + return m_Parameters.Get(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *param - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetParameters2( const char *param ) +{ + int iLength = Q_strlen( param ); + m_Parameters2 = param; + + // HACK: Remove trailing " " until faceposer is fixed + if ( iLength > 0 ) + { + if ( param[iLength-1] == ' ' ) + { + char tmp[1024]; + Q_strncpy( tmp, param, sizeof(tmp) ); + tmp[iLength-1] = 0; + m_Parameters2.Set(tmp); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *CChoreoEvent::GetParameters2( void ) +{ + return m_Parameters2.Get(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *param - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetParameters3( const char *param ) +{ + int iLength = Q_strlen( param ); + m_Parameters3 = param; + + // HACK: Remove trailing " " until faceposer is fixed + if ( iLength > 0 ) + { + if ( param[iLength-1] == ' ' ) + { + char tmp[1024]; + Q_strncpy( tmp, param, sizeof(tmp) ); + tmp[iLength-1] = 0; + m_Parameters3.Set(tmp); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *CChoreoEvent::GetParameters3( void ) +{ + return m_Parameters3.Get(); +} + +//----------------------------------------------------------------------------- +// Purpose: debugging description +// Output : const char +//----------------------------------------------------------------------------- +const char *CChoreoEvent::GetDescription( void ) +{ + static char description[ 256 ]; + + description[ 0 ] = 0; + + if ( !GetActor() ) + { + Q_snprintf( description,sizeof(description), "global %s", m_Name.Get() ); + } + else + { + Assert( m_pChannel ); + Q_snprintf( description,sizeof(description), "%s : %s : %s -- %s \"%s\"", m_pActor->GetName(), m_pChannel->GetName(), GetName(), NameForType( GetType() ), GetParameters() ); + if ( GetType() == EXPRESSION ) + { + char sz[ 256 ]; + + Q_snprintf( sz,sizeof(sz), " \"%s\"", GetParameters2() ); + Q_strncat( description, sz, sizeof(description), COPY_ALL_CHARACTERS ); + } + } + + return description; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : starttime - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetStartTime( float starttime ) +{ + m_flStartTime = starttime; + if ( m_flEndTime != -1.0f ) + { + if ( m_flEndTime < m_flStartTime ) + { + m_flEndTime = m_flStartTime; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CChoreoEvent::GetStartTime( ) +{ + return m_flStartTime; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : endtime - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetEndTime( float endtime ) +{ + bool changed = m_flEndTime != endtime; + + m_flEndTime = endtime; + + if ( endtime != -1.0f ) + { + if ( m_flEndTime < m_flStartTime ) + { + m_flEndTime = m_flStartTime; + } + + if ( changed ) + { + OnEndTimeChanged(); + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CChoreoEvent::GetEndTime( ) +{ + return m_flEndTime; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CChoreoEvent::HasEndTime( void ) +{ + return m_flEndTime != -1.0f ? true : false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CChoreoEvent::GetCompletion( float time ) +{ + float t = (time - GetStartTime()) / (GetEndTime() - GetStartTime()); + + if (t < 0.0f) + return 0.0f; + else if (t > 1.0f) + return 1.0f; + + return t; +} + +// ICurveDataAccessor method +bool CChoreoEvent::CurveHasEndTime() +{ + return HasEndTime(); +} + +//----------------------------------------------------------------------------- +// Default curve type +//----------------------------------------------------------------------------- +void CChoreoEvent::SetDefaultCurveType( int nCurveType ) +{ + m_nDefaultCurveType = nCurveType; +} + +int CChoreoEvent::GetDefaultCurveType() +{ + return m_nDefaultCurveType; +} + +float CCurveData::GetIntensity( ICurveDataAccessor *data, float time ) +{ + float zeroValue = 0.0f; + + // find samples that span the time + if ( !data->CurveHasEndTime() ) + { + return zeroValue; + } + + int rampCount = GetCount(); + if ( rampCount < 1 ) + { + // Full intensity + return 1.0f; + } + + CExpressionSample *esStart = NULL; + CExpressionSample *esEnd = NULL; + + // do binary search for sample in time period + int j = MAX( rampCount / 2, 1 ); + int i = j; + while ( i > -2 && i < rampCount + 1 ) + { + bool dummy; + esStart = GetBoundedSample( data, i, dummy ); + esEnd = GetBoundedSample( data, i + 1, dummy ); + + j = MAX( j / 2, 1 ); + if ( time < esStart->time) + { + i -= j; + } + else if ( time > esEnd->time) + { + i += j; + } + else + { + break; + } + } + + if (!esStart) + { + return 1.0f; + } + + int prev = i - 1; + int next = i + 2; + + prev = MAX( -1, prev ); + next = MIN( next, rampCount ); + + bool bclamp[ 2 ]; + CExpressionSample *esPre = GetBoundedSample( data, prev, bclamp[ 0 ] ); + CExpressionSample *esNext = GetBoundedSample( data, next, bclamp[ 1 ] ); + + float dt = esEnd->time - esStart->time; + + Vector vPre( esPre->time, esPre->value, 0 ); + Vector vStart( esStart->time, esStart->value, 0 ); + Vector vEnd( esEnd->time, esEnd->value, 0 ); + Vector vNext( esNext->time, esNext->value, 0 ); + + if ( bclamp[ 0 ] ) + { + vPre.x = vStart.x; + } + + if ( bclamp[ 1 ] ) + { + vNext.x = vEnd.x; + } + + float f2 = 0.0f; + if ( dt > 0.0f ) + { + f2 = ( time - esStart->time ) / ( dt ); + } + f2 = clamp( f2, 0.0f, 1.0f ); + + Vector vOut; + int dummy; + int earlypart, laterpart; + + int startCurve = esStart->GetCurveType(); + int endCurve = esEnd->GetCurveType(); + + if ( startCurve == CURVE_DEFAULT ) + { + startCurve = data->GetDefaultCurveType(); + } + if ( endCurve == CURVE_DEFAULT ) + { + endCurve = data->GetDefaultCurveType(); + } + + // Not holding out value of previous curve... + Interpolator_CurveInterpolatorsForType( startCurve, dummy, earlypart ); + Interpolator_CurveInterpolatorsForType( endCurve, laterpart, dummy ); + + if ( earlypart == INTERPOLATE_HOLD ) + { + // Hold "out" of previous sample (can cause a discontinuity) + VectorLerp( vStart, vEnd, f2, vOut ); + vOut.y = vStart.y; + } + else if ( laterpart == INTERPOLATE_HOLD ) + { + // Hold "out" of previous sample (can cause a discontinuity) + VectorLerp( vStart, vEnd, f2, vOut ); + vOut.y = vEnd.y; + } + else + { + bool sameCurveType = earlypart == laterpart ? true : false; + if ( sameCurveType ) + { + Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut ); + } + else // curves differ, sigh + { + Vector vOut1, vOut2; + + Interpolator_CurveInterpolate( earlypart, vPre, vStart, vEnd, vNext, f2, vOut1 ); + Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut2 ); + + VectorLerp( vOut1, vOut2, f2, vOut ); + } + } + + float retval = clamp( vOut.y, 0.0f, 1.0f ); + return retval; +} + +//----------------------------------------------------------------------------- +// Purpose: Get intensity for event, bounded by scene global intensity +// Output : float +//----------------------------------------------------------------------------- +float CChoreoEvent::GetIntensity( float scenetime ) +{ + float global_intensity = 1.0f; + if ( m_pScene ) + { + global_intensity = m_pScene->GetSceneRampIntensity( scenetime ); + } + else + { + Assert( 0 ); + } + + float event_intensity = _GetIntensity( scenetime ); + + return global_intensity * event_intensity; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CChoreoEvent::_GetIntensity( float scenetime ) +{ + // Convert to event local time + float time = scenetime - GetStartTime(); + return m_Ramp.GetIntensity( this, time ); +} + + +float CChoreoEvent::GetIntensityArea( float scenetime ) +{ + // Convert to event local time + float time = scenetime - GetStartTime(); + return m_Ramp.GetIntensityArea( this, time ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CCurveData::GetIntensityArea( ICurveDataAccessor *data, float time ) +{ + float zeroValue = 0.0f; + + // find samples that span the time + if ( !data->CurveHasEndTime() ) + { + return zeroValue; + } + + int rampCount = GetCount(); + if ( rampCount < 1 ) + { + // Full intensity + return 1.0f; + } + + CExpressionSample *esStart = NULL; + CExpressionSample *esEnd = NULL; + + // do binary search for sample in time period + int j = MAX( rampCount / 2, 1 ); + int i = j; + while ( i > -2 && i < rampCount + 1 ) + { + bool dummy; + esStart = GetBoundedSample( data, i, dummy ); + esEnd = GetBoundedSample( data, i + 1, dummy ); + + j = MAX( j / 2, 1 ); + if ( time < esStart->time) + { + i -= j; + } + else if ( time > esEnd->time) + { + i += j; + } + else + { + break; + } + } + + UpdateIntensityArea( data ); + + float flTotal = 0.0f; + flTotal = m_RampAccumulator[i+1]; + + int prev = i - 1; + int next = i + 2; + + prev = MAX( -1, prev ); + next = MIN( next, rampCount ); + + bool bclamp[ 2 ]; + CExpressionSample *esPre = GetBoundedSample( data, prev, bclamp[ 0 ] ); + CExpressionSample *esNext = GetBoundedSample( data, next, bclamp[ 1 ] ); + + float dt = esEnd->time - esStart->time; + + Vector vPre( esPre->time, esPre->value, 0 ); + Vector vStart( esStart->time, esStart->value, 0 ); + Vector vEnd( esEnd->time, esEnd->value, 0 ); + Vector vNext( esNext->time, esNext->value, 0 ); + + if ( bclamp[ 0 ] ) + { + vPre.x = vStart.x; + } + + if ( bclamp[ 1 ] ) + { + vNext.x = vEnd.x; + } + + float f2 = 0.0f; + if ( dt > 0.0f ) + { + f2 = ( time - esStart->time ) / ( dt ); + } + f2 = clamp( f2, 0.0f, 1.0f ); + + Vector vOut; + int dummy; + int earlypart, laterpart; + + int startCurve = esStart->GetCurveType(); + int endCurve = esEnd->GetCurveType(); + + if ( startCurve == CURVE_DEFAULT ) + { + startCurve = data->GetDefaultCurveType(); + } + if ( endCurve == CURVE_DEFAULT ) + { + endCurve = data->GetDefaultCurveType(); + } + + // Not holding out value of previous curve... + Interpolator_CurveInterpolatorsForType( startCurve, dummy, earlypart ); + Interpolator_CurveInterpolatorsForType( endCurve, laterpart, dummy ); + + // FIXME: needs other curve types + Catmull_Rom_Spline_Integral_Normalize( + vPre, + vStart, + vEnd, + vNext, + f2, + vOut ); + + // Con_Printf( "Accum %f : Partial %f\n", flTotal, vOut.y * (vEnd.x - vStart.x) * f2 ); + flTotal = flTotal + clamp( vOut.y, 0.0f, 1.0f ) * (vEnd.x - vStart.x); + return flTotal; +} + + +void CCurveData::UpdateIntensityArea( ICurveDataAccessor *data ) +{ + int rampCount = GetCount();; + if ( rampCount < 1 ) + { + return; + } + + if (m_RampAccumulator.Count() == rampCount + 2) + { + return; + } + + m_RampAccumulator.SetCount( rampCount + 2 ); + + int i = -1; + + bool dummy; + CExpressionSample *esPre = GetBoundedSample( data, i - 1, dummy ); + CExpressionSample *esStart = GetBoundedSample( data, i, dummy ); + CExpressionSample *esEnd = GetBoundedSample( data, MIN( i + 1, rampCount ), dummy ); + + Vector vPre( esPre->time, esPre->value, 0 ); + Vector vStart( esStart->time, esStart->value, 0 ); + Vector vEnd( esEnd->time, esEnd->value, 0 ); + + Vector vOut; + for (i = -1; i < rampCount; i++) + { + CExpressionSample *esNext = GetBoundedSample( data, MIN( i + 2, rampCount ), dummy ); + Vector vNext( esNext->time, esNext->value, 0 ); + + Catmull_Rom_Spline_Integral_Normalize( + vPre, + vStart, + vEnd, + vNext, + 1.0f, + vOut ); + + m_RampAccumulator[i+1] = clamp( vOut.y, 0.0f, 1.0f ) * (vEnd.x - vStart.x); + + vPre = vStart; + vStart = vEnd; + vEnd = vNext; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dt - +//----------------------------------------------------------------------------- +void CChoreoEvent::OffsetStartTime( float dt ) +{ + SetStartTime( GetStartTime() + dt ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dt - +//----------------------------------------------------------------------------- +void CChoreoEvent::OffsetEndTime( float dt ) +{ + if ( HasEndTime() ) + { + SetEndTime( GetEndTime() + dt ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dt - +//----------------------------------------------------------------------------- +void CChoreoEvent::OffsetTime( float dt ) +{ + if ( HasEndTime() ) + { + m_flEndTime += dt; + } + m_flStartTime += dt; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *actor - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetActor( CChoreoActor *actor ) +{ + m_pActor = actor; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoActor +//----------------------------------------------------------------------------- +CChoreoActor *CChoreoEvent::GetActor( void ) +{ + return m_pActor; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *channel - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetChannel( CChoreoChannel *channel ) +{ + m_pChannel = channel; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoChannel +//----------------------------------------------------------------------------- +CChoreoChannel *CChoreoEvent::GetChannel( void ) +{ + return m_pChannel; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *scene - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetSubScene( CChoreoScene *scene ) +{ + m_pSubScene = scene; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoScene +//----------------------------------------------------------------------------- +CChoreoScene *CChoreoEvent::GetSubScene( void ) +{ + return m_pSubScene; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +struct EventNameMap_t +{ + CChoreoEvent::EVENTTYPE type; + char const *name; +}; + +static EventNameMap_t g_NameMap[] = +{ + { CChoreoEvent::UNSPECIFIED, "unspecified" }, // error condition!!! + { CChoreoEvent::SECTION, "section" }, + { CChoreoEvent::EXPRESSION, "expression" }, + { CChoreoEvent::LOOKAT, "lookat" }, + { CChoreoEvent::MOVETO, "moveto" }, + { CChoreoEvent::SPEAK, "speak" }, + { CChoreoEvent::GESTURE, "gesture" }, + { CChoreoEvent::SEQUENCE, "sequence" }, + { CChoreoEvent::FACE, "face" }, + { CChoreoEvent::FIRETRIGGER, "firetrigger" }, + { CChoreoEvent::FLEXANIMATION, "flexanimation" }, + { CChoreoEvent::SUBSCENE, "subscene" }, + { CChoreoEvent::LOOP, "loop" }, + { CChoreoEvent::INTERRUPT, "interrupt" }, + { CChoreoEvent::STOPPOINT, "stoppoint" }, + { CChoreoEvent::PERMIT_RESPONSES, "permitresponses" }, + { CChoreoEvent::GENERIC, "generic" }, +}; + +//----------------------------------------------------------------------------- +// Purpose: A simple class to verify the names data above at runtime +//----------------------------------------------------------------------------- +class CCheckEventNames +{ +public: + CCheckEventNames() + { + if ( ARRAYSIZE( g_NameMap ) != CChoreoEvent::NUM_TYPES ) + { + Error( "g_NameMap contains %i entries, CChoreoEvent::NUM_TYPES == %i!", + ARRAYSIZE( g_NameMap ), CChoreoEvent::NUM_TYPES ); + } + for ( int i = 0; i < CChoreoEvent::NUM_TYPES; ++i ) + { + if ( !g_NameMap[ i ].name ) + { + Error( "g_NameMap: Event type at %i has NULL name string!", i ); + } + + if ( (CChoreoEvent::EVENTTYPE)(i) == g_NameMap[ i ].type ) + continue; + + Error( "g_NameMap: Event type at %i has wrong value (%i)!", + i, (int)g_NameMap[ i ].type ); + } + } +}; +static CCheckEventNames g_CheckNamesSingleton; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +// Output : int +//----------------------------------------------------------------------------- +CChoreoEvent::EVENTTYPE CChoreoEvent::TypeForName( const char *name ) +{ + for ( int i = 0; i < NUM_TYPES; ++i ) + { + EventNameMap_t *slot = &g_NameMap[ i ]; + if ( !Q_stricmp( name, slot->name ) ) + return slot->type; + } + + Assert( !"CChoreoEvent::TypeForName failed!!!" ); + return UNSPECIFIED; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// Output : const char +//----------------------------------------------------------------------------- +const char *CChoreoEvent::NameForType( EVENTTYPE type ) +{ + int i = (int)type; + if ( i < 0 || i >= NUM_TYPES ) + { + Assert( "!CChoreoEvent::NameForType: bogus type!" ); + // returns "unspecified!!!"; + return g_NameMap[ 0 ].name; + } + + return g_NameMap[ i ].name; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +struct CCNameMap_t +{ + CChoreoEvent::CLOSECAPTION type; + char const *name; +}; + +static CCNameMap_t g_CCNameMap[] = +{ + { CChoreoEvent::CC_MASTER, "cc_master" }, // error condition!!! + { CChoreoEvent::CC_SLAVE, "cc_slave" }, + { CChoreoEvent::CC_DISABLED, "cc_disabled" }, +}; + +//----------------------------------------------------------------------------- +// Purpose: A simple class to verify the names data above at runtime +//----------------------------------------------------------------------------- +class CCheckCCNames +{ +public: + CCheckCCNames() + { + if ( ARRAYSIZE( g_CCNameMap ) != CChoreoEvent::NUM_CC_TYPES ) + { + Error( "g_CCNameMap contains %i entries, CChoreoEvent::NUM_CC_TYPES == %i!", + ARRAYSIZE( g_CCNameMap ), CChoreoEvent::NUM_CC_TYPES ); + } + for ( int i = 0; i < CChoreoEvent::NUM_CC_TYPES; ++i ) + { + if ( !g_CCNameMap[ i ].name ) + { + Error( "g_NameMap: CC type at %i has NULL name string!", i ); + } + + if ( (CChoreoEvent::CLOSECAPTION)(i) == g_CCNameMap[ i ].type ) + continue; + + Error( "g_CCNameMap: Event type at %i has wrong value (%i)!", + i, (int)g_CCNameMap[ i ].type ); + } + } +}; +static CCheckCCNames g_CheckCCNamesSingleton; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +// Output : CLOSECAPTION +//----------------------------------------------------------------------------- +CChoreoEvent::CLOSECAPTION CChoreoEvent::CCTypeForName( const char *name ) +{ + for ( int i = 0; i < NUM_CC_TYPES; ++i ) + { + CCNameMap_t *slot = &g_CCNameMap[ i ]; + if ( !Q_stricmp( name, slot->name ) ) + return slot->type; + } + + Assert( !"CChoreoEvent::TypeForName failed!!!" ); + return CC_MASTER; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// Output : const char +//----------------------------------------------------------------------------- +const char *CChoreoEvent::NameForCCType( CLOSECAPTION type ) +{ + int i = (int)type; + if ( i < 0 || i >= NUM_CC_TYPES ) + { + Assert( "!CChoreoEvent::NameForType: bogus type!" ); + // returns "unspecified!!!"; + return g_CCNameMap[ 0 ].name; + } + + return g_CCNameMap[ i ].name; +} + +//----------------------------------------------------------------------------- +// Purpose: Is the event something that can be sized ( a wave file, e.g. ) +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CChoreoEvent::IsFixedLength( void ) +{ + return m_bFixedLength; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : isfixedlength - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetFixedLength( bool isfixedlength ) +{ + m_bFixedLength = isfixedlength; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : resumecondition - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetResumeCondition( bool resumecondition ) +{ + m_bResumeCondition = resumecondition; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CChoreoEvent::IsResumeCondition( void ) +{ + return m_bResumeCondition; +} + + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : lockbodyfacing - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetLockBodyFacing( bool lockbodyfacing ) +{ + m_bLockBodyFacing = lockbodyfacing; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CChoreoEvent::IsLockBodyFacing( void ) +{ + return m_bLockBodyFacing; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : distancetotarget - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetDistanceToTarget( float distancetotarget ) +{ + m_flDistanceToTarget = distancetotarget; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns ideal distance to target +//----------------------------------------------------------------------------- +float CChoreoEvent::GetDistanceToTarget( void ) +{ + return m_flDistanceToTarget; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : set if small (sub-1/2 bbox) movements are forced +//----------------------------------------------------------------------------- + +void CChoreoEvent::SetForceShortMovement( bool bForceShortMovement ) +{ + m_bForceShortMovement = bForceShortMovement; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : get if small (sub-1/2 bbox) movements are forced +//----------------------------------------------------------------------------- + +bool CChoreoEvent::GetForceShortMovement( void ) +{ + return m_bForceShortMovement; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : set if the gesture should sync its exit tag with the following gestures entry tag +//----------------------------------------------------------------------------- + +void CChoreoEvent::SetSyncToFollowingGesture( bool bSyncToFollowingGesture ) +{ + m_bSyncToFollowingGesture = bSyncToFollowingGesture; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : get if the gesture should sync its exit tag with the following gestures entry tag +//----------------------------------------------------------------------------- + +bool CChoreoEvent::GetSyncToFollowingGesture( void ) +{ + return m_bSyncToFollowingGesture; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : set if the sequence should player overtop of an underlying SS +//----------------------------------------------------------------------------- + +void CChoreoEvent::SetPlayOverScript( bool bPlayOverScript ) +{ + m_bPlayOverScript = bPlayOverScript; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : get if the sequence should player overtop of an underlying SS +//----------------------------------------------------------------------------- + +bool CChoreoEvent::GetPlayOverScript( void ) +{ + return m_bPlayOverScript; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CChoreoEvent::GetDuration( void ) +{ + if ( HasEndTime() ) + { + return GetEndTime() - GetStartTime(); + } + + return 0.0f; +} + + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CChoreoEvent::ClearAllRelativeTags( void ) +{ + m_RelativeTags.Purge(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CChoreoEvent::GetNumRelativeTags( void ) +{ + return m_RelativeTags.Size(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : tagnum - +// Output : CEventRelativeTag +//----------------------------------------------------------------------------- +CEventRelativeTag *CChoreoEvent::GetRelativeTag( int tagnum ) +{ + Assert( tagnum >= 0 && tagnum < m_RelativeTags.Size() ); + return &m_RelativeTags[ tagnum ]; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *tagname - +// percentage - +//----------------------------------------------------------------------------- +void CChoreoEvent::AddRelativeTag( const char *tagname, float percentage ) +{ + CEventRelativeTag rt( this, tagname, percentage ); + m_RelativeTags.AddToTail( rt ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *tagname - +//----------------------------------------------------------------------------- +void CChoreoEvent::RemoveRelativeTag( const char *tagname ) +{ + for ( int i = 0; i < m_RelativeTags.Size(); i++ ) + { + CEventRelativeTag *prt = &m_RelativeTags[ i ]; + if ( !prt ) + continue; + + if ( !stricmp( prt->GetName(), tagname ) ) + { + m_RelativeTags.Remove( i ); + return; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *tagname - +// Output : CEventRelativeTag * +//----------------------------------------------------------------------------- +CEventRelativeTag * CChoreoEvent::FindRelativeTag( const char *tagname ) +{ + for ( int i = 0; i < m_RelativeTags.Size(); i++ ) + { + CEventRelativeTag *prt = &m_RelativeTags[ i ]; + if ( !prt ) + continue; + + if ( !stricmp( prt->GetName(), tagname ) ) + { + return prt; + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CChoreoEvent::IsUsingRelativeTag( void ) +{ + return m_bUsesTag; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : usetag - +// 0 - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetUsingRelativeTag( bool usetag, const char *tagname /*= 0*/, + const char *wavname /* = 0 */ ) +{ + m_bUsesTag = usetag; + if ( tagname ) + { + m_TagName = tagname; + } + else + { + m_TagName.Set(""); + } + if ( wavname ) + { + m_TagWavName = wavname; + } + else + { + m_TagWavName.Set(""); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *CChoreoEvent::GetRelativeTagName( void ) +{ + return m_TagName.Get(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *CChoreoEvent::GetRelativeWavName( void ) +{ + return m_TagWavName.Get(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CChoreoEvent::ClearAllTimingTags( void ) +{ + m_TimingTags.Purge(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CChoreoEvent::GetNumTimingTags( void ) +{ + return m_TimingTags.Size(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : tagnum - +// Output : CEventRelativeTag +//----------------------------------------------------------------------------- +CFlexTimingTag *CChoreoEvent::GetTimingTag( int tagnum ) +{ + Assert( tagnum >= 0 && tagnum < m_TimingTags.Size() ); + return &m_TimingTags[ tagnum ]; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *tagname - +// percentage - +//----------------------------------------------------------------------------- +void CChoreoEvent::AddTimingTag( const char *tagname, float percentage, bool locked ) +{ + CFlexTimingTag tt( this, tagname, percentage, locked ); + m_TimingTags.AddToTail( tt ); + + // Sort tags + CFlexTimingTag temp( (CChoreoEvent *)0x1, "", 0.0f, false ); + + // ugly bubble sort + for ( int i = 0; i < m_TimingTags.Size(); i++ ) + { + for ( int j = i + 1; j < m_TimingTags.Size(); j++ ) + { + CFlexTimingTag *t1 = &m_TimingTags[ i ]; + CFlexTimingTag *t2 = &m_TimingTags[ j ]; + + if ( t1->GetPercentage() > t2->GetPercentage() ) + { + temp = *t1; + *t1 = *t2; + *t2 = temp; + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *tagname - +//----------------------------------------------------------------------------- +void CChoreoEvent::RemoveTimingTag( const char *tagname ) +{ + for ( int i = 0; i < m_TimingTags.Size(); i++ ) + { + CFlexTimingTag *ptt = &m_TimingTags[ i ]; + if ( !ptt ) + continue; + + if ( !stricmp( ptt->GetName(), tagname ) ) + { + m_TimingTags.Remove( i ); + return; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *tagname - +// Output : CEventRelativeTag * +//----------------------------------------------------------------------------- +CFlexTimingTag * CChoreoEvent::FindTimingTag( const char *tagname ) +{ + for ( int i = 0; i < m_TimingTags.Size(); i++ ) + { + CFlexTimingTag *ptt = &m_TimingTags[ i ]; + if ( !ptt ) + continue; + + if ( !stricmp( ptt->GetName(), tagname ) ) + { + return ptt; + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CChoreoEvent::OnEndTimeChanged( void ) +{ + int c = GetNumFlexAnimationTracks(); + for ( int i = 0; i < c; i++ ) + { + CFlexAnimationTrack *track = GetFlexAnimationTrack( i ); + Assert( track ); + if ( !track ) + continue; + + track->Resort( 0 ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CChoreoEvent::GetNumFlexAnimationTracks( void ) +{ + return m_FlexAnimationTracks.Size(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : index - +// Output : CFlexAnimationTrack +//----------------------------------------------------------------------------- +CFlexAnimationTrack *CChoreoEvent::GetFlexAnimationTrack( int index ) +{ + if ( index < 0 || index >= GetNumFlexAnimationTracks() ) + return NULL; + return m_FlexAnimationTracks[ index ]; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *controllername - +// Output : CFlexAnimationTrack +//----------------------------------------------------------------------------- +CFlexAnimationTrack *CChoreoEvent::AddTrack( const char *controllername ) +{ + CFlexAnimationTrack *newTrack = new CFlexAnimationTrack( this ); + newTrack->SetFlexControllerName( controllername ); + + m_FlexAnimationTracks.AddToTail( newTrack ); + + return newTrack; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : index - +//----------------------------------------------------------------------------- +void CChoreoEvent::RemoveTrack( int index ) +{ + CFlexAnimationTrack *track = GetFlexAnimationTrack( index ); + if ( !track ) + return; + + m_FlexAnimationTracks.Remove( index ); + delete track; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CChoreoEvent::RemoveAllTracks( void ) +{ + while ( GetNumFlexAnimationTracks() > 0 ) + { + RemoveTrack( 0 ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *controllername - +// Output : CFlexAnimationTrack +//----------------------------------------------------------------------------- +CFlexAnimationTrack *CChoreoEvent::FindTrack( const char *controllername ) +{ + for ( int i = 0; i < GetNumFlexAnimationTracks(); i++ ) + { + CFlexAnimationTrack *t = GetFlexAnimationTrack( i ); + if ( t && !stricmp( t->GetFlexControllerName(), controllername ) ) + { + return t; + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CChoreoEvent::GetTrackLookupSet( void ) +{ + return m_bTrackLookupSet; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : set - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetTrackLookupSet( bool set ) +{ + m_bTrackLookupSet = set; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CChoreoEvent::IsProcessing( void ) const +{ + return m_bProcessing; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *cb - +// t - +//----------------------------------------------------------------------------- +void CChoreoEvent::StartProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) +{ + Assert( !m_bProcessing ); + m_bProcessing = true; + if ( cb ) + { + cb->StartEvent( t, scene, this ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *cb - +// t - +//----------------------------------------------------------------------------- +void CChoreoEvent::ContinueProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) +{ + Assert( m_bProcessing ); + if ( cb ) + { + cb->ProcessEvent( t, scene, this ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *cb - +// t - +//----------------------------------------------------------------------------- +void CChoreoEvent::StopProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) +{ + Assert( m_bProcessing ); + if ( cb ) + { + cb->EndEvent( t, scene, this ); + } + m_bProcessing = false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *cb - +// t - +//----------------------------------------------------------------------------- +bool CChoreoEvent::CheckProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) +{ + //Assert( !m_bProcessing ); + if ( cb ) + { + return cb->CheckEvent( t, scene, this ); + } + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CChoreoEvent::ResetProcessing( void ) +{ + if ( GetType() == LOOP ) + { + m_nLoopsRemaining = m_nNumLoops; + } + + m_bProcessing = false; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *mixer - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetMixer( CAudioMixer *mixer ) +{ + m_pMixer = mixer; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CAudioMixer +//----------------------------------------------------------------------------- +CAudioMixer *CChoreoEvent::GetMixer( void ) const +{ + return m_pMixer; +} + +// Snap to scene framerate +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CChoreoEvent::SnapTimes() +{ + if ( HasEndTime() && !IsFixedLength() ) + { + m_flEndTime = SnapTime( m_flEndTime ); + } + float oldstart = m_flStartTime; + m_flStartTime = SnapTime( m_flStartTime ); + + // Don't snap end time for fixed length events, just set based on new start time + if ( IsFixedLength() ) + { + float dt = m_flStartTime - oldstart; + m_flEndTime += dt; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : t - +// Output : float +//----------------------------------------------------------------------------- +float CChoreoEvent::SnapTime( float t ) +{ + CChoreoScene *scene = GetScene(); + if ( !scene) + { + Assert( 0 ); + return t; + } + + return scene->SnapTime( t ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : CChoreoScene +//----------------------------------------------------------------------------- +CChoreoScene *CChoreoEvent::GetScene( void ) +{ + return m_pScene; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *scene - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetScene( CChoreoScene *scene ) +{ + m_pScene = scene; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : t - +// Output : char const +//----------------------------------------------------------------------------- +const char *CChoreoEvent::NameForAbsoluteTagType( AbsTagType t ) +{ + switch ( t ) + { + case PLAYBACK: + return "playback_time"; + case ORIGINAL: + return "shifted_time"; + default: + break; + } + + return "AbsTagType(unknown)"; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *name - +// Output : AbsTagType +//----------------------------------------------------------------------------- +CChoreoEvent::AbsTagType CChoreoEvent::TypeForAbsoluteTagName( const char *name ) +{ + if ( !Q_strcasecmp( name, "playback_time" ) ) + { + return PLAYBACK; + } + else if ( !Q_strcasecmp( name, "shifted_time" ) ) + { + return ORIGINAL; + } + + return (AbsTagType)-1; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +//----------------------------------------------------------------------------- +void CChoreoEvent::ClearAllAbsoluteTags( AbsTagType type ) +{ + m_AbsoluteTags[ type ].Purge(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// Output : int +//----------------------------------------------------------------------------- +int CChoreoEvent::GetNumAbsoluteTags( AbsTagType type ) +{ + return m_AbsoluteTags[ type ].Size(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// tagnum - +// Output : CEventAbsoluteTag +//----------------------------------------------------------------------------- +CEventAbsoluteTag *CChoreoEvent::GetAbsoluteTag( AbsTagType type, int tagnum ) +{ + Assert( tagnum >= 0 && tagnum < m_AbsoluteTags[ type ].Size() ); + return &m_AbsoluteTags[ type ][ tagnum ]; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// *tagname - +// Output : CEventAbsoluteTag +//----------------------------------------------------------------------------- +CEventAbsoluteTag *CChoreoEvent::FindAbsoluteTag( AbsTagType type, const char *tagname ) +{ + for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + { + CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; + if ( !ptag ) + continue; + + if ( !stricmp( ptag->GetName(), tagname ) ) + { + return ptag; + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// *tagname - +// t - +//----------------------------------------------------------------------------- +void CChoreoEvent::AddAbsoluteTag( AbsTagType type, const char *tagname, float t ) +{ + CEventAbsoluteTag at( this, tagname, t ); + m_AbsoluteTags[ type ].AddToTail( at ); + + // Sort tags + CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f ); + + // ugly bubble sort + for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + { + for ( int j = i + 1; j < m_AbsoluteTags[ type ].Size(); j++ ) + { + CEventAbsoluteTag *t1 = &m_AbsoluteTags[ type ][ i ]; + CEventAbsoluteTag *t2 = &m_AbsoluteTags[ type ][ j ]; + + if ( t1->GetPercentage() > t2->GetPercentage() ) + { + temp = *t1; + *t1 = *t2; + *t2 = temp; + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// *tagname - +//----------------------------------------------------------------------------- +void CChoreoEvent::RemoveAbsoluteTag( AbsTagType type, const char *tagname ) +{ + for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + { + CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; + if ( !ptag ) + continue; + + if ( !stricmp( ptag->GetName(), tagname ) ) + { + m_AbsoluteTags[ type ].Remove( i ); + return; + } + } +} + + + +//----------------------------------------------------------------------------- +// Purpose: makes sure tags in PLAYBACK are in the same order as ORIGINAL +// Input : +// Output : true if they were in order, false if it has to reorder them +//----------------------------------------------------------------------------- +bool CChoreoEvent::VerifyTagOrder( ) +{ + bool bInOrder = true; + + // Sort tags + CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f ); + + for ( int i = 0; i < m_AbsoluteTags[ CChoreoEvent::ORIGINAL ].Size(); i++ ) + { + CEventAbsoluteTag *ptag = &m_AbsoluteTags[ CChoreoEvent::ORIGINAL ][ i ]; + if ( !ptag ) + continue; + + CEventAbsoluteTag *t1 = &m_AbsoluteTags[ CChoreoEvent::PLAYBACK ][ i ]; + + if ( stricmp( ptag->GetName(), t1->GetName() ) == 0) + continue; + + bInOrder = false; + for ( int j = i + 1; j < m_AbsoluteTags[ CChoreoEvent::PLAYBACK ].Size(); j++ ) + { + CEventAbsoluteTag *t2 = &m_AbsoluteTags[ CChoreoEvent::PLAYBACK ][ j ]; + + if ( stricmp( ptag->GetName(), t2->GetName() ) == 0 ) + { + temp = *t1; + *t1 = *t2; + *t2 = temp; + break; + } + } + } + return bInOrder; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// *tagname - +//----------------------------------------------------------------------------- + +float CChoreoEvent::GetBoundedAbsoluteTagPercentage( AbsTagType type, int tagnum ) +{ + if ( tagnum <= -2 ) + { + /* + if (GetNumAbsoluteTags( type ) >= 1) + { + CEventAbsoluteTag *tag = GetAbsoluteTag( type, 0 ); + Assert( tag ); + return -tag->GetTime(); + } + */ + return 0.0f; // -0.5f; + } + else if ( tagnum == -1 ) + { + return 0.0f; + } + else if ( tagnum == GetNumAbsoluteTags( type ) ) + { + return 1.0; + } + else if ( tagnum > GetNumAbsoluteTags( type ) ) + { + /* + if (GetNumAbsoluteTags( type ) >= 1) + { + CEventAbsoluteTag *tag = GetAbsoluteTag( type, tagnum - 2 ); + Assert( tag ); + return 2.0 - tag->GetTime(); + } + */ + return 1.0; // 1.5; + } + + /* + { + float duration = GetDuration(); + + if ( type == SHIFTED ) + { + float seqduration; + GetGestureSequenceDuration( seqduration ); + return seqduration; + } + return duration; + } + */ + + CEventAbsoluteTag *tag = GetAbsoluteTag( type, tagnum ); + Assert( tag ); + return tag->GetPercentage(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : t - +// Output : float +//----------------------------------------------------------------------------- +float CChoreoEvent::GetOriginalPercentageFromPlaybackPercentage( float t ) +{ + Assert( GetType() == GESTURE ); + if ( GetType() != GESTURE ) + return t; + + int count = GetNumAbsoluteTags( PLAYBACK ); + + if ( count != GetNumAbsoluteTags( ORIGINAL ) ) + { + return t; + } + + if ( count <= 0 ) + { + return t; + } + + if ( t <= 0.0f ) + return 0.0f; + + float s = 0.0f, n = 0.0f; + + // find what tags this is between + int i; + for ( i = -1 ; i < count; i++ ) + { + s = GetBoundedAbsoluteTagPercentage( PLAYBACK, i ); + n = GetBoundedAbsoluteTagPercentage( PLAYBACK, i + 1 ); + + if ( t >= s && t <= n ) + { + break; + } + } + + int prev = i - 1; + int start = i; + int end = i + 1; + int next = i + 2; + + prev = MAX( -2, prev ); + start = MAX( -1, start ); + end = MIN( end, count ); + next = MIN( next, count + 1 ); + + CEventAbsoluteTag *pStartTag = NULL; + CEventAbsoluteTag *pEndTag = NULL; + + // check for linear portion of lookup + if (start >= 0 && start < count) + { + pStartTag = GetAbsoluteTag( PLAYBACK, start ); + } + if (end >= 0 && end < count) + { + pEndTag = GetAbsoluteTag( PLAYBACK, end ); + } + + if (pStartTag && pEndTag) + { + if (pStartTag->GetLinear() && pEndTag->GetLinear()) + { + CEventAbsoluteTag *pOrigStartTag = GetAbsoluteTag( ORIGINAL, start ); + CEventAbsoluteTag *pOrigEndTag = GetAbsoluteTag( ORIGINAL, end ); + + if (pOrigStartTag && pOrigEndTag) + { + s = ( t - pStartTag->GetPercentage() ) / (pEndTag->GetPercentage() - pStartTag->GetPercentage()); + return (1 - s) * pOrigStartTag->GetPercentage() + s * pOrigEndTag->GetPercentage(); + } + } + } + + float dt = n - s; + + Vector vPre( GetBoundedAbsoluteTagPercentage( PLAYBACK, prev ), GetBoundedAbsoluteTagPercentage( ORIGINAL, prev ), 0 ); + Vector vStart( GetBoundedAbsoluteTagPercentage( PLAYBACK, start ), GetBoundedAbsoluteTagPercentage( ORIGINAL, start ), 0 ); + Vector vEnd( GetBoundedAbsoluteTagPercentage( PLAYBACK, end ), GetBoundedAbsoluteTagPercentage( ORIGINAL, end ), 0 ); + Vector vNext( GetBoundedAbsoluteTagPercentage( PLAYBACK, next ), GetBoundedAbsoluteTagPercentage( ORIGINAL, next ), 0 ); + + // simulate sections of either side of "linear" portion of ramp as linear slope + if (pStartTag && pStartTag->GetLinear()) + { + vPre.Init( vStart.x - (vEnd.x - vStart.x), vStart.y - (vEnd.y - vStart.y), 0 ); + } + + if (pEndTag && pEndTag->GetLinear()) + { + vNext.Init( vEnd.x + (vEnd.x - vStart.x), vEnd.y + (vEnd.y - vStart.y), 0 ); + } + + + float f2 = 0.0f; + if ( dt > 0.0f ) + { + f2 = ( t - s ) / ( dt ); + } + f2 = clamp( f2, 0.0f, 1.0f ); + + Vector vOut; + Catmull_Rom_Spline_NormalizeX( + vPre, + vStart, + vEnd, + vNext, + f2, + vOut ); + + return vOut.y; + + /* + float duration; + GetGestureSequenceDuration( duration ); + + float retval = clamp( vOut.y, 0.0f, duration ); + return retval; + */ +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : t - +// Output : float +//----------------------------------------------------------------------------- +float CChoreoEvent::GetPlaybackPercentageFromOriginalPercentage( float t ) +{ + Assert( GetType() == GESTURE ); + if ( GetType() != GESTURE ) + return t; + + int count = GetNumAbsoluteTags( PLAYBACK ); + + if ( count != GetNumAbsoluteTags( ORIGINAL ) ) + { + return t; + } + + if ( count <= 0 ) + { + return t; + } + + if ( t <= 0.0f ) + return 0.0f; + + float s = 0.0f, n = 0.0f; + + // find what tags this is between + int i; + for ( i = -1 ; i < count; i++ ) + { + s = GetBoundedAbsoluteTagPercentage( PLAYBACK, i ); + n = GetBoundedAbsoluteTagPercentage( PLAYBACK, i + 1 ); + + if ( t >= s && t <= n ) + { + break; + } + } + + int prev = i - 1; + int start = i; + int end = i + 1; + int next = i + 2; + + prev = MAX( -2, prev ); + start = MAX( -1, start ); + end = MIN( end, count ); + next = MIN( next, count + 1 ); + + CEventAbsoluteTag *pStartTag = NULL; + CEventAbsoluteTag *pEndTag = NULL; + + // check for linear portion of lookup + if (start >= 0 && start < count) + { + pStartTag = GetAbsoluteTag( ORIGINAL, start ); + } + if (end >= 0 && end < count) + { + pEndTag = GetAbsoluteTag( ORIGINAL, end ); + } + + // check for linear portion of lookup + if (pStartTag && pEndTag) + { + if (pStartTag->GetLinear() && pEndTag->GetLinear()) + { + CEventAbsoluteTag *pPlaybackStartTag = GetAbsoluteTag( PLAYBACK, start ); + CEventAbsoluteTag *pPlaybackEndTag = GetAbsoluteTag( PLAYBACK, end ); + + if (pPlaybackStartTag && pPlaybackEndTag) + { + s = ( t - pStartTag->GetPercentage() ) / (pEndTag->GetPercentage() - pStartTag->GetPercentage()); + return (1 - s) * pPlaybackStartTag->GetPercentage() + s * pPlaybackEndTag->GetPercentage(); + } + } + } + + float dt = n - s; + + Vector vPre( GetBoundedAbsoluteTagPercentage( ORIGINAL, prev ), GetBoundedAbsoluteTagPercentage( PLAYBACK, prev ), 0 ); + Vector vStart( GetBoundedAbsoluteTagPercentage( ORIGINAL, start ), GetBoundedAbsoluteTagPercentage( PLAYBACK, start ), 0 ); + Vector vEnd( GetBoundedAbsoluteTagPercentage( ORIGINAL, end ), GetBoundedAbsoluteTagPercentage( PLAYBACK, end ), 0 ); + Vector vNext( GetBoundedAbsoluteTagPercentage( ORIGINAL, next ), GetBoundedAbsoluteTagPercentage( PLAYBACK, next ), 0 ); + + // simulate sections of either side of "linear" portion of ramp as linear slope + if (pStartTag && pStartTag->GetLinear()) + { + vPre.Init( vStart.x - (vEnd.x - vStart.x), vStart.y - (vEnd.y - vStart.y), 0 ); + } + + if (pEndTag && pEndTag->GetLinear()) + { + vNext.Init( vEnd.x + (vEnd.x - vStart.x), vEnd.y + (vEnd.y - vStart.y), 0 ); + } + + float f2 = 0.0f; + if ( dt > 0.0f ) + { + f2 = ( t - s ) / ( dt ); + } + f2 = clamp( f2, 0.0f, 1.0f ); + + Vector vOut; + Catmull_Rom_Spline_NormalizeX( + vPre, + vStart, + vEnd, + vNext, + f2, + vOut ); + + return vOut.y; + + /* + float duration; + GetGestureSequenceDuration( duration ); + + float retval = clamp( vOut.y, 0.0f, duration ); + return retval; + */ +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : duration - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetGestureSequenceDuration( float duration ) +{ + m_flGestureSequenceDuration = duration; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : duration - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CChoreoEvent::GetGestureSequenceDuration( float& duration ) +{ + bool valid = m_flGestureSequenceDuration != 0.0f; + + if ( !valid ) + { + duration = GetDuration(); + } + else + { + duration = m_flGestureSequenceDuration; + } + + return valid; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pitch - +//----------------------------------------------------------------------------- +int CChoreoEvent::GetPitch( void ) const +{ + return m_nPitch; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pitch - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetPitch( int pitch ) +{ + m_nPitch = pitch; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : yaw - +//----------------------------------------------------------------------------- +int CChoreoEvent::GetYaw( void ) const +{ + return m_nYaw; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : yaw - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetYaw( int yaw ) +{ + m_nYaw = yaw; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : t - +// -1 - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetLoopCount( int numloops ) +{ + Assert( GetType() == LOOP ); + // Never below -1 + m_nNumLoops = MAX( numloops, -1 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CChoreoEvent::GetNumLoopsRemaining( void ) +{ + Assert( GetType() == LOOP ); + + return m_nLoopsRemaining; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : loops - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetNumLoopsRemaining( int loops ) +{ + Assert( GetType() == LOOP ); + + m_nLoopsRemaining = loops; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CChoreoEvent::GetLoopCount( void ) +{ + Assert( GetType() == LOOP ); + return m_nNumLoops; +} + +EdgeInfo_t *CCurveData::GetEdgeInfo( int idx ) +{ + return &m_RampEdgeInfo[ idx ]; +} + +int CCurveData::GetCount( void ) +{ + return m_Ramp.Count(); +} + +CExpressionSample *CCurveData::Get( int index ) +{ + if ( index < 0 || index >= GetCount() ) + return NULL; + + return &m_Ramp[ index ]; +} + +CExpressionSample *CCurveData::Add( float time, float value, bool selected ) +{ + CExpressionSample sample; + + sample.time = time; + sample.value = value; + sample.selected = selected; + + int idx = m_Ramp.AddToTail( sample ); + return &m_Ramp[ idx ]; +} + +void CCurveData::Delete( int index ) +{ + if ( index < 0 || index >= GetCount() ) + return; + + m_Ramp.Remove( index ); +} + +void CCurveData::Clear( void ) +{ + m_Ramp.RemoveAll(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCurveData::Resort( ICurveDataAccessor *data ) +{ + for ( int i = 0; i < m_Ramp.Size(); i++ ) + { + for ( int j = i + 1; j < m_Ramp.Size(); j++ ) + { + CExpressionSample src = m_Ramp[ i ]; + CExpressionSample dest = m_Ramp[ j ]; + + if ( src.time > dest.time ) + { + m_Ramp[ i ] = dest; + m_Ramp[ j ] = src; + } + } + } + + RemoveOutOfRangeSamples( data ); + + // m_RampAccumulator.RemoveAll(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : number - +// Output : CExpressionSample +//----------------------------------------------------------------------------- +CExpressionSample *CCurveData::GetBoundedSample( ICurveDataAccessor *data, int number, bool& bClamped ) +{ + // Search for two samples which span time f + if ( number < 0 ) + { + static CExpressionSample nullstart; + nullstart.time = 0.0f; + nullstart.value = GetEdgeZeroValue( true ); + nullstart.SetCurveType( GetEdgeCurveType( true ) ); + bClamped = true; + return &nullstart; + } + else if ( number >= GetCount() ) + { + static CExpressionSample nullend; + nullend.time = data->GetDuration(); + nullend.value = GetEdgeZeroValue( false ); + nullend.SetCurveType( GetEdgeCurveType( false ) ); + bClamped = true; + return &nullend; + } + + bClamped = false; + return Get( number ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCurveData::RemoveOutOfRangeSamples( ICurveDataAccessor *data ) +{ + float duration = data->GetDuration(); + + int c = GetCount(); + for ( int i = c-1; i >= 0; i-- ) + { + CExpressionSample src = m_Ramp[ i ]; + if ( src.time < 0 || + src.time > duration + 0.01 ) + { + m_Ramp.Remove( i ); + } + } +} + + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CChoreoEvent::RescaleGestureTimes( float newstart, float newend, bool bMaintainAbsoluteTagPositions ) +{ + if ( GetType() != CChoreoEvent::GESTURE ) + return; + + // Did it actually change + if ( newstart == GetStartTime() && + newend == GetEndTime() ) + { + return; + } + + float newduration = newend - newstart; + + float dt = 0.0f; + //If the end is moving, leave tags stay where they are (dt == 0.0f) + if ( newstart != GetStartTime() ) + { + // Otherwise, if the new start is later, then tags need to be shifted backwards + dt -= ( newstart - GetStartTime() ); + } + + if ( bMaintainAbsoluteTagPositions ) + { + int i; + int count = GetNumAbsoluteTags( CChoreoEvent::PLAYBACK ); + for ( i = 0; i < count; i++ ) + { + CEventAbsoluteTag *tag = GetAbsoluteTag( CChoreoEvent::PLAYBACK, i ); + float tagtime = tag->GetPercentage() * GetDuration(); + + tagtime += dt; + + tagtime = clamp( tagtime / newduration, 0.0f, 1.0f ); + + tag->SetPercentage( tagtime ); + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Make sure tags aren't co-located or out of order +//----------------------------------------------------------------------------- +bool CChoreoEvent::PreventTagOverlap( void ) +{ + bool bHadOverlap = false; + + // FIXME: limit to single frame? + float minDp = 0.01; + + float minP = 1.00; + + int count = GetNumAbsoluteTags( CChoreoEvent::PLAYBACK ); + for ( int i = count - 1; i >= 0; i-- ) + { + CEventAbsoluteTag *tag = GetAbsoluteTag( CChoreoEvent::PLAYBACK, i ); + + if (tag->GetPercentage() > minP) + { + tag->SetPercentage( minP ); + + minDp = MIN( 0.01, minP / (i + 1) ); + bHadOverlap = true; + } + else + { + minP = tag->GetPercentage(); + } + minP = MAX( minP - minDp, 0 ); + } + + return bHadOverlap; +} + + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// Output : CEventAbsoluteTag +//----------------------------------------------------------------------------- +CEventAbsoluteTag *CChoreoEvent::FindEntryTag( AbsTagType type ) +{ + for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + { + CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; + if ( !ptag ) + continue; + + if ( ptag->GetEntry() ) + { + return ptag; + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +// Output : CEventAbsoluteTag +//----------------------------------------------------------------------------- +CEventAbsoluteTag *CChoreoEvent::FindExitTag( AbsTagType type ) +{ + for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) + { + CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; + if ( !ptag ) + continue; + + if ( ptag->GetExit() ) + { + return ptag; + } + } + return NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *style - +// maxlen - +//----------------------------------------------------------------------------- +void CChoreoEvent::GetMovementStyle( char *style, int maxlen ) +{ + Assert( GetType() == MOVETO ); + + style[0] = 0; + + const char *in = m_Parameters2.Get(); + char *out = style; + + while ( *in && *in != '\0' && *in != ' ' ) + { + if ( out - style >= maxlen - 1 ) + break; + *out++ = *in++; + } + + *out = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *style - +// maxlen - +//----------------------------------------------------------------------------- +void CChoreoEvent::GetDistanceStyle( char *style, int maxlen ) +{ + Assert( GetType() == MOVETO ); + + style[0]= 0; + + const char *in = Q_strstr( m_Parameters2.Get(), " " ); + if ( !in ) + return; + + in++; + char *out = style; + + while ( *in && *in != '\0' ) + { + if ( out - style >= maxlen - 1 ) + break; + *out++ = *in++; + } + + *out = 0; +} + +void CChoreoEvent::SetCloseCaptionType( CLOSECAPTION type ) +{ + Assert( m_fType == SPEAK ); + m_ccType = type; +} + +CChoreoEvent::CLOSECAPTION CChoreoEvent::GetCloseCaptionType() const +{ + Assert( m_fType == SPEAK ); + return (CLOSECAPTION)m_ccType; +} + +void CChoreoEvent::SetCloseCaptionToken( char const *token ) +{ + Assert( m_fType == SPEAK ); + Assert( token ); + m_CCToken = token; +} + +char const *CChoreoEvent::GetCloseCaptionToken() const +{ + Assert( m_fType == SPEAK ); + return m_CCToken.Get(); +} + +bool CChoreoEvent::GetPlaybackCloseCaptionToken( char *dest, int destlen ) +{ + dest[0] = 0; + + Assert( m_fType == SPEAK ); + + switch ( m_ccType ) + { + default: + case CC_DISABLED: + { + return false; + } + case CC_SLAVE: + { + // If it's a slave, then only disable if we're not using the combined wave + if ( IsUsingCombinedFile() ) + { + return false; + } + + if ( m_CCToken[ 0 ] != 0 ) + { + Q_strncpy( dest, m_CCToken.Get(), destlen ); + } + else + { + Q_strncpy( dest, m_Parameters.Get(), destlen ); + } + return true; + } + case CC_MASTER: + { + // Always use the override if we're the master, otherwise always use the default + // parameter + if ( m_CCToken[ 0 ] != 0 ) + { + Q_strncpy( dest, m_CCToken.Get(), destlen ); + } + else + { + Q_strncpy( dest, m_Parameters.Get(), destlen ); + } + return true; + } + } + + return false; +} + + +void CChoreoEvent::SetUsingCombinedFile( bool isusing ) +{ + Assert( m_fType == SPEAK ); + m_bUsingCombinedSoundFile = isusing; +} + +bool CChoreoEvent::IsUsingCombinedFile() const +{ + Assert( m_fType == SPEAK ); + return m_bUsingCombinedSoundFile; +} + +void CChoreoEvent::SetRequiredCombinedChecksum( unsigned int checksum ) +{ + Assert( m_fType == SPEAK ); + m_uRequiredCombinedChecksum = checksum; +} + +unsigned int CChoreoEvent::GetRequiredCombinedChecksum() +{ + Assert( m_fType == SPEAK ); + return m_uRequiredCombinedChecksum; +} + +void CChoreoEvent::SetNumSlaves( int num ) +{ + Assert( m_fType == SPEAK ); + Assert( num >= 0 ); + m_nNumSlaves = num; +} + +int CChoreoEvent::GetNumSlaves() const +{ + Assert( m_fType == SPEAK ); + return m_nNumSlaves; +} + +void CChoreoEvent::SetLastSlaveEndTime( float t ) +{ + Assert( m_fType == SPEAK ); + m_flLastSlaveEndTime = t; +} + +float CChoreoEvent::GetLastSlaveEndTime() const +{ + Assert( m_fType == SPEAK ); + return m_flLastSlaveEndTime; +} + +void CChoreoEvent::SetCloseCaptionTokenValid( bool valid ) +{ + Assert( m_fType == SPEAK ); + m_bCCTokenValid = valid; +} + +bool CChoreoEvent::GetCloseCaptionTokenValid() const +{ + Assert( m_fType == SPEAK ); + return m_bCCTokenValid; +} + + +//----------------------------------------------------------------------------- +// Purpose: Removes characters which can't appear in windows filenames +// Input : *in - +// *dest - +// destlen - +// Output : static void +//----------------------------------------------------------------------------- +static void CleanupTokenName( char const *in, char *dest, int destlen ) +{ + char *out = dest; + while ( *in && ( out - dest ) < destlen ) + { + if ( V_isalnum( *in ) || // lowercase, uppercase, digits and underscore are valid + *in == '_' ) + { + *out++ = *in; + } + else + { + *out++ = '_'; // Put underscores in for bogus characters + } + in++; + } + *out = 0; +} + +bool CChoreoEvent::ComputeCombinedBaseFileName( char *dest, int destlen, bool creategenderwildcard ) +{ + if ( m_fType != SPEAK ) + return false; + + if ( m_ccType != CC_MASTER ) + return false; + + if ( GetNumSlaves() == 0 ) + return false; + + if ( !m_pScene ) + return false; + + char vcdpath[ 512 ]; + char cleanedtoken[ MAX_CCTOKEN_STRING ]; + CleanupTokenName( m_CCToken.Get(), cleanedtoken, sizeof( cleanedtoken ) ); + + if ( Q_strlen( cleanedtoken ) <= 0 ) + return false; + + Q_strncpy( vcdpath, m_pScene->GetFilename(), sizeof( vcdpath ) ); + Q_StripFilename( vcdpath ); + Q_FixSlashes( vcdpath, '/' ); + + char *pvcd = vcdpath; + + char *offset = Q_strstr( vcdpath, "scenes" ); + if ( offset ) + { + pvcd = offset + 6; + if ( *pvcd == '/' ) + { + ++pvcd; + } + } + + int len = Q_strlen( pvcd ); + + if ( len > 0 && ( len + 1 ) < ( sizeof( vcdpath ) - 1 ) ) + { + pvcd[ len ] = '/'; + pvcd[ len + 1 ] = 0; + } + + Assert( !Q_strstr( pvcd, ":" ) ); + + if ( creategenderwildcard ) + { + Q_snprintf( dest, destlen, "sound/combined/%s%s_$gender.wav", pvcd, cleanedtoken ); + } + else + { + Q_snprintf( dest, destlen, "sound/combined/%s%s.wav", pvcd, cleanedtoken ); + } + return true; +} + +bool CChoreoEvent::IsCombinedUsingGenderToken() const +{ + return m_bCombinedUsingGenderToken; +} + +void CChoreoEvent::SetCombinedUsingGenderToken( bool using_gender ) +{ + m_bCombinedUsingGenderToken = using_gender; +} + + +int CChoreoEvent::ValidateCombinedFile() +{ + + return 0; +} + +bool CChoreoEvent::IsSuppressingCaptionAttenuation() const +{ + return m_bSuppressCaptionAttenuation; +} + +void CChoreoEvent::SetSuppressingCaptionAttenuation( bool suppress ) +{ + m_bSuppressCaptionAttenuation = suppress; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CChoreoEvent::ClearEventDependencies() +{ + m_Dependencies.RemoveAll(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *other - +//----------------------------------------------------------------------------- +void CChoreoEvent::AddEventDependency( CChoreoEvent *other ) +{ + if ( m_Dependencies.Find( other ) == m_Dependencies.InvalidIndex() ) + { + m_Dependencies.AddToTail( other ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : list - +//----------------------------------------------------------------------------- +void CChoreoEvent::GetEventDependencies( CUtlVector< CChoreoEvent * >& list ) +{ + int c = m_Dependencies.Count(); + for ( int i = 0; i < c; ++i ) + { + list.AddToTail( m_Dependencies[ i ] ); + } +} + +void CCurveData::SetEdgeInfo( bool leftEdge, int curveType, float zero ) +{ + int idx = leftEdge ? 0 : 1; + m_RampEdgeInfo[ idx ].m_CurveType = curveType; + m_RampEdgeInfo[ idx ].m_flZeroPos = zero; +} + +void CCurveData::GetEdgeInfo( bool leftEdge, int& curveType, float& zero ) const +{ + int idx = leftEdge ? 0 : 1; + curveType = m_RampEdgeInfo[ idx ].m_CurveType; + zero = m_RampEdgeInfo[ idx ].m_flZeroPos; +} + +void CCurveData::SetEdgeActive( bool leftEdge, bool state ) +{ + int idx = leftEdge ? 0 : 1; + m_RampEdgeInfo[ idx ].m_bActive = state; +} + +bool CCurveData::IsEdgeActive( bool leftEdge ) const +{ + int idx = leftEdge ? 0 : 1; + return m_RampEdgeInfo[ idx ].m_bActive; +} + +int CCurveData::GetEdgeCurveType( bool leftEdge ) const +{ + if ( !IsEdgeActive( leftEdge ) ) + { + return CURVE_DEFAULT; + } + + int idx = leftEdge ? 0 : 1; + return m_RampEdgeInfo[ idx ].m_CurveType; +} + +float CCurveData::GetEdgeZeroValue( bool leftEdge ) const +{ + if ( !IsEdgeActive( leftEdge ) ) + { + return 0.0f; + } + + int idx = leftEdge ? 0 : 1; + return m_RampEdgeInfo[ idx ].m_flZeroPos; +} + + +void CChoreoEvent::SaveToBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ) +{ + buf.PutChar( GetType() ); + buf.PutShort( pStringPool->FindOrAddString( GetName() ) ); + + float st = GetStartTime(); + buf.PutFloat( st ); + + float et = GetEndTime(); + buf.PutFloat( et ); + + buf.PutShort( pStringPool->FindOrAddString( GetParameters() ) ); + buf.PutShort( pStringPool->FindOrAddString( GetParameters2() ) ); + buf.PutShort( pStringPool->FindOrAddString( GetParameters3() ) ); + + m_Ramp.SaveToBuffer( buf, pStringPool ); + + int flags = 0; + flags |= IsResumeCondition() ? 1<<0 : 0; + flags |= IsLockBodyFacing() ? 1<<1 : 0; + flags |= IsFixedLength() ? 1<<2 : 0; + flags |= GetActive() ? 1<<3 : 0; + flags |= GetForceShortMovement() ? 1<<4 : 0; + flags |= GetPlayOverScript() ? 1<<5 : 0; + + buf.PutUnsignedChar( flags ); + + buf.PutFloat( GetDistanceToTarget() ); + + int numRelativeTags = GetNumRelativeTags(); + Assert( numRelativeTags <= 255 ); + buf.PutUnsignedChar( numRelativeTags ); + + for ( int t = 0; t < numRelativeTags; t++ ) + { + CEventRelativeTag *rt = GetRelativeTag( t ); + Assert( rt ); + buf.PutShort( pStringPool->FindOrAddString( rt->GetName() ) ); + + Assert( rt->GetPercentage() >= 0.0f && rt->GetPercentage() <= 1.0f ); + unsigned char p = rt->GetPercentage() * 255.0f; + buf.PutUnsignedChar( p ); + } + + int numTimingTags = GetNumTimingTags(); + Assert( numTimingTags <= 255 ); + buf.PutUnsignedChar( numTimingTags ); + + for ( int t = 0; t < numTimingTags; t++ ) + { + CFlexTimingTag *tt = GetTimingTag( t ); + Assert( tt ); + buf.PutShort( pStringPool->FindOrAddString( tt->GetName() ) ); + + // save as u0.8 + Assert( tt->GetPercentage() >= 0.0f && tt->GetPercentage() <= 1.0f ); + unsigned char p = tt->GetPercentage() * 255.0f; + buf.PutUnsignedChar( p ); + + // Don't save locked state, it's only used by the editor tt->GetLocked() + } + + int tagtype; + for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ ) + { + int num = GetNumAbsoluteTags( (CChoreoEvent::AbsTagType)tagtype ); + Assert( num <= 255 ); + buf.PutUnsignedChar( num ); + + for ( int i = 0; i < num ; ++i ) + { + CEventAbsoluteTag *abstag = GetAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, i ); + Assert( abstag ); + buf.PutShort( pStringPool->FindOrAddString( abstag->GetName() ) ); + + // save as u4.12 + Assert( abstag->GetPercentage() >= 0.0f && abstag->GetPercentage() <= 15.0f ); + unsigned short p = abstag->GetPercentage() * 4096.0f; + buf.PutUnsignedShort( p ); + } + } + + if ( GetType() == CChoreoEvent::GESTURE ) + { + float duration; + if ( GetGestureSequenceDuration( duration ) ) + { + buf.PutFloat( duration ); + } + else + { + buf.PutFloat( -1.0f ); + } + } + + buf.PutChar( IsUsingRelativeTag() ? 1 : 0 ); + if ( IsUsingRelativeTag() ) + { + buf.PutShort( pStringPool->FindOrAddString( GetRelativeTagName() ) ); + buf.PutShort( pStringPool->FindOrAddString( GetRelativeWavName() ) ); + } + + SaveFlexAnimationsToBuffer( buf, pStringPool ); + + if ( GetType() == LOOP ) + { + buf.PutChar( GetLoopCount() ); + } + + if ( GetType() == CChoreoEvent::SPEAK ) + { + buf.PutChar( GetCloseCaptionType() ); + buf.PutShort( pStringPool->FindOrAddString( GetCloseCaptionToken() ) ); + flags = 0; + + if ( GetCloseCaptionType() != CChoreoEvent::CC_DISABLED && + IsUsingCombinedFile() ) + { + flags |= ( 1<<0 ); + } + if ( IsCombinedUsingGenderToken() ) + { + flags |= ( 1<<1 ); + } + if ( IsSuppressingCaptionAttenuation() ) + { + flags |= ( 1<<2 ); + } + + buf.PutChar( flags ); + } +} + +bool CChoreoEvent::RestoreFromBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ) +{ + MEM_ALLOC_CREDIT(); + + SetType( (EVENTTYPE)buf.GetChar() ); + char sz[ 256 ]; + pStringPool->GetString( buf.GetShort(), sz, sizeof( sz ) ); + SetName( sz ); + + SetStartTime( buf.GetFloat() ); + SetEndTime( buf.GetFloat() ); + + char params[ 2048 ]; + pStringPool->GetString( buf.GetShort(), params, sizeof( params ) ); + SetParameters( params ); + pStringPool->GetString( buf.GetShort(), params, sizeof( params ) ); + SetParameters2( params ); + pStringPool->GetString( buf.GetShort(), params, sizeof( params ) ); + SetParameters3( params ); + + if ( !m_Ramp.RestoreFromBuffer( buf, pStringPool ) ) + return false; + + int flags = buf.GetUnsignedChar(); + SetResumeCondition( ( flags & ( 1<<0 ) ) ? true : false ); + SetLockBodyFacing( ( flags & ( 1<<1 ) ) ? true : false ); + SetFixedLength( ( flags & ( 1<<2 ) ) ? true : false ); + SetActive( ( flags & ( 1<<3 ) ) ? true : false ); + SetForceShortMovement( ( flags & ( 1<<4 ) ) ? true : false ); + SetPlayOverScript( ( flags & ( 1<<5 ) ) ? true : false ); + + SetDistanceToTarget( buf.GetFloat() ); + + int numRelTags = buf.GetUnsignedChar(); + for ( int i = 0; i < numRelTags; ++i ) + { + char tagName[ 256 ]; + pStringPool->GetString( buf.GetShort(), tagName, sizeof( tagName ) ); + float percentage = (float)buf.GetUnsignedChar() * 1.0f/255.0f; + AddRelativeTag( tagName, percentage ); + } + + int numTimingTags = buf.GetUnsignedChar(); + for ( int i = 0; i < numTimingTags; ++i ) + { + char tagName[ 256 ]; + pStringPool->GetString( buf.GetShort(), tagName, sizeof( tagName ) ); + float percentage = (float)buf.GetUnsignedChar() * 1.0f/255.0f; + // Don't parse locked state, only used by editors + AddTimingTag( tagName, percentage, false ); + } + + int tagtype; + for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ ) + { + int num = buf.GetUnsignedChar(); + for ( int i = 0; i < num; ++i ) + { + char tagName[ 256 ]; + pStringPool->GetString( buf.GetShort(), tagName, sizeof( tagName ) ); + float percentage = (float)buf.GetUnsignedShort() * 1.0f/4096.0f; + + // Don't parse locked state, only used by editors + AddAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, tagName, percentage ); + } + } + + if ( GetType() == CChoreoEvent::GESTURE ) + { + float duration = buf.GetFloat(); + if ( duration != -1 ) + { + SetGestureSequenceDuration( duration ); + } + } + + if ( buf.GetChar() == 1 ) + { + char tagname[ 256 ]; + char wavname[ 256 ]; + pStringPool->GetString( buf.GetShort(), tagname, sizeof( tagname ) ); + pStringPool->GetString( buf.GetShort(), wavname, sizeof( wavname ) ); + + SetUsingRelativeTag( true, tagname, wavname ); + } + + if ( !RestoreFlexAnimationsFromBuffer( buf, pStringPool ) ) + return false; + + if ( GetType() == LOOP ) + { + SetLoopCount( buf.GetChar() ); + } + + if ( GetType() == CChoreoEvent::SPEAK ) + { + SetCloseCaptionType( (CLOSECAPTION)buf.GetChar() ); + char cctoken[ 256 ]; + pStringPool->GetString( buf.GetShort(), cctoken, sizeof( cctoken ) ); + SetCloseCaptionToken( cctoken ); + int flags = buf.GetChar(); + if ( flags & ( 1<<0 ) ) + { + SetUsingCombinedFile( true ); + } + if ( flags & ( 1<<1 ) ) + { + SetCombinedUsingGenderToken( true ); + } + if ( flags & ( 1<<2 ) ) + { + SetSuppressingCaptionAttenuation( true ); + } + } + + return true; +} + +void CCurveData::SaveToBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) +{ + int c = GetCount(); + Assert( c <= 255 ); + buf.PutUnsignedChar( c ); + + for ( int i = 0; i < c; i++ ) + { + CExpressionSample *sample = Get( i ); + buf.PutFloat( sample->time ); + + Assert( sample->value >= 0.0f && sample->value <= 1.0f ); + unsigned char v = sample->value * 255.0f; + buf.PutUnsignedChar( v ); + } +} + +bool CCurveData::RestoreFromBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) +{ + int c = buf.GetUnsignedChar(); + for ( int i = 0; i < c; i++ ) + { + float t, v; + t = buf.GetFloat(); + v = (float)buf.GetUnsignedChar() * 1.0f/255.0f; + + Add( t, v, false ); + } + + return true; +} + +void CChoreoEvent::SaveFlexAnimationsToBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) +{ + int numFlexAnimationTracks = GetNumFlexAnimationTracks(); + Assert( numFlexAnimationTracks <= 255 ); + buf.PutUnsignedChar( numFlexAnimationTracks ); + + for ( int i = 0; i < numFlexAnimationTracks; i++ ) + { + CFlexAnimationTrack *track = GetFlexAnimationTrack( i ); + + buf.PutShort( pStringPool->FindOrAddString( track->GetFlexControllerName() ) ); + + int flags = 0; + flags |= track->IsTrackActive() ? 1<<0 : 0; + flags |= track->IsComboType() ? 1<<1 : 0; + buf.PutUnsignedChar( flags ); + + buf.PutFloat( track->GetMin() ); + buf.PutFloat( track->GetMax() ); + + buf.PutShort( track->GetNumSamples( 0 ) ); + for ( int j = 0 ; j < track->GetNumSamples( 0 ) ; j++ ) + { + CExpressionSample *s = track->GetSample( j, 0 ); + if ( !s ) + continue; + + buf.PutFloat( s->time ); + + Assert( s->value >= 0.0f && s->value <= 1.0f ); + unsigned char v = s->value * 255.0f; + buf.PutUnsignedChar( v ); + + buf.PutUnsignedShort( s->GetCurveType() ); + } + + // Write out combo samples + if ( track->IsComboType() ) + { + int numSamples = track->GetNumSamples( 1 ); + Assert( numSamples <= 32767 ); + buf.PutUnsignedShort( numSamples ); + + for ( int j = 0; j < numSamples; j++ ) + { + CExpressionSample *s = track->GetSample( j, 1 ); + if ( !s ) + continue; + + buf.PutFloat( s->time ); + + Assert( s->value >= 0.0f && s->value <= 1.0f ); + unsigned char v = s->value * 255.0f; + buf.PutUnsignedChar( v ); + + buf.PutUnsignedShort( s->GetCurveType() ); + } + } + } +} + +bool CChoreoEvent::RestoreFlexAnimationsFromBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) +{ + int numTracks = buf.GetUnsignedChar(); + + for ( int i = 0; i < numTracks; i++ ) + { + char name[ 256 ]; + pStringPool->GetString( buf.GetShort(), name, sizeof( name ) ); + + CFlexAnimationTrack *track = AddTrack( name ); + + int flags = buf.GetUnsignedChar(); + track->SetTrackActive( ( flags & ( 1<<0 ) ) ? true : false ); + track->SetComboType( ( flags & ( 1<<1 ) ) ? true : false ); + + track->SetMin( buf.GetFloat() ); + track->SetMax( buf.GetFloat() ); + + int s = buf.GetShort(); + for ( int j = 0; j < s; ++j ) + { + float t, v; + t = buf.GetFloat(); + v = (float)buf.GetUnsignedChar() * 1.0f/255.0f; + + CExpressionSample *pSample = track->AddSample( t, v, 0 ); + pSample->SetCurveType( buf.GetUnsignedShort() ); + } + + if ( track->IsComboType() ) + { + int s = buf.GetUnsignedShort(); + for ( int j = 0; j < s; ++j ) + { + float t, v; + t = buf.GetFloat(); + v = (float)buf.GetUnsignedChar() * 1.0f/255.0f; + + CExpressionSample *pSample = track->AddSample( t, v, 1 ); + pSample->SetCurveType( buf.GetUnsignedShort() ); + } + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Marks the event as enabled/disabled +// Input : state - +//----------------------------------------------------------------------------- +void CChoreoEvent::SetActive( bool state ) +{ + m_bActive = state; +} + +bool CChoreoEvent::GetActive() const +{ + return m_bActive; +} -- cgit v1.2.3