You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4514 lines
114 KiB
4514 lines
114 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "tier0/dbg.h" |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <ctype.h> |
|
#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 %zd 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 %zd 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; |
|
}
|
|
|