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/client/c_baseviewmodel.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/client/c_baseviewmodel.cpp')
| -rw-r--r-- | mp/src/game/client/c_baseviewmodel.cpp | 996 |
1 files changed, 498 insertions, 498 deletions
diff --git a/mp/src/game/client/c_baseviewmodel.cpp b/mp/src/game/client/c_baseviewmodel.cpp index 0999fee0..98132bc9 100644 --- a/mp/src/game/client/c_baseviewmodel.cpp +++ b/mp/src/game/client/c_baseviewmodel.cpp @@ -1,498 +1,498 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Client side view model implementation. Responsible for drawing
-// the view model.
-//
-// $NoKeywords: $
-//=============================================================================//
-#include "cbase.h"
-#include "c_baseviewmodel.h"
-#include "model_types.h"
-#include "hud.h"
-#include "view_shared.h"
-#include "iviewrender.h"
-#include "view.h"
-#include "mathlib/vmatrix.h"
-#include "cl_animevent.h"
-#include "eventlist.h"
-#include "tools/bonelist.h"
-#include <KeyValues.h>
-#include "hltvcamera.h"
-
-#if defined( REPLAY_ENABLED )
-#include "replay/replaycamera.h"
-#include "replay/ireplaysystem.h"
-#include "replay/ienginereplay.h"
-#endif
-
-// NVNT haptics system interface
-#include "haptics/ihaptics.h"
-
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#ifdef CSTRIKE_DLL
- ConVar cl_righthand( "cl_righthand", "1", FCVAR_ARCHIVE, "Use right-handed view models." );
-#endif
-
-#ifdef TF_CLIENT_DLL
- ConVar cl_flipviewmodels( "cl_flipviewmodels", "0", FCVAR_USERINFO | FCVAR_ARCHIVE | FCVAR_NOT_CONNECTED, "Flip view models." );
-#endif
-
-void PostToolMessage( HTOOLHANDLE hEntity, KeyValues *msg );
-
-void FormatViewModelAttachment( Vector &vOrigin, bool bInverse )
-{
- // Presumably, SetUpView has been called so we know our FOV and render origin.
- const CViewSetup *pViewSetup = view->GetPlayerViewSetup();
-
- float worldx = tan( pViewSetup->fov * M_PI/360.0 );
- float viewx = tan( pViewSetup->fovViewmodel * M_PI/360.0 );
-
- // aspect ratio cancels out, so only need one factor
- // the difference between the screen coordinates of the 2 systems is the ratio
- // of the coefficients of the projection matrices (tan (fov/2) is that coefficient)
- float factorX = worldx / viewx;
-
- float factorY = factorX;
-
- // Get the coordinates in the viewer's space.
- Vector tmp = vOrigin - pViewSetup->origin;
- Vector vTransformed( MainViewRight().Dot( tmp ), MainViewUp().Dot( tmp ), MainViewForward().Dot( tmp ) );
-
- // Now squash X and Y.
- if ( bInverse )
- {
- if ( factorX != 0 && factorY != 0 )
- {
- vTransformed.x /= factorX;
- vTransformed.y /= factorY;
- }
- else
- {
- vTransformed.x = 0.0f;
- vTransformed.y = 0.0f;
- }
- }
- else
- {
- vTransformed.x *= factorX;
- vTransformed.y *= factorY;
- }
-
-
-
- // Transform back to world space.
- Vector vOut = (MainViewRight() * vTransformed.x) + (MainViewUp() * vTransformed.y) + (MainViewForward() * vTransformed.z);
- vOrigin = pViewSetup->origin + vOut;
-}
-
-
-void C_BaseViewModel::FormatViewModelAttachment( int nAttachment, matrix3x4_t &attachmentToWorld )
-{
- Vector vecOrigin;
- MatrixPosition( attachmentToWorld, vecOrigin );
- ::FormatViewModelAttachment( vecOrigin, false );
- PositionMatrix( vecOrigin, attachmentToWorld );
-}
-
-
-bool C_BaseViewModel::IsViewModel() const
-{
- return true;
-}
-
-void C_BaseViewModel::UncorrectViewModelAttachment( Vector &vOrigin )
-{
- // Unformat the attachment.
- ::FormatViewModelAttachment( vOrigin, true );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose
-//-----------------------------------------------------------------------------
-void C_BaseViewModel::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
-{
- // We override sound requests so that we can play them locally on the owning player
- if ( ( event == AE_CL_PLAYSOUND ) || ( event == CL_EVENT_SOUND ) )
- {
- // Only do this if we're owned by someone
- if ( GetOwner() != NULL )
- {
- CLocalPlayerFilter filter;
- EmitSound( filter, GetOwner()->GetSoundSourceIndex(), options, &GetAbsOrigin() );
- return;
- }
- }
-
- // Otherwise pass the event to our associated weapon
- C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
- if ( pWeapon )
- {
- // NVNT notify the haptics system of our viewmodel's event
- if ( haptics )
- haptics->ProcessHapticEvent(4,"Weapons",pWeapon->GetName(),"AnimationEvents",VarArgs("%i",event));
-
- bool bResult = pWeapon->OnFireEvent( this, origin, angles, event, options );
- if ( !bResult )
- {
- BaseClass::FireEvent( origin, angles, event, options );
- }
- }
-}
-
-bool C_BaseViewModel::Interpolate( float currentTime )
-{
- CStudioHdr *pStudioHdr = GetModelPtr();
- // Make sure we reset our animation information if we've switch sequences
- UpdateAnimationParity();
-
- bool bret = BaseClass::Interpolate( currentTime );
-
- // Hack to extrapolate cycle counter for view model
- float elapsed_time = currentTime - m_flAnimTime;
- C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
-
- // Predicted viewmodels have fixed up interval
- if ( GetPredictable() || IsClientCreated() )
- {
- Assert( pPlayer );
- float curtime = pPlayer ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime;
- elapsed_time = curtime - m_flAnimTime;
- // Adjust for interpolated partial frame
- if ( !engine->IsPaused() )
- {
- elapsed_time += ( gpGlobals->interpolation_amount * TICK_INTERVAL );
- }
- }
-
- // Prediction errors?
- if ( elapsed_time < 0 )
- {
- elapsed_time = 0;
- }
-
- float dt = elapsed_time * GetSequenceCycleRate( pStudioHdr, GetSequence() ) * GetPlaybackRate();
- if ( dt >= 1.0f )
- {
- if ( !IsSequenceLooping( GetSequence() ) )
- {
- dt = 0.999f;
- }
- else
- {
- dt = fmod( dt, 1.0f );
- }
- }
-
- SetCycle( dt );
- return bret;
-}
-
-
-inline bool C_BaseViewModel::ShouldFlipViewModel()
-{
-#ifdef CSTRIKE_DLL
- // If cl_righthand is set, then we want them all right-handed.
- CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
- if ( pWeapon )
- {
- const FileWeaponInfo_t *pInfo = &pWeapon->GetWpnData();
- return pInfo->m_bAllowFlipping && pInfo->m_bBuiltRightHanded != cl_righthand.GetBool();
- }
-#endif
-
-#ifdef TF_CLIENT_DLL
- CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
- if ( pWeapon )
- {
- return pWeapon->m_bFlipViewModel != cl_flipviewmodels.GetBool();
- }
-#endif
-
- return false;
-}
-
-
-void C_BaseViewModel::ApplyBoneMatrixTransform( matrix3x4_t& transform )
-{
- if ( ShouldFlipViewModel() )
- {
- matrix3x4_t viewMatrix, viewMatrixInverse;
-
- // We could get MATERIAL_VIEW here, but this is called sometimes before the renderer
- // has set that matrix. Luckily, this is called AFTER the CViewSetup has been initialized.
- const CViewSetup *pSetup = view->GetPlayerViewSetup();
- AngleMatrix( pSetup->angles, pSetup->origin, viewMatrixInverse );
- MatrixInvert( viewMatrixInverse, viewMatrix );
-
- // Transform into view space.
- matrix3x4_t temp, temp2;
- ConcatTransforms( viewMatrix, transform, temp );
-
- // Flip it along X.
-
- // (This is the slower way to do it, and it equates to negating the top row).
- //matrix3x4_t mScale;
- //SetIdentityMatrix( mScale );
- //mScale[0][0] = 1;
- //mScale[1][1] = -1;
- //mScale[2][2] = 1;
- //ConcatTransforms( mScale, temp, temp2 );
- temp[1][0] = -temp[1][0];
- temp[1][1] = -temp[1][1];
- temp[1][2] = -temp[1][2];
- temp[1][3] = -temp[1][3];
-
- // Transform back out of view space.
- ConcatTransforms( viewMatrixInverse, temp, transform );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: check if weapon viewmodel should be drawn
-//-----------------------------------------------------------------------------
-bool C_BaseViewModel::ShouldDraw()
-{
- if ( engine->IsHLTV() )
- {
- return ( HLTVCamera()->GetMode() == OBS_MODE_IN_EYE &&
- HLTVCamera()->GetPrimaryTarget() == GetOwner() );
- }
-#if defined( REPLAY_ENABLED )
- else if ( g_pEngineClientReplay->IsPlayingReplayDemo() )
- {
- return ( ReplayCamera()->GetMode() == OBS_MODE_IN_EYE &&
- ReplayCamera()->GetPrimaryTarget() == GetOwner() );
- }
-#endif
- else
- {
- return BaseClass::ShouldDraw();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Render the weapon. Draw the Viewmodel if the weapon's being carried
-// by this player, otherwise draw the worldmodel.
-//-----------------------------------------------------------------------------
-int C_BaseViewModel::DrawModel( int flags )
-{
- if ( !m_bReadyToDraw )
- return 0;
-
- if ( flags & STUDIO_RENDER )
- {
- // Determine blending amount and tell engine
- float blend = (float)( GetFxBlend() / 255.0f );
-
- // Totally gone
- if ( blend <= 0.0f )
- return 0;
-
- // Tell engine
- render->SetBlend( blend );
-
- float color[3];
- GetColorModulation( color );
- render->SetColorModulation( color );
- }
-
- C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
- C_BaseCombatWeapon *pWeapon = GetOwningWeapon();
- int ret;
- // If the local player's overriding the viewmodel rendering, let him do it
- if ( pPlayer && pPlayer->IsOverridingViewmodel() )
- {
- ret = pPlayer->DrawOverriddenViewmodel( this, flags );
- }
- else if ( pWeapon && pWeapon->IsOverridingViewmodel() )
- {
- ret = pWeapon->DrawOverriddenViewmodel( this, flags );
- }
- else
- {
- ret = BaseClass::DrawModel( flags );
- }
-
- // Now that we've rendered, reset the animation restart flag
- if ( flags & STUDIO_RENDER )
- {
- if ( m_nOldAnimationParity != m_nAnimationParity )
- {
- m_nOldAnimationParity = m_nAnimationParity;
- }
- // Tell the weapon itself that we've rendered, in case it wants to do something
- if ( pWeapon )
- {
- pWeapon->ViewModelDrawn( this );
- }
- }
-
- return ret;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-int C_BaseViewModel::InternalDrawModel( int flags )
-{
- CMatRenderContextPtr pRenderContext( materials );
- if ( ShouldFlipViewModel() )
- pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
-
- int ret = BaseClass::InternalDrawModel( flags );
-
- pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
-
- return ret;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called by the player when the player's overriding the viewmodel drawing. Avoids infinite recursion.
-//-----------------------------------------------------------------------------
-int C_BaseViewModel::DrawOverriddenViewmodel( int flags )
-{
- return BaseClass::DrawModel( flags );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Output : int
-//-----------------------------------------------------------------------------
-int C_BaseViewModel::GetFxBlend( void )
-{
- // See if the local player wants to override the viewmodel's rendering
- C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
- if ( pPlayer && pPlayer->IsOverridingViewmodel() )
- {
- pPlayer->ComputeFxBlend();
- return pPlayer->GetFxBlend();
- }
-
- C_BaseCombatWeapon *pWeapon = GetOwningWeapon();
- if ( pWeapon && pWeapon->IsOverridingViewmodel() )
- {
- pWeapon->ComputeFxBlend();
- return pWeapon->GetFxBlend();
- }
-
- return BaseClass::GetFxBlend();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool C_BaseViewModel::IsTransparent( void )
-{
- // See if the local player wants to override the viewmodel's rendering
- C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
- if ( pPlayer && pPlayer->IsOverridingViewmodel() )
- {
- return pPlayer->ViewModel_IsTransparent();
- }
-
- C_BaseCombatWeapon *pWeapon = GetOwningWeapon();
- if ( pWeapon && pWeapon->IsOverridingViewmodel() )
- return pWeapon->ViewModel_IsTransparent();
-
- return BaseClass::IsTransparent();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool C_BaseViewModel::UsesPowerOfTwoFrameBufferTexture( void )
-{
- // See if the local player wants to override the viewmodel's rendering
- C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
- if ( pPlayer && pPlayer->IsOverridingViewmodel() )
- {
- return pPlayer->ViewModel_IsUsingFBTexture();
- }
-
- C_BaseCombatWeapon *pWeapon = GetOwningWeapon();
- if ( pWeapon && pWeapon->IsOverridingViewmodel() )
- {
- return pWeapon->ViewModel_IsUsingFBTexture();
- }
-
- return BaseClass::UsesPowerOfTwoFrameBufferTexture();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: If the animation parity of the weapon has changed, we reset cycle to avoid popping
-//-----------------------------------------------------------------------------
-void C_BaseViewModel::UpdateAnimationParity( void )
-{
- C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
-
- // If we're predicting, then we don't use animation parity because we change the animations on the clientside
- // while predicting. When not predicting, only the server changes the animations, so a parity mismatch
- // tells us if we need to reset the animation.
- if ( m_nOldAnimationParity != m_nAnimationParity && !GetPredictable() )
- {
- float curtime = (pPlayer && IsIntermediateDataAllocated()) ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime;
- // FIXME: this is bad
- // Simulate a networked m_flAnimTime and m_flCycle
- // FIXME: Do we need the magic 0.1?
- SetCycle( 0.0f ); // GetSequenceCycleRate( GetSequence() ) * 0.1;
- m_flAnimTime = curtime;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Update global map state based on data received
-// Input : bnewentity -
-//-----------------------------------------------------------------------------
-void C_BaseViewModel::OnDataChanged( DataUpdateType_t updateType )
-{
- SetPredictionEligible( true );
- BaseClass::OnDataChanged(updateType);
-}
-
-void C_BaseViewModel::PostDataUpdate( DataUpdateType_t updateType )
-{
- BaseClass::PostDataUpdate(updateType);
- OnLatchInterpolatedVariables( LATCH_ANIMATION_VAR );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Add entity to visible view models list
-//-----------------------------------------------------------------------------
-void C_BaseViewModel::AddEntity( void )
-{
- // Server says don't interpolate this frame, so set previous info to new info.
- if ( IsNoInterpolationFrame() )
- {
- ResetLatched();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void C_BaseViewModel::GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS])
-{
- BaseClass::GetBoneControllers( controllers );
-
- // Tell the weapon itself that we've rendered, in case it wants to do something
- C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
- if ( pWeapon )
- {
- pWeapon->GetViewmodelBoneControllers( this, controllers );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Output : RenderGroup_t
-//-----------------------------------------------------------------------------
-RenderGroup_t C_BaseViewModel::GetRenderGroup()
-{
- return RENDER_GROUP_VIEW_MODEL_OPAQUE;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Client side view model implementation. Responsible for drawing +// the view model. +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "c_baseviewmodel.h" +#include "model_types.h" +#include "hud.h" +#include "view_shared.h" +#include "iviewrender.h" +#include "view.h" +#include "mathlib/vmatrix.h" +#include "cl_animevent.h" +#include "eventlist.h" +#include "tools/bonelist.h" +#include <KeyValues.h> +#include "hltvcamera.h" + +#if defined( REPLAY_ENABLED ) +#include "replay/replaycamera.h" +#include "replay/ireplaysystem.h" +#include "replay/ienginereplay.h" +#endif + +// NVNT haptics system interface +#include "haptics/ihaptics.h" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifdef CSTRIKE_DLL + ConVar cl_righthand( "cl_righthand", "1", FCVAR_ARCHIVE, "Use right-handed view models." ); +#endif + +#ifdef TF_CLIENT_DLL + ConVar cl_flipviewmodels( "cl_flipviewmodels", "0", FCVAR_USERINFO | FCVAR_ARCHIVE | FCVAR_NOT_CONNECTED, "Flip view models." ); +#endif + +void PostToolMessage( HTOOLHANDLE hEntity, KeyValues *msg ); + +void FormatViewModelAttachment( Vector &vOrigin, bool bInverse ) +{ + // Presumably, SetUpView has been called so we know our FOV and render origin. + const CViewSetup *pViewSetup = view->GetPlayerViewSetup(); + + float worldx = tan( pViewSetup->fov * M_PI/360.0 ); + float viewx = tan( pViewSetup->fovViewmodel * M_PI/360.0 ); + + // aspect ratio cancels out, so only need one factor + // the difference between the screen coordinates of the 2 systems is the ratio + // of the coefficients of the projection matrices (tan (fov/2) is that coefficient) + float factorX = worldx / viewx; + + float factorY = factorX; + + // Get the coordinates in the viewer's space. + Vector tmp = vOrigin - pViewSetup->origin; + Vector vTransformed( MainViewRight().Dot( tmp ), MainViewUp().Dot( tmp ), MainViewForward().Dot( tmp ) ); + + // Now squash X and Y. + if ( bInverse ) + { + if ( factorX != 0 && factorY != 0 ) + { + vTransformed.x /= factorX; + vTransformed.y /= factorY; + } + else + { + vTransformed.x = 0.0f; + vTransformed.y = 0.0f; + } + } + else + { + vTransformed.x *= factorX; + vTransformed.y *= factorY; + } + + + + // Transform back to world space. + Vector vOut = (MainViewRight() * vTransformed.x) + (MainViewUp() * vTransformed.y) + (MainViewForward() * vTransformed.z); + vOrigin = pViewSetup->origin + vOut; +} + + +void C_BaseViewModel::FormatViewModelAttachment( int nAttachment, matrix3x4_t &attachmentToWorld ) +{ + Vector vecOrigin; + MatrixPosition( attachmentToWorld, vecOrigin ); + ::FormatViewModelAttachment( vecOrigin, false ); + PositionMatrix( vecOrigin, attachmentToWorld ); +} + + +bool C_BaseViewModel::IsViewModel() const +{ + return true; +} + +void C_BaseViewModel::UncorrectViewModelAttachment( Vector &vOrigin ) +{ + // Unformat the attachment. + ::FormatViewModelAttachment( vOrigin, true ); +} + + +//----------------------------------------------------------------------------- +// Purpose +//----------------------------------------------------------------------------- +void C_BaseViewModel::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options ) +{ + // We override sound requests so that we can play them locally on the owning player + if ( ( event == AE_CL_PLAYSOUND ) || ( event == CL_EVENT_SOUND ) ) + { + // Only do this if we're owned by someone + if ( GetOwner() != NULL ) + { + CLocalPlayerFilter filter; + EmitSound( filter, GetOwner()->GetSoundSourceIndex(), options, &GetAbsOrigin() ); + return; + } + } + + // Otherwise pass the event to our associated weapon + C_BaseCombatWeapon *pWeapon = GetActiveWeapon(); + if ( pWeapon ) + { + // NVNT notify the haptics system of our viewmodel's event + if ( haptics ) + haptics->ProcessHapticEvent(4,"Weapons",pWeapon->GetName(),"AnimationEvents",VarArgs("%i",event)); + + bool bResult = pWeapon->OnFireEvent( this, origin, angles, event, options ); + if ( !bResult ) + { + BaseClass::FireEvent( origin, angles, event, options ); + } + } +} + +bool C_BaseViewModel::Interpolate( float currentTime ) +{ + CStudioHdr *pStudioHdr = GetModelPtr(); + // Make sure we reset our animation information if we've switch sequences + UpdateAnimationParity(); + + bool bret = BaseClass::Interpolate( currentTime ); + + // Hack to extrapolate cycle counter for view model + float elapsed_time = currentTime - m_flAnimTime; + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + + // Predicted viewmodels have fixed up interval + if ( GetPredictable() || IsClientCreated() ) + { + Assert( pPlayer ); + float curtime = pPlayer ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime; + elapsed_time = curtime - m_flAnimTime; + // Adjust for interpolated partial frame + if ( !engine->IsPaused() ) + { + elapsed_time += ( gpGlobals->interpolation_amount * TICK_INTERVAL ); + } + } + + // Prediction errors? + if ( elapsed_time < 0 ) + { + elapsed_time = 0; + } + + float dt = elapsed_time * GetSequenceCycleRate( pStudioHdr, GetSequence() ) * GetPlaybackRate(); + if ( dt >= 1.0f ) + { + if ( !IsSequenceLooping( GetSequence() ) ) + { + dt = 0.999f; + } + else + { + dt = fmod( dt, 1.0f ); + } + } + + SetCycle( dt ); + return bret; +} + + +inline bool C_BaseViewModel::ShouldFlipViewModel() +{ +#ifdef CSTRIKE_DLL + // If cl_righthand is set, then we want them all right-handed. + CBaseCombatWeapon *pWeapon = m_hWeapon.Get(); + if ( pWeapon ) + { + const FileWeaponInfo_t *pInfo = &pWeapon->GetWpnData(); + return pInfo->m_bAllowFlipping && pInfo->m_bBuiltRightHanded != cl_righthand.GetBool(); + } +#endif + +#ifdef TF_CLIENT_DLL + CBaseCombatWeapon *pWeapon = m_hWeapon.Get(); + if ( pWeapon ) + { + return pWeapon->m_bFlipViewModel != cl_flipviewmodels.GetBool(); + } +#endif + + return false; +} + + +void C_BaseViewModel::ApplyBoneMatrixTransform( matrix3x4_t& transform ) +{ + if ( ShouldFlipViewModel() ) + { + matrix3x4_t viewMatrix, viewMatrixInverse; + + // We could get MATERIAL_VIEW here, but this is called sometimes before the renderer + // has set that matrix. Luckily, this is called AFTER the CViewSetup has been initialized. + const CViewSetup *pSetup = view->GetPlayerViewSetup(); + AngleMatrix( pSetup->angles, pSetup->origin, viewMatrixInverse ); + MatrixInvert( viewMatrixInverse, viewMatrix ); + + // Transform into view space. + matrix3x4_t temp, temp2; + ConcatTransforms( viewMatrix, transform, temp ); + + // Flip it along X. + + // (This is the slower way to do it, and it equates to negating the top row). + //matrix3x4_t mScale; + //SetIdentityMatrix( mScale ); + //mScale[0][0] = 1; + //mScale[1][1] = -1; + //mScale[2][2] = 1; + //ConcatTransforms( mScale, temp, temp2 ); + temp[1][0] = -temp[1][0]; + temp[1][1] = -temp[1][1]; + temp[1][2] = -temp[1][2]; + temp[1][3] = -temp[1][3]; + + // Transform back out of view space. + ConcatTransforms( viewMatrixInverse, temp, transform ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: check if weapon viewmodel should be drawn +//----------------------------------------------------------------------------- +bool C_BaseViewModel::ShouldDraw() +{ + if ( engine->IsHLTV() ) + { + return ( HLTVCamera()->GetMode() == OBS_MODE_IN_EYE && + HLTVCamera()->GetPrimaryTarget() == GetOwner() ); + } +#if defined( REPLAY_ENABLED ) + else if ( g_pEngineClientReplay->IsPlayingReplayDemo() ) + { + return ( ReplayCamera()->GetMode() == OBS_MODE_IN_EYE && + ReplayCamera()->GetPrimaryTarget() == GetOwner() ); + } +#endif + else + { + return BaseClass::ShouldDraw(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Render the weapon. Draw the Viewmodel if the weapon's being carried +// by this player, otherwise draw the worldmodel. +//----------------------------------------------------------------------------- +int C_BaseViewModel::DrawModel( int flags ) +{ + if ( !m_bReadyToDraw ) + return 0; + + if ( flags & STUDIO_RENDER ) + { + // Determine blending amount and tell engine + float blend = (float)( GetFxBlend() / 255.0f ); + + // Totally gone + if ( blend <= 0.0f ) + return 0; + + // Tell engine + render->SetBlend( blend ); + + float color[3]; + GetColorModulation( color ); + render->SetColorModulation( color ); + } + + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + C_BaseCombatWeapon *pWeapon = GetOwningWeapon(); + int ret; + // If the local player's overriding the viewmodel rendering, let him do it + if ( pPlayer && pPlayer->IsOverridingViewmodel() ) + { + ret = pPlayer->DrawOverriddenViewmodel( this, flags ); + } + else if ( pWeapon && pWeapon->IsOverridingViewmodel() ) + { + ret = pWeapon->DrawOverriddenViewmodel( this, flags ); + } + else + { + ret = BaseClass::DrawModel( flags ); + } + + // Now that we've rendered, reset the animation restart flag + if ( flags & STUDIO_RENDER ) + { + if ( m_nOldAnimationParity != m_nAnimationParity ) + { + m_nOldAnimationParity = m_nAnimationParity; + } + // Tell the weapon itself that we've rendered, in case it wants to do something + if ( pWeapon ) + { + pWeapon->ViewModelDrawn( this ); + } + } + + return ret; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int C_BaseViewModel::InternalDrawModel( int flags ) +{ + CMatRenderContextPtr pRenderContext( materials ); + if ( ShouldFlipViewModel() ) + pRenderContext->CullMode( MATERIAL_CULLMODE_CW ); + + int ret = BaseClass::InternalDrawModel( flags ); + + pRenderContext->CullMode( MATERIAL_CULLMODE_CCW ); + + return ret; +} + +//----------------------------------------------------------------------------- +// Purpose: Called by the player when the player's overriding the viewmodel drawing. Avoids infinite recursion. +//----------------------------------------------------------------------------- +int C_BaseViewModel::DrawOverriddenViewmodel( int flags ) +{ + return BaseClass::DrawModel( flags ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int C_BaseViewModel::GetFxBlend( void ) +{ + // See if the local player wants to override the viewmodel's rendering + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( pPlayer && pPlayer->IsOverridingViewmodel() ) + { + pPlayer->ComputeFxBlend(); + return pPlayer->GetFxBlend(); + } + + C_BaseCombatWeapon *pWeapon = GetOwningWeapon(); + if ( pWeapon && pWeapon->IsOverridingViewmodel() ) + { + pWeapon->ComputeFxBlend(); + return pWeapon->GetFxBlend(); + } + + return BaseClass::GetFxBlend(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool C_BaseViewModel::IsTransparent( void ) +{ + // See if the local player wants to override the viewmodel's rendering + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( pPlayer && pPlayer->IsOverridingViewmodel() ) + { + return pPlayer->ViewModel_IsTransparent(); + } + + C_BaseCombatWeapon *pWeapon = GetOwningWeapon(); + if ( pWeapon && pWeapon->IsOverridingViewmodel() ) + return pWeapon->ViewModel_IsTransparent(); + + return BaseClass::IsTransparent(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool C_BaseViewModel::UsesPowerOfTwoFrameBufferTexture( void ) +{ + // See if the local player wants to override the viewmodel's rendering + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( pPlayer && pPlayer->IsOverridingViewmodel() ) + { + return pPlayer->ViewModel_IsUsingFBTexture(); + } + + C_BaseCombatWeapon *pWeapon = GetOwningWeapon(); + if ( pWeapon && pWeapon->IsOverridingViewmodel() ) + { + return pWeapon->ViewModel_IsUsingFBTexture(); + } + + return BaseClass::UsesPowerOfTwoFrameBufferTexture(); +} + +//----------------------------------------------------------------------------- +// Purpose: If the animation parity of the weapon has changed, we reset cycle to avoid popping +//----------------------------------------------------------------------------- +void C_BaseViewModel::UpdateAnimationParity( void ) +{ + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + + // If we're predicting, then we don't use animation parity because we change the animations on the clientside + // while predicting. When not predicting, only the server changes the animations, so a parity mismatch + // tells us if we need to reset the animation. + if ( m_nOldAnimationParity != m_nAnimationParity && !GetPredictable() ) + { + float curtime = (pPlayer && IsIntermediateDataAllocated()) ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime; + // FIXME: this is bad + // Simulate a networked m_flAnimTime and m_flCycle + // FIXME: Do we need the magic 0.1? + SetCycle( 0.0f ); // GetSequenceCycleRate( GetSequence() ) * 0.1; + m_flAnimTime = curtime; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Update global map state based on data received +// Input : bnewentity - +//----------------------------------------------------------------------------- +void C_BaseViewModel::OnDataChanged( DataUpdateType_t updateType ) +{ + SetPredictionEligible( true ); + BaseClass::OnDataChanged(updateType); +} + +void C_BaseViewModel::PostDataUpdate( DataUpdateType_t updateType ) +{ + BaseClass::PostDataUpdate(updateType); + OnLatchInterpolatedVariables( LATCH_ANIMATION_VAR ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Add entity to visible view models list +//----------------------------------------------------------------------------- +void C_BaseViewModel::AddEntity( void ) +{ + // Server says don't interpolate this frame, so set previous info to new info. + if ( IsNoInterpolationFrame() ) + { + ResetLatched(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_BaseViewModel::GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS]) +{ + BaseClass::GetBoneControllers( controllers ); + + // Tell the weapon itself that we've rendered, in case it wants to do something + C_BaseCombatWeapon *pWeapon = GetActiveWeapon(); + if ( pWeapon ) + { + pWeapon->GetViewmodelBoneControllers( this, controllers ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : RenderGroup_t +//----------------------------------------------------------------------------- +RenderGroup_t C_BaseViewModel::GetRenderGroup() +{ + return RENDER_GROUP_VIEW_MODEL_OPAQUE; +} |