diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/shared/point_posecontroller.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/shared/point_posecontroller.cpp')
| -rw-r--r-- | mp/src/game/shared/point_posecontroller.cpp | 1090 |
1 files changed, 545 insertions, 545 deletions
diff --git a/mp/src/game/shared/point_posecontroller.cpp b/mp/src/game/shared/point_posecontroller.cpp index f565013c..660d6248 100644 --- a/mp/src/game/shared/point_posecontroller.cpp +++ b/mp/src/game/shared/point_posecontroller.cpp @@ -1,545 +1,545 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Controls the pose parameters of a model
-//
-//===========================================================================//
-
-
-#include "cbase.h"
-#include "point_posecontroller.h"
-
-
-#ifndef CLIENT_DLL
-//-----------------------------------------------------------------------------
-// SERVER CLASS
-//-----------------------------------------------------------------------------
-
-#include "baseanimating.h"
-#include "props.h"
-
-
-#define MAX_POSE_INTERPOLATION_TIME 10.0f
-#define MAX_POSE_CYCLE_FREQUENCY 10.0f
-#define MAX_POSE_FMOD_RATE 10.0f
-#define MAX_POSE_FMOD_AMPLITUDE 10.0f
-
-
-LINK_ENTITY_TO_CLASS( point_posecontroller, CPoseController );
-
-
-BEGIN_DATADESC( CPoseController )
- DEFINE_AUTO_ARRAY( m_hProps, FIELD_EHANDLE ),
- DEFINE_AUTO_ARRAY( m_chPoseIndex, FIELD_CHARACTER ),
- DEFINE_FIELD( m_bDisablePropLookup, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_bPoseValueParity, FIELD_BOOLEAN ),
- // Keys
- DEFINE_KEYFIELD( m_iszPropName, FIELD_STRING, "PropName" ),
- DEFINE_KEYFIELD( m_iszPoseParameterName, FIELD_STRING, "PoseParameterName" ),
- DEFINE_KEYFIELD( m_fPoseValue, FIELD_FLOAT, "PoseValue" ),
- DEFINE_KEYFIELD( m_fInterpolationTime, FIELD_FLOAT, "InterpolationTime" ),
- DEFINE_KEYFIELD( m_bInterpolationWrap, FIELD_BOOLEAN, "InterpolationWrap" ),
- DEFINE_KEYFIELD( m_fCycleFrequency, FIELD_FLOAT, "CycleFrequency" ),
- DEFINE_KEYFIELD( m_nFModType, FIELD_INTEGER, "FModType" ),
- DEFINE_KEYFIELD( m_fFModTimeOffset, FIELD_FLOAT, "FModTimeOffset" ),
- DEFINE_KEYFIELD( m_fFModRate, FIELD_FLOAT, "FModRate" ),
- DEFINE_KEYFIELD( m_fFModAmplitude, FIELD_FLOAT, "FModAmplitude" ),
- // Functions
- DEFINE_FUNCTION( Think ),
- // Inputs
- DEFINE_INPUTFUNC( FIELD_STRING, "SetPoseParameterName", InputSetPoseParameterName ),
- DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPoseValue", InputSetPoseValue ),
- DEFINE_INPUTFUNC( FIELD_FLOAT, "SetInterpolationTime", InputSetInterpolationTime ),
- DEFINE_INPUTFUNC( FIELD_FLOAT, "SetCycleFrequency", InputSetCycleFrequency ),
- DEFINE_INPUTFUNC( FIELD_INTEGER, "SetFModType", InputSetFModType ),
- DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFModTimeOffset", InputSetFModTimeOffset ),
- DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFModRate", InputSetFModRate ),
- DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFModAmplitude", InputSetFModAmplitude ),
- DEFINE_INPUTFUNC( FIELD_FLOAT, "RandomizeFMod", InputRandomizeFMod ),
- DEFINE_INPUTFUNC( FIELD_VOID, "GetFMod", InputGetFMod ),
-END_DATADESC()
-
-
-IMPLEMENT_SERVERCLASS_ST(CPoseController, DT_PoseController)
- SendPropArray3( SENDINFO_ARRAY3(m_hProps), SendPropEHandle( SENDINFO_ARRAY(m_hProps) ) ),
- SendPropArray3( SENDINFO_ARRAY3(m_chPoseIndex), SendPropInt( SENDINFO_ARRAY(m_chPoseIndex), 5, SPROP_UNSIGNED ) ), // bits sent must be enough to represent MAXSTUDIOPOSEPARAM
- SendPropBool( SENDINFO(m_bPoseValueParity) ),
- SendPropFloat( SENDINFO(m_fPoseValue), 11, 0, 0.0f, 1.0f ),
- SendPropFloat( SENDINFO(m_fInterpolationTime), 11, 0, 0.0f, MAX_POSE_INTERPOLATION_TIME ),
- SendPropBool( SENDINFO(m_bInterpolationWrap) ),
- SendPropFloat( SENDINFO(m_fCycleFrequency), 11, 0, -MAX_POSE_CYCLE_FREQUENCY, MAX_POSE_CYCLE_FREQUENCY ),
- SendPropInt( SENDINFO(m_nFModType), 3, SPROP_UNSIGNED ),
- SendPropFloat( SENDINFO(m_fFModTimeOffset), 11, 0, -1.0f, 1.0f ),
- SendPropFloat( SENDINFO(m_fFModRate), 11, 0, -MAX_POSE_FMOD_RATE, MAX_POSE_FMOD_RATE ),
- SendPropFloat( SENDINFO(m_fFModAmplitude), 11, 0, 0.0f, MAX_POSE_FMOD_AMPLITUDE ),
-END_SEND_TABLE()
-
-
-void CPoseController::Spawn( void )
-{
- BaseClass::Spawn();
-
- // Talk to the client class when data changes
- AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
-
- // Think to refresh the list of models
- SetThink( &CPoseController::Think );
- SetNextThink( gpGlobals->curtime + 1.0 );
-}
-
-void CPoseController::Think( void )
-{
- if ( !m_bDisablePropLookup )
- {
- // Refresh the list of models
- BuildPropList();
-
- SetCurrentPose( m_fPoseValue );
-
- m_bDisablePropLookup = true;
-
- SetNextThink( gpGlobals->curtime + 1.0 );
- }
-}
-
-void CPoseController::BuildPropList( void )
-{
- int iPropNum = 0;
- CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, m_iszPropName );
-
- while ( pEnt && iPropNum < MAX_POSE_CONTROLLED_PROPS )
- {
- CBaseAnimating *pProp = dynamic_cast<CBaseAnimating*>( pEnt );
- if ( pProp )
- {
- CDynamicProp *pDynamicProp = dynamic_cast<CDynamicProp*>( pProp );
- if ( pDynamicProp )
- pDynamicProp->PropSetSequence( 0 );
-
- if ( m_hProps[ iPropNum ] != pProp )
- {
- // Only set new handles (to avoid network spam)
- m_hProps.Set( iPropNum, pProp );
- }
-
- // Update the pose parameter index
- SetPoseIndex( iPropNum, pProp->LookupPoseParameter( m_iszPoseParameterName.ToCStr() ) );
-
- ++iPropNum;
- }
-
- // Get the next entity with specified targetname
- pEnt = gEntList.FindEntityByName( pEnt, m_iszPropName );
- }
-
- // Nullify the remaining handles
- while ( iPropNum < MAX_POSE_CONTROLLED_PROPS )
- {
- if ( m_hProps[ iPropNum ] != NULL )
- m_hProps.Set( iPropNum, NULL );
-
- ++iPropNum;
- }
-
- SetNextThink( gpGlobals->curtime + 1.0 );
-}
-
-void CPoseController::BuildPoseIndexList( void )
-{
- for ( int iPropNum = 0; iPropNum < MAX_POSE_CONTROLLED_PROPS; ++iPropNum )
- {
- CBaseAnimating *pProp = dynamic_cast<CBaseAnimating*>( m_hProps[ iPropNum ].Get() );
-
- if ( pProp )
- {
- // Update the pose parameter index
- SetPoseIndex( iPropNum, pProp->LookupPoseParameter( m_iszPoseParameterName.ToCStr() ) );
- }
- }
-}
-
-void CPoseController::SetPoseIndex( int i, int iValue )
-{
- if ( iValue == -1 )
- {
- // Using this as invalid lets us network less bits
- iValue = MAXSTUDIOPOSEPARAM;
- }
-
- if ( m_chPoseIndex[ i ] != iValue )
- {
- // Only set a new index (to avoid network spam)
- m_chPoseIndex.Set( i, iValue );
- }
-}
-
-float CPoseController::GetPoseValue( void )
-{
- return m_fPoseValue;
-}
-
-void CPoseController::SetProp( CBaseAnimating *pProp )
-{
- // Control a prop directly by pointer
- if ( m_hProps[ 0 ] != pProp )
- {
- // Only set new handles (to avoid network spam)
- m_hProps.Set( 0, pProp );
- }
-
- // Update the pose parameter index
- SetPoseIndex( 0, pProp->LookupPoseParameter( m_iszPoseParameterName.ToCStr() ) );
-
- // Nullify the remaining handles
- for ( int iPropNum = 1; iPropNum < MAX_POSE_CONTROLLED_PROPS; ++iPropNum )
- {
- if ( m_hProps[ iPropNum ] != NULL )
- m_hProps.Set( iPropNum, NULL );
- }
-
- m_bDisablePropLookup = false;
-}
-
-void CPoseController::SetPropName( const char *pName )
-{
- m_iszPropName = MAKE_STRING( pName );
-
- BuildPropList();
-}
-
-void CPoseController::SetPoseParameterName( const char *pName )
-{
- m_iszPoseParameterName = MAKE_STRING( pName );
-
- BuildPoseIndexList();
-}
-
-void CPoseController::SetPoseValue( float fValue )
-{
- m_fPoseValue = clamp( fValue, 0.0f, 1.0f );
-
- // Force the client to set the current pose
- m_bPoseValueParity = !m_bPoseValueParity;
-
- SetCurrentPose( m_fPoseValue );
-}
-
-void CPoseController::SetInterpolationTime( float fValue )
-{
- m_fInterpolationTime = clamp( fValue, 0.0f, MAX_POSE_INTERPOLATION_TIME );
-}
-
-void CPoseController::SetInterpolationWrap( bool bWrap )
-{
- m_bInterpolationWrap = bWrap;
-}
-
-void CPoseController::SetCycleFrequency( float fValue )
-{
- m_fCycleFrequency = clamp( fValue, -MAX_POSE_CYCLE_FREQUENCY, MAX_POSE_CYCLE_FREQUENCY );
-}
-
-void CPoseController::SetFModType( int nType )
-{
- if ( nType < 0 || nType >= POSECONTROLLER_FMODTYPE_TOTAL )
- return;
-
- m_nFModType = static_cast<PoseController_FModType_t>(nType);
-}
-
-void CPoseController::SetFModTimeOffset( float fValue )
-{
- m_fFModTimeOffset = clamp( fValue, -1.0f, 1.0f );
-}
-
-void CPoseController::SetFModRate( float fValue )
-{
- m_fFModRate = clamp( fValue, -MAX_POSE_FMOD_RATE, MAX_POSE_FMOD_RATE );
-}
-
-void CPoseController::SetFModAmplitude( float fValue )
-{
- m_fFModAmplitude = clamp( fValue, 0.0f, MAX_POSE_FMOD_AMPLITUDE );
-}
-
-void CPoseController::RandomizeFMod( float fExtremeness )
-{
- fExtremeness = clamp( fExtremeness, 0.0f, 1.0f );
-
- SetFModType( RandomInt( 1, POSECONTROLLER_FMODTYPE_TOTAL - 1 ) );
- SetFModTimeOffset( RandomFloat( -1.0, 1.0f ) );
- SetFModRate( RandomFloat( fExtremeness * -MAX_POSE_FMOD_RATE, fExtremeness * MAX_POSE_FMOD_RATE ) );
- SetFModAmplitude( RandomFloat( 0.0f, fExtremeness * MAX_POSE_FMOD_AMPLITUDE ) );
-}
-
-void CPoseController::InputSetPoseParameterName( inputdata_t &inputdata )
-{
- SetPoseParameterName( inputdata.value.String() );
-}
-
-void CPoseController::InputSetPoseValue( inputdata_t &inputdata )
-{
- SetPoseValue( inputdata.value.Float() );
-}
-
-void CPoseController::InputSetInterpolationTime( inputdata_t &inputdata )
-{
- SetInterpolationTime( inputdata.value.Float() );
-}
-
-void CPoseController::InputSetCycleFrequency( inputdata_t &inputdata )
-{
- SetCycleFrequency( inputdata.value.Float() );
-}
-
-void CPoseController::InputSetFModType( inputdata_t &inputdata )
-{
- SetFModType( inputdata.value.Int() );
-}
-
-void CPoseController::InputSetFModTimeOffset( inputdata_t &inputdata )
-{
- SetFModTimeOffset( inputdata.value.Float() );
-}
-
-void CPoseController::InputSetFModRate( inputdata_t &inputdata )
-{
- SetFModRate( inputdata.value.Float() );
-}
-
-void CPoseController::InputSetFModAmplitude( inputdata_t &inputdata )
-{
- SetFModAmplitude( inputdata.value.Float() );
-}
-
-void CPoseController::InputRandomizeFMod( inputdata_t &inputdata )
-{
- RandomizeFMod( inputdata.value.Float() );
-}
-
-void CPoseController::InputGetFMod( inputdata_t &inputdata )
-{
- DevMsg( "FMod values for pose controller %s\nTYPE: %i\nTIME OFFSET: %f\nRATE: %f\nAMPLITUDE: %f\n",
- STRING( GetEntityName() ),
- m_nFModType.Get(),
- m_fFModTimeOffset.Get(),
- m_fFModRate.Get(),
- m_fFModAmplitude.Get() );
-}
-
-
-#else //#ifndef CLIENT_DLL
-//-----------------------------------------------------------------------------
-// CLIENT CLASS
-//-----------------------------------------------------------------------------
-
-
-IMPLEMENT_CLIENTCLASS_DT( C_PoseController, DT_PoseController, CPoseController )
- RecvPropArray3( RECVINFO_ARRAY(m_hProps), RecvPropEHandle( RECVINFO(m_hProps[0]) ) ),
- RecvPropArray3( RECVINFO_ARRAY(m_chPoseIndex), RecvPropInt( RECVINFO(m_chPoseIndex[0]) ) ),
- RecvPropBool( RECVINFO(m_bPoseValueParity) ),
- RecvPropFloat( RECVINFO(m_fPoseValue) ),
- RecvPropFloat( RECVINFO(m_fInterpolationTime) ),
- RecvPropBool( RECVINFO(m_bInterpolationWrap) ),
- RecvPropFloat( RECVINFO(m_fCycleFrequency) ),
- RecvPropInt( RECVINFO(m_nFModType) ),
- RecvPropFloat( RECVINFO(m_fFModTimeOffset) ),
- RecvPropFloat( RECVINFO(m_fFModRate) ),
- RecvPropFloat( RECVINFO(m_fFModAmplitude) ),
-END_RECV_TABLE()
-
-
-void C_PoseController::Spawn( void )
-{
- SetThink( &C_PoseController::ClientThink );
- SetNextClientThink( CLIENT_THINK_ALWAYS );
-
- m_fCurrentFMod = 0.0f;
- m_PoseTransitionValue.Init( 0.0f, 0.0f, 0.0f );
-
- BaseClass::Spawn();
-}
-
-void C_PoseController::OnDataChanged( DataUpdateType_t updateType )
-{
- BaseClass::OnDataChanged( updateType );
-
- if ( updateType == DATA_UPDATE_CREATED )
- {
- // Start thinking (Baseclass stops it)
- SetNextClientThink( CLIENT_THINK_ALWAYS );
-
- m_bOldPoseValueParity = m_bPoseValueParity;
- m_fCurrentPoseValue = m_fPoseValue;
-
- SetCurrentPose( m_fCurrentPoseValue );
- }
-
- if ( m_bOldPoseValueParity != m_bPoseValueParity )
- {
- // If the pose value was set directly set the actual pose value
- float fClientPoseValue = m_fCurrentPoseValue + m_PoseTransitionValue.Interp( gpGlobals->curtime );
-
- if ( fClientPoseValue < 0.0f )
- fClientPoseValue += 1.0f;
- else if ( fClientPoseValue > 1.0f )
- fClientPoseValue -= 1.0f;
-
- float fInterpForward = fClientPoseValue - m_fPoseValue;
-
- if ( m_bInterpolationWrap )
- {
- float fInterpBackward = ( fClientPoseValue + ( ( fClientPoseValue < 0.5f ) ? ( 1.0f ) : ( -1.0f ) ) ) - m_fPoseValue;
-
- m_PoseTransitionValue.Init( ( ( fabsf( fInterpForward ) < fabsf( fInterpBackward ) ) ? ( fInterpForward ) : ( fInterpBackward ) ), 0.0f, m_fInterpolationTime );
- }
- else
- {
- m_PoseTransitionValue.Init( fInterpForward, 0.0f, m_fInterpolationTime );
- }
-
- m_bOldPoseValueParity = m_bPoseValueParity;
- m_fCurrentPoseValue = m_fPoseValue;
- }
-}
-
-void C_PoseController::ClientThink( void )
-{
- UpdateModulation();
-
- UpdatePoseCycle( m_fCycleFrequency + m_fCurrentFMod );
-}
-
-void C_PoseController::UpdateModulation( void )
-{
- switch ( m_nFModType )
- {
- case POSECONTROLLER_FMODTYPE_NONE:
- {
- // No modulation
- m_fCurrentFMod = 0.0f;
- break;
- }
-
- case POSECONTROLLER_FMODTYPE_SINE:
- {
- float fCycleTime = m_fFModRate * ( gpGlobals->curtime + m_fFModTimeOffset );
-
- m_fCurrentFMod = m_fFModAmplitude * sinf( fCycleTime * ( 2.0f * M_PI ) );
- break;
- }
-
- case POSECONTROLLER_FMODTYPE_SQUARE:
- {
- float fCycleTime = fabsf( m_fFModRate * 2.0f * ( gpGlobals->curtime + m_fFModTimeOffset ) );
-
- // Separate the current time into integer and decimal
- int iIntegerPortion = static_cast<int>( fCycleTime );
-
- // Find if it's going up or down
- if ( ( iIntegerPortion % 2 ) == 0 )
- m_fCurrentFMod = m_fFModAmplitude;
- else
- m_fCurrentFMod = -m_fFModAmplitude;
-
- break;
- }
-
- case POSECONTROLLER_FMODTYPE_TRIANGLE:
- {
- float fCycleTime = fabsf( m_fFModRate * 4.0f * ( gpGlobals->curtime + m_fFModTimeOffset ) );
-
- // Separate the current time into integer and decimal
- int iIntegerPortion = static_cast<int>( fCycleTime );
- float fDecimalPortion = fCycleTime - static_cast<float>( iIntegerPortion );
-
- // Find if it's going up from 0, down from 1, down from 0, or up from -1
- switch ( iIntegerPortion % 4 )
- {
- case 0:
- m_fCurrentFMod = fDecimalPortion * m_fFModAmplitude;
- break;
- case 1:
- m_fCurrentFMod = ( 1.0f - fDecimalPortion ) * m_fFModAmplitude;
- break;
- case 2:
- m_fCurrentFMod = -fDecimalPortion * m_fFModAmplitude;
- break;
- case 3:
- m_fCurrentFMod = ( -1.0f + fDecimalPortion ) * m_fFModAmplitude;
- break;
- }
-
- break;
- }
-
- case POSECONTROLLER_FMODTYPE_SAWTOOTH:
- {
- float fCycleTime = fabsf( m_fFModRate * 2.0f * ( gpGlobals->curtime + m_fFModTimeOffset ) );
-
- // Separate the current time into integer and decimal
- int iIntegerPortion = static_cast<int>( fCycleTime );
- float fDecimalPortion = fCycleTime - static_cast<float>( iIntegerPortion );
-
- // Find if it's going up from 0 or up from -1
- if ( ( iIntegerPortion % 2 ) == 0 )
- m_fCurrentFMod = fDecimalPortion * m_fFModAmplitude;
- else
- m_fCurrentFMod = ( -1.0f + fDecimalPortion ) * m_fFModAmplitude;
-
- break;
- }
-
- case POSECONTROLLER_FMODTYPE_NOISE:
- {
- // Randomly increase or decrease by the rate
- if ( RandomInt( 0, 1 ) == 0 )
- m_fCurrentFMod += m_fFModRate * gpGlobals->frametime;
- else
- m_fCurrentFMod -= m_fFModRate * gpGlobals->frametime;
-
- m_fCurrentFMod = clamp( m_fCurrentFMod, -m_fFModAmplitude, m_fFModAmplitude );
-
- break;
- }
- }
-}
-
-void C_PoseController::UpdatePoseCycle( float fCycleAmount )
-{
- m_fCurrentPoseValue += fCycleAmount * gpGlobals->frametime;
-
- float fNewPoseValue = m_fCurrentPoseValue + m_PoseTransitionValue.Interp( gpGlobals->curtime );
-
- if ( fNewPoseValue < 0.0f )
- fNewPoseValue += 1.0f;
- else if ( fNewPoseValue > 1.0f )
- fNewPoseValue -= 1.0f;
-
- SetCurrentPose( fNewPoseValue );
-}
-
-#define CPoseController C_PoseController
-#define CBaseAnimating C_BaseAnimating
-
-
-#endif //#ifndef CLIENT_DLL
-
-
-void CPoseController::SetCurrentPose( float fCurrentPoseValue )
-{
- for ( int iPropNum = 0; iPropNum < MAX_POSE_CONTROLLED_PROPS; ++iPropNum )
- {
- // Control each model's pose parameter
- CBaseAnimating *pProp = dynamic_cast<CBaseAnimating*>( m_hProps[ iPropNum ].Get() );
-
- if ( pProp )
- {
- float fPoseValueMin;
- float fPoseValueMax;
-
- // Map to the pose parameter's range
- pProp->GetPoseParameterRange( m_chPoseIndex[ iPropNum ], fPoseValueMin, fPoseValueMax );
- pProp->SetPoseParameter( m_chPoseIndex[ iPropNum ], fPoseValueMin + fCurrentPoseValue * ( fPoseValueMax - fPoseValueMin ) );
- }
- }
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Controls the pose parameters of a model +// +//===========================================================================// + + +#include "cbase.h" +#include "point_posecontroller.h" + + +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// SERVER CLASS +//----------------------------------------------------------------------------- + +#include "baseanimating.h" +#include "props.h" + + +#define MAX_POSE_INTERPOLATION_TIME 10.0f +#define MAX_POSE_CYCLE_FREQUENCY 10.0f +#define MAX_POSE_FMOD_RATE 10.0f +#define MAX_POSE_FMOD_AMPLITUDE 10.0f + + +LINK_ENTITY_TO_CLASS( point_posecontroller, CPoseController ); + + +BEGIN_DATADESC( CPoseController ) + DEFINE_AUTO_ARRAY( m_hProps, FIELD_EHANDLE ), + DEFINE_AUTO_ARRAY( m_chPoseIndex, FIELD_CHARACTER ), + DEFINE_FIELD( m_bDisablePropLookup, FIELD_BOOLEAN ), + DEFINE_FIELD( m_bPoseValueParity, FIELD_BOOLEAN ), + // Keys + DEFINE_KEYFIELD( m_iszPropName, FIELD_STRING, "PropName" ), + DEFINE_KEYFIELD( m_iszPoseParameterName, FIELD_STRING, "PoseParameterName" ), + DEFINE_KEYFIELD( m_fPoseValue, FIELD_FLOAT, "PoseValue" ), + DEFINE_KEYFIELD( m_fInterpolationTime, FIELD_FLOAT, "InterpolationTime" ), + DEFINE_KEYFIELD( m_bInterpolationWrap, FIELD_BOOLEAN, "InterpolationWrap" ), + DEFINE_KEYFIELD( m_fCycleFrequency, FIELD_FLOAT, "CycleFrequency" ), + DEFINE_KEYFIELD( m_nFModType, FIELD_INTEGER, "FModType" ), + DEFINE_KEYFIELD( m_fFModTimeOffset, FIELD_FLOAT, "FModTimeOffset" ), + DEFINE_KEYFIELD( m_fFModRate, FIELD_FLOAT, "FModRate" ), + DEFINE_KEYFIELD( m_fFModAmplitude, FIELD_FLOAT, "FModAmplitude" ), + // Functions + DEFINE_FUNCTION( Think ), + // Inputs + DEFINE_INPUTFUNC( FIELD_STRING, "SetPoseParameterName", InputSetPoseParameterName ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPoseValue", InputSetPoseValue ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetInterpolationTime", InputSetInterpolationTime ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetCycleFrequency", InputSetCycleFrequency ), + DEFINE_INPUTFUNC( FIELD_INTEGER, "SetFModType", InputSetFModType ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFModTimeOffset", InputSetFModTimeOffset ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFModRate", InputSetFModRate ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFModAmplitude", InputSetFModAmplitude ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "RandomizeFMod", InputRandomizeFMod ), + DEFINE_INPUTFUNC( FIELD_VOID, "GetFMod", InputGetFMod ), +END_DATADESC() + + +IMPLEMENT_SERVERCLASS_ST(CPoseController, DT_PoseController) + SendPropArray3( SENDINFO_ARRAY3(m_hProps), SendPropEHandle( SENDINFO_ARRAY(m_hProps) ) ), + SendPropArray3( SENDINFO_ARRAY3(m_chPoseIndex), SendPropInt( SENDINFO_ARRAY(m_chPoseIndex), 5, SPROP_UNSIGNED ) ), // bits sent must be enough to represent MAXSTUDIOPOSEPARAM + SendPropBool( SENDINFO(m_bPoseValueParity) ), + SendPropFloat( SENDINFO(m_fPoseValue), 11, 0, 0.0f, 1.0f ), + SendPropFloat( SENDINFO(m_fInterpolationTime), 11, 0, 0.0f, MAX_POSE_INTERPOLATION_TIME ), + SendPropBool( SENDINFO(m_bInterpolationWrap) ), + SendPropFloat( SENDINFO(m_fCycleFrequency), 11, 0, -MAX_POSE_CYCLE_FREQUENCY, MAX_POSE_CYCLE_FREQUENCY ), + SendPropInt( SENDINFO(m_nFModType), 3, SPROP_UNSIGNED ), + SendPropFloat( SENDINFO(m_fFModTimeOffset), 11, 0, -1.0f, 1.0f ), + SendPropFloat( SENDINFO(m_fFModRate), 11, 0, -MAX_POSE_FMOD_RATE, MAX_POSE_FMOD_RATE ), + SendPropFloat( SENDINFO(m_fFModAmplitude), 11, 0, 0.0f, MAX_POSE_FMOD_AMPLITUDE ), +END_SEND_TABLE() + + +void CPoseController::Spawn( void ) +{ + BaseClass::Spawn(); + + // Talk to the client class when data changes + AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); + + // Think to refresh the list of models + SetThink( &CPoseController::Think ); + SetNextThink( gpGlobals->curtime + 1.0 ); +} + +void CPoseController::Think( void ) +{ + if ( !m_bDisablePropLookup ) + { + // Refresh the list of models + BuildPropList(); + + SetCurrentPose( m_fPoseValue ); + + m_bDisablePropLookup = true; + + SetNextThink( gpGlobals->curtime + 1.0 ); + } +} + +void CPoseController::BuildPropList( void ) +{ + int iPropNum = 0; + CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, m_iszPropName ); + + while ( pEnt && iPropNum < MAX_POSE_CONTROLLED_PROPS ) + { + CBaseAnimating *pProp = dynamic_cast<CBaseAnimating*>( pEnt ); + if ( pProp ) + { + CDynamicProp *pDynamicProp = dynamic_cast<CDynamicProp*>( pProp ); + if ( pDynamicProp ) + pDynamicProp->PropSetSequence( 0 ); + + if ( m_hProps[ iPropNum ] != pProp ) + { + // Only set new handles (to avoid network spam) + m_hProps.Set( iPropNum, pProp ); + } + + // Update the pose parameter index + SetPoseIndex( iPropNum, pProp->LookupPoseParameter( m_iszPoseParameterName.ToCStr() ) ); + + ++iPropNum; + } + + // Get the next entity with specified targetname + pEnt = gEntList.FindEntityByName( pEnt, m_iszPropName ); + } + + // Nullify the remaining handles + while ( iPropNum < MAX_POSE_CONTROLLED_PROPS ) + { + if ( m_hProps[ iPropNum ] != NULL ) + m_hProps.Set( iPropNum, NULL ); + + ++iPropNum; + } + + SetNextThink( gpGlobals->curtime + 1.0 ); +} + +void CPoseController::BuildPoseIndexList( void ) +{ + for ( int iPropNum = 0; iPropNum < MAX_POSE_CONTROLLED_PROPS; ++iPropNum ) + { + CBaseAnimating *pProp = dynamic_cast<CBaseAnimating*>( m_hProps[ iPropNum ].Get() ); + + if ( pProp ) + { + // Update the pose parameter index + SetPoseIndex( iPropNum, pProp->LookupPoseParameter( m_iszPoseParameterName.ToCStr() ) ); + } + } +} + +void CPoseController::SetPoseIndex( int i, int iValue ) +{ + if ( iValue == -1 ) + { + // Using this as invalid lets us network less bits + iValue = MAXSTUDIOPOSEPARAM; + } + + if ( m_chPoseIndex[ i ] != iValue ) + { + // Only set a new index (to avoid network spam) + m_chPoseIndex.Set( i, iValue ); + } +} + +float CPoseController::GetPoseValue( void ) +{ + return m_fPoseValue; +} + +void CPoseController::SetProp( CBaseAnimating *pProp ) +{ + // Control a prop directly by pointer + if ( m_hProps[ 0 ] != pProp ) + { + // Only set new handles (to avoid network spam) + m_hProps.Set( 0, pProp ); + } + + // Update the pose parameter index + SetPoseIndex( 0, pProp->LookupPoseParameter( m_iszPoseParameterName.ToCStr() ) ); + + // Nullify the remaining handles + for ( int iPropNum = 1; iPropNum < MAX_POSE_CONTROLLED_PROPS; ++iPropNum ) + { + if ( m_hProps[ iPropNum ] != NULL ) + m_hProps.Set( iPropNum, NULL ); + } + + m_bDisablePropLookup = false; +} + +void CPoseController::SetPropName( const char *pName ) +{ + m_iszPropName = MAKE_STRING( pName ); + + BuildPropList(); +} + +void CPoseController::SetPoseParameterName( const char *pName ) +{ + m_iszPoseParameterName = MAKE_STRING( pName ); + + BuildPoseIndexList(); +} + +void CPoseController::SetPoseValue( float fValue ) +{ + m_fPoseValue = clamp( fValue, 0.0f, 1.0f ); + + // Force the client to set the current pose + m_bPoseValueParity = !m_bPoseValueParity; + + SetCurrentPose( m_fPoseValue ); +} + +void CPoseController::SetInterpolationTime( float fValue ) +{ + m_fInterpolationTime = clamp( fValue, 0.0f, MAX_POSE_INTERPOLATION_TIME ); +} + +void CPoseController::SetInterpolationWrap( bool bWrap ) +{ + m_bInterpolationWrap = bWrap; +} + +void CPoseController::SetCycleFrequency( float fValue ) +{ + m_fCycleFrequency = clamp( fValue, -MAX_POSE_CYCLE_FREQUENCY, MAX_POSE_CYCLE_FREQUENCY ); +} + +void CPoseController::SetFModType( int nType ) +{ + if ( nType < 0 || nType >= POSECONTROLLER_FMODTYPE_TOTAL ) + return; + + m_nFModType = static_cast<PoseController_FModType_t>(nType); +} + +void CPoseController::SetFModTimeOffset( float fValue ) +{ + m_fFModTimeOffset = clamp( fValue, -1.0f, 1.0f ); +} + +void CPoseController::SetFModRate( float fValue ) +{ + m_fFModRate = clamp( fValue, -MAX_POSE_FMOD_RATE, MAX_POSE_FMOD_RATE ); +} + +void CPoseController::SetFModAmplitude( float fValue ) +{ + m_fFModAmplitude = clamp( fValue, 0.0f, MAX_POSE_FMOD_AMPLITUDE ); +} + +void CPoseController::RandomizeFMod( float fExtremeness ) +{ + fExtremeness = clamp( fExtremeness, 0.0f, 1.0f ); + + SetFModType( RandomInt( 1, POSECONTROLLER_FMODTYPE_TOTAL - 1 ) ); + SetFModTimeOffset( RandomFloat( -1.0, 1.0f ) ); + SetFModRate( RandomFloat( fExtremeness * -MAX_POSE_FMOD_RATE, fExtremeness * MAX_POSE_FMOD_RATE ) ); + SetFModAmplitude( RandomFloat( 0.0f, fExtremeness * MAX_POSE_FMOD_AMPLITUDE ) ); +} + +void CPoseController::InputSetPoseParameterName( inputdata_t &inputdata ) +{ + SetPoseParameterName( inputdata.value.String() ); +} + +void CPoseController::InputSetPoseValue( inputdata_t &inputdata ) +{ + SetPoseValue( inputdata.value.Float() ); +} + +void CPoseController::InputSetInterpolationTime( inputdata_t &inputdata ) +{ + SetInterpolationTime( inputdata.value.Float() ); +} + +void CPoseController::InputSetCycleFrequency( inputdata_t &inputdata ) +{ + SetCycleFrequency( inputdata.value.Float() ); +} + +void CPoseController::InputSetFModType( inputdata_t &inputdata ) +{ + SetFModType( inputdata.value.Int() ); +} + +void CPoseController::InputSetFModTimeOffset( inputdata_t &inputdata ) +{ + SetFModTimeOffset( inputdata.value.Float() ); +} + +void CPoseController::InputSetFModRate( inputdata_t &inputdata ) +{ + SetFModRate( inputdata.value.Float() ); +} + +void CPoseController::InputSetFModAmplitude( inputdata_t &inputdata ) +{ + SetFModAmplitude( inputdata.value.Float() ); +} + +void CPoseController::InputRandomizeFMod( inputdata_t &inputdata ) +{ + RandomizeFMod( inputdata.value.Float() ); +} + +void CPoseController::InputGetFMod( inputdata_t &inputdata ) +{ + DevMsg( "FMod values for pose controller %s\nTYPE: %i\nTIME OFFSET: %f\nRATE: %f\nAMPLITUDE: %f\n", + STRING( GetEntityName() ), + m_nFModType.Get(), + m_fFModTimeOffset.Get(), + m_fFModRate.Get(), + m_fFModAmplitude.Get() ); +} + + +#else //#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// CLIENT CLASS +//----------------------------------------------------------------------------- + + +IMPLEMENT_CLIENTCLASS_DT( C_PoseController, DT_PoseController, CPoseController ) + RecvPropArray3( RECVINFO_ARRAY(m_hProps), RecvPropEHandle( RECVINFO(m_hProps[0]) ) ), + RecvPropArray3( RECVINFO_ARRAY(m_chPoseIndex), RecvPropInt( RECVINFO(m_chPoseIndex[0]) ) ), + RecvPropBool( RECVINFO(m_bPoseValueParity) ), + RecvPropFloat( RECVINFO(m_fPoseValue) ), + RecvPropFloat( RECVINFO(m_fInterpolationTime) ), + RecvPropBool( RECVINFO(m_bInterpolationWrap) ), + RecvPropFloat( RECVINFO(m_fCycleFrequency) ), + RecvPropInt( RECVINFO(m_nFModType) ), + RecvPropFloat( RECVINFO(m_fFModTimeOffset) ), + RecvPropFloat( RECVINFO(m_fFModRate) ), + RecvPropFloat( RECVINFO(m_fFModAmplitude) ), +END_RECV_TABLE() + + +void C_PoseController::Spawn( void ) +{ + SetThink( &C_PoseController::ClientThink ); + SetNextClientThink( CLIENT_THINK_ALWAYS ); + + m_fCurrentFMod = 0.0f; + m_PoseTransitionValue.Init( 0.0f, 0.0f, 0.0f ); + + BaseClass::Spawn(); +} + +void C_PoseController::OnDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnDataChanged( updateType ); + + if ( updateType == DATA_UPDATE_CREATED ) + { + // Start thinking (Baseclass stops it) + SetNextClientThink( CLIENT_THINK_ALWAYS ); + + m_bOldPoseValueParity = m_bPoseValueParity; + m_fCurrentPoseValue = m_fPoseValue; + + SetCurrentPose( m_fCurrentPoseValue ); + } + + if ( m_bOldPoseValueParity != m_bPoseValueParity ) + { + // If the pose value was set directly set the actual pose value + float fClientPoseValue = m_fCurrentPoseValue + m_PoseTransitionValue.Interp( gpGlobals->curtime ); + + if ( fClientPoseValue < 0.0f ) + fClientPoseValue += 1.0f; + else if ( fClientPoseValue > 1.0f ) + fClientPoseValue -= 1.0f; + + float fInterpForward = fClientPoseValue - m_fPoseValue; + + if ( m_bInterpolationWrap ) + { + float fInterpBackward = ( fClientPoseValue + ( ( fClientPoseValue < 0.5f ) ? ( 1.0f ) : ( -1.0f ) ) ) - m_fPoseValue; + + m_PoseTransitionValue.Init( ( ( fabsf( fInterpForward ) < fabsf( fInterpBackward ) ) ? ( fInterpForward ) : ( fInterpBackward ) ), 0.0f, m_fInterpolationTime ); + } + else + { + m_PoseTransitionValue.Init( fInterpForward, 0.0f, m_fInterpolationTime ); + } + + m_bOldPoseValueParity = m_bPoseValueParity; + m_fCurrentPoseValue = m_fPoseValue; + } +} + +void C_PoseController::ClientThink( void ) +{ + UpdateModulation(); + + UpdatePoseCycle( m_fCycleFrequency + m_fCurrentFMod ); +} + +void C_PoseController::UpdateModulation( void ) +{ + switch ( m_nFModType ) + { + case POSECONTROLLER_FMODTYPE_NONE: + { + // No modulation + m_fCurrentFMod = 0.0f; + break; + } + + case POSECONTROLLER_FMODTYPE_SINE: + { + float fCycleTime = m_fFModRate * ( gpGlobals->curtime + m_fFModTimeOffset ); + + m_fCurrentFMod = m_fFModAmplitude * sinf( fCycleTime * ( 2.0f * M_PI ) ); + break; + } + + case POSECONTROLLER_FMODTYPE_SQUARE: + { + float fCycleTime = fabsf( m_fFModRate * 2.0f * ( gpGlobals->curtime + m_fFModTimeOffset ) ); + + // Separate the current time into integer and decimal + int iIntegerPortion = static_cast<int>( fCycleTime ); + + // Find if it's going up or down + if ( ( iIntegerPortion % 2 ) == 0 ) + m_fCurrentFMod = m_fFModAmplitude; + else + m_fCurrentFMod = -m_fFModAmplitude; + + break; + } + + case POSECONTROLLER_FMODTYPE_TRIANGLE: + { + float fCycleTime = fabsf( m_fFModRate * 4.0f * ( gpGlobals->curtime + m_fFModTimeOffset ) ); + + // Separate the current time into integer and decimal + int iIntegerPortion = static_cast<int>( fCycleTime ); + float fDecimalPortion = fCycleTime - static_cast<float>( iIntegerPortion ); + + // Find if it's going up from 0, down from 1, down from 0, or up from -1 + switch ( iIntegerPortion % 4 ) + { + case 0: + m_fCurrentFMod = fDecimalPortion * m_fFModAmplitude; + break; + case 1: + m_fCurrentFMod = ( 1.0f - fDecimalPortion ) * m_fFModAmplitude; + break; + case 2: + m_fCurrentFMod = -fDecimalPortion * m_fFModAmplitude; + break; + case 3: + m_fCurrentFMod = ( -1.0f + fDecimalPortion ) * m_fFModAmplitude; + break; + } + + break; + } + + case POSECONTROLLER_FMODTYPE_SAWTOOTH: + { + float fCycleTime = fabsf( m_fFModRate * 2.0f * ( gpGlobals->curtime + m_fFModTimeOffset ) ); + + // Separate the current time into integer and decimal + int iIntegerPortion = static_cast<int>( fCycleTime ); + float fDecimalPortion = fCycleTime - static_cast<float>( iIntegerPortion ); + + // Find if it's going up from 0 or up from -1 + if ( ( iIntegerPortion % 2 ) == 0 ) + m_fCurrentFMod = fDecimalPortion * m_fFModAmplitude; + else + m_fCurrentFMod = ( -1.0f + fDecimalPortion ) * m_fFModAmplitude; + + break; + } + + case POSECONTROLLER_FMODTYPE_NOISE: + { + // Randomly increase or decrease by the rate + if ( RandomInt( 0, 1 ) == 0 ) + m_fCurrentFMod += m_fFModRate * gpGlobals->frametime; + else + m_fCurrentFMod -= m_fFModRate * gpGlobals->frametime; + + m_fCurrentFMod = clamp( m_fCurrentFMod, -m_fFModAmplitude, m_fFModAmplitude ); + + break; + } + } +} + +void C_PoseController::UpdatePoseCycle( float fCycleAmount ) +{ + m_fCurrentPoseValue += fCycleAmount * gpGlobals->frametime; + + float fNewPoseValue = m_fCurrentPoseValue + m_PoseTransitionValue.Interp( gpGlobals->curtime ); + + if ( fNewPoseValue < 0.0f ) + fNewPoseValue += 1.0f; + else if ( fNewPoseValue > 1.0f ) + fNewPoseValue -= 1.0f; + + SetCurrentPose( fNewPoseValue ); +} + +#define CPoseController C_PoseController +#define CBaseAnimating C_BaseAnimating + + +#endif //#ifndef CLIENT_DLL + + +void CPoseController::SetCurrentPose( float fCurrentPoseValue ) +{ + for ( int iPropNum = 0; iPropNum < MAX_POSE_CONTROLLED_PROPS; ++iPropNum ) + { + // Control each model's pose parameter + CBaseAnimating *pProp = dynamic_cast<CBaseAnimating*>( m_hProps[ iPropNum ].Get() ); + + if ( pProp ) + { + float fPoseValueMin; + float fPoseValueMax; + + // Map to the pose parameter's range + pProp->GetPoseParameterRange( m_chPoseIndex[ iPropNum ], fPoseValueMin, fPoseValueMax ); + pProp->SetPoseParameter( m_chPoseIndex[ iPropNum ], fPoseValueMin + fCurrentPoseValue * ( fPoseValueMax - fPoseValueMin ) ); + } + } +} |