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/SpriteTrail.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/SpriteTrail.cpp')
| -rw-r--r-- | mp/src/game/shared/SpriteTrail.cpp | 1324 |
1 files changed, 662 insertions, 662 deletions
diff --git a/mp/src/game/shared/SpriteTrail.cpp b/mp/src/game/shared/SpriteTrail.cpp index 409a2770..217d64cd 100644 --- a/mp/src/game/shared/SpriteTrail.cpp +++ b/mp/src/game/shared/SpriteTrail.cpp @@ -1,662 +1,662 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "SpriteTrail.h"
-
-#ifdef CLIENT_DLL
-
-#include "clientsideeffects.h"
-#include "materialsystem/imaterialsystem.h"
-#include "materialsystem/imesh.h"
-#include "mathlib/vmatrix.h"
-#include "view.h"
-#include "beamdraw.h"
-#include "enginesprite.h"
-#include "tier0/vprof.h"
-
-extern CEngineSprite *Draw_SetSpriteTexture( const model_t *pSpriteModel, int frame, int rendermode );
-
-#endif // CLIENT_DLL
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-//-----------------------------------------------------------------------------
-// constants
-//-----------------------------------------------------------------------------
-#define SCREEN_SPACE_TRAILS 0
-
-
-//-----------------------------------------------------------------------------
-// Save/Restore
-//-----------------------------------------------------------------------------
-#if defined( CLIENT_DLL )
-
-BEGIN_SIMPLE_DATADESC( TrailPoint_t )
-#if SCREEN_SPACE_TRAILS
- DEFINE_FIELD( m_vecScreenPos, FIELD_VECTOR ),
-#else
- DEFINE_FIELD( m_vecScreenPos, FIELD_POSITION_VECTOR ),
-#endif
-
- DEFINE_FIELD( m_flDieTime, FIELD_TIME ),
- DEFINE_FIELD( m_flTexCoord, FIELD_FLOAT ),
- DEFINE_FIELD( m_flWidthVariance,FIELD_FLOAT ),
-END_DATADESC()
-
-#endif
-
-BEGIN_DATADESC( CSpriteTrail )
-
- DEFINE_KEYFIELD( m_flLifeTime, FIELD_FLOAT, "lifetime" ),
- DEFINE_KEYFIELD( m_flStartWidth, FIELD_FLOAT, "startwidth" ),
- DEFINE_KEYFIELD( m_flEndWidth, FIELD_FLOAT, "endwidth" ),
- DEFINE_KEYFIELD( m_iszSpriteName, FIELD_STRING, "spritename" ),
- DEFINE_KEYFIELD( m_bAnimate, FIELD_BOOLEAN, "animate" ),
- DEFINE_FIELD( m_flStartWidthVariance, FIELD_FLOAT ),
- DEFINE_FIELD( m_flTextureRes, FIELD_FLOAT ),
- DEFINE_FIELD( m_flMinFadeLength, FIELD_FLOAT ),
- DEFINE_FIELD( m_vecSkyboxOrigin, FIELD_POSITION_VECTOR ),
- DEFINE_FIELD( m_flSkyboxScale, FIELD_FLOAT ),
-
- // These are client-only
-#if defined( CLIENT_DLL )
- DEFINE_EMBEDDED_AUTO_ARRAY( m_vecSteps ),
- DEFINE_FIELD( m_nFirstStep, FIELD_INTEGER ),
- DEFINE_FIELD( m_nStepCount, FIELD_INTEGER ),
- DEFINE_FIELD( m_flUpdateTime, FIELD_TIME ),
- DEFINE_FIELD( m_vecPrevSkyboxOrigin, FIELD_POSITION_VECTOR ),
- DEFINE_FIELD( m_flPrevSkyboxScale, FIELD_FLOAT ),
- DEFINE_FIELD( m_vecRenderMins, FIELD_VECTOR ),
- DEFINE_FIELD( m_vecRenderMaxs, FIELD_VECTOR ),
-#endif
-
-END_DATADESC()
-
-LINK_ENTITY_TO_CLASS( env_spritetrail, CSpriteTrail );
-
-
-//-----------------------------------------------------------------------------
-// Networking
-//-----------------------------------------------------------------------------
-IMPLEMENT_NETWORKCLASS_ALIASED( SpriteTrail, DT_SpriteTrail );
-
-BEGIN_NETWORK_TABLE( CSpriteTrail, DT_SpriteTrail )
-#if !defined( CLIENT_DLL )
- SendPropFloat( SENDINFO(m_flLifeTime), 0, SPROP_NOSCALE ),
- SendPropFloat( SENDINFO(m_flStartWidth), 0, SPROP_NOSCALE ),
- SendPropFloat( SENDINFO(m_flEndWidth), 0, SPROP_NOSCALE ),
- SendPropFloat( SENDINFO(m_flStartWidthVariance), 0, SPROP_NOSCALE ),
- SendPropFloat( SENDINFO(m_flTextureRes), 0, SPROP_NOSCALE ),
- SendPropFloat( SENDINFO(m_flMinFadeLength), 0, SPROP_NOSCALE ),
- SendPropVector( SENDINFO(m_vecSkyboxOrigin),0, SPROP_NOSCALE ),
- SendPropFloat( SENDINFO(m_flSkyboxScale), 0, SPROP_NOSCALE ),
-#else
- RecvPropFloat( RECVINFO(m_flLifeTime)),
- RecvPropFloat( RECVINFO(m_flStartWidth)),
- RecvPropFloat( RECVINFO(m_flEndWidth)),
- RecvPropFloat( RECVINFO(m_flStartWidthVariance)),
- RecvPropFloat( RECVINFO(m_flTextureRes)),
- RecvPropFloat( RECVINFO(m_flMinFadeLength)),
- RecvPropVector( RECVINFO(m_vecSkyboxOrigin)),
- RecvPropFloat( RECVINFO(m_flSkyboxScale)),
-#endif
-END_NETWORK_TABLE()
-
-//-----------------------------------------------------------------------------
-// Prediction
-//-----------------------------------------------------------------------------
-BEGIN_PREDICTION_DATA( CSpriteTrail )
-END_PREDICTION_DATA()
-
-//-----------------------------------------------------------------------------
-// Constructor
-//-----------------------------------------------------------------------------
-CSpriteTrail::CSpriteTrail( void )
-{
-#ifdef CLIENT_DLL
- m_nFirstStep = 0;
- m_nStepCount = 0;
-#endif
-
- m_flStartWidthVariance = 0;
- m_vecSkyboxOrigin.Init( 0, 0, 0 );
- m_flSkyboxScale = 1.0f;
- m_flEndWidth = -1.0f;
- m_bDrawForMoveParent = true;
-}
-
-void CSpriteTrail::Spawn( void )
-{
-#ifdef CLIENT_DLL
- BaseClass::Spawn();
-#else
-
- if ( GetModelName() != NULL_STRING )
- {
- BaseClass::Spawn();
- return;
- }
-
- SetModelName( m_iszSpriteName );
- BaseClass::Spawn();
-
- SetSolid( SOLID_NONE );
- SetMoveType( MOVETYPE_NOCLIP );
-
- SetCollisionBounds( vec3_origin, vec3_origin );
- TurnOn();
-
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Sets parameters of the sprite trail
-//-----------------------------------------------------------------------------
-void CSpriteTrail::Precache( void )
-{
- BaseClass::Precache();
-
- if ( m_iszSpriteName != NULL_STRING )
- {
- PrecacheModel( STRING(m_iszSpriteName) );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Sets parameters of the sprite trail
-//-----------------------------------------------------------------------------
-void CSpriteTrail::SetLifeTime( float time )
-{
- m_flLifeTime = time;
-}
-
-void CSpriteTrail::SetStartWidth( float flStartWidth )
-{
- m_flStartWidth = flStartWidth;
- m_flStartWidth /= m_flSkyboxScale;
-}
-
-void CSpriteTrail::SetStartWidthVariance( float flStartWidthVariance )
-{
- m_flStartWidthVariance = flStartWidthVariance;
- m_flStartWidthVariance /= m_flSkyboxScale;
-}
-
-void CSpriteTrail::SetEndWidth( float flEndWidth )
-{
- m_flEndWidth = flEndWidth;
- m_flEndWidth /= m_flSkyboxScale;
-}
-
-void CSpriteTrail::SetTextureResolution( float flTexelsPerInch )
-{
- m_flTextureRes = flTexelsPerInch;
- m_flTextureRes *= m_flSkyboxScale;
-}
-
-void CSpriteTrail::SetMinFadeLength( float flMinFadeLength )
-{
- m_flMinFadeLength = flMinFadeLength;
- m_flMinFadeLength /= m_flSkyboxScale;
-}
-
-void CSpriteTrail::SetSkybox( const Vector &vecSkyboxOrigin, float flSkyboxScale )
-{
- m_flTextureRes /= m_flSkyboxScale;
- m_flMinFadeLength *= m_flSkyboxScale;
- m_flStartWidth *= m_flSkyboxScale;
- m_flEndWidth *= m_flSkyboxScale;
- m_flStartWidthVariance *= m_flSkyboxScale;
-
- m_vecSkyboxOrigin = vecSkyboxOrigin;
- m_flSkyboxScale = flSkyboxScale;
-
- m_flTextureRes *= m_flSkyboxScale;
- m_flMinFadeLength /= m_flSkyboxScale;
- m_flStartWidth /= m_flSkyboxScale;
- m_flEndWidth /= m_flSkyboxScale;
- m_flStartWidthVariance /= m_flSkyboxScale;
-
- if ( IsInSkybox() )
- {
- AddEFlags( EFL_IN_SKYBOX );
- }
- else
- {
- RemoveEFlags( EFL_IN_SKYBOX );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Is the trail in the skybox?
-//-----------------------------------------------------------------------------
-bool CSpriteTrail::IsInSkybox() const
-{
- return (m_flSkyboxScale != 1.0f) || (m_vecSkyboxOrigin != vec3_origin);
-}
-
-
-
-#ifdef CLIENT_DLL
-
-
-//-----------------------------------------------------------------------------
-// On data update
-//-----------------------------------------------------------------------------
-void CSpriteTrail::OnPreDataChanged( DataUpdateType_t updateType )
-{
- BaseClass::OnPreDataChanged( updateType );
- m_vecPrevSkyboxOrigin = m_vecSkyboxOrigin;
- m_flPrevSkyboxScale = m_flSkyboxScale;
-}
-
-void CSpriteTrail::OnDataChanged( DataUpdateType_t updateType )
-{
- BaseClass::OnDataChanged( updateType );
- if ( updateType == DATA_UPDATE_CREATED )
- {
- SetNextClientThink( CLIENT_THINK_ALWAYS );
- }
- else
- {
- if ((m_flPrevSkyboxScale != m_flSkyboxScale) || (m_vecPrevSkyboxOrigin != m_vecSkyboxOrigin))
- {
- ConvertSkybox();
- }
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Compute position + bounding box
-//-----------------------------------------------------------------------------
-void CSpriteTrail::ClientThink()
-{
- // Update the trail + bounding box
- UpdateTrail();
- UpdateBoundingBox();
-}
-
-
-//-----------------------------------------------------------------------------
-// Render bounds
-//-----------------------------------------------------------------------------
-void CSpriteTrail::GetRenderBounds( Vector& mins, Vector& maxs )
-{
- mins = m_vecRenderMins;
- maxs = m_vecRenderMaxs;
-}
-
-
-//-----------------------------------------------------------------------------
-// Converts the trail when it changes skyboxes
-//-----------------------------------------------------------------------------
-void CSpriteTrail::ConvertSkybox()
-{
- for ( int i = 0; i < m_nStepCount; ++i )
- {
- // This makes it so that we're always drawing to the current location
- TrailPoint_t *pPoint = GetTrailPoint(i);
-
- VectorSubtract( pPoint->m_vecScreenPos, m_vecPrevSkyboxOrigin, pPoint->m_vecScreenPos );
- pPoint->m_vecScreenPos *= m_flPrevSkyboxScale / m_flSkyboxScale;
- VectorSubtract( pPoint->m_vecScreenPos, m_vecSkyboxOrigin, pPoint->m_vecScreenPos );
- pPoint->m_flWidthVariance *= m_flPrevSkyboxScale / m_flSkyboxScale;
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Gets at the nth item in the list
-//-----------------------------------------------------------------------------
-TrailPoint_t *CSpriteTrail::GetTrailPoint( int n )
-{
- Assert( n < MAX_SPRITE_TRAIL_POINTS );
- COMPILE_TIME_ASSERT( (MAX_SPRITE_TRAIL_POINTS & (MAX_SPRITE_TRAIL_POINTS-1)) == 0 );
- int nIndex = (n + m_nFirstStep) & MAX_SPRITE_TRAIL_MASK;
- return &m_vecSteps[nIndex];
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CSpriteTrail::ComputeScreenPosition( Vector *pScreenPos )
-{
-#if SCREEN_SPACE_TRAILS
- VMatrix viewMatrix;
- materials->GetMatrix( MATERIAL_VIEW, &viewMatrix );
- *pScreenPos = viewMatrix * GetRenderOrigin();
-#else
- *pScreenPos = GetRenderOrigin();
-#endif
-}
-
-
-//-----------------------------------------------------------------------------
-// Compute position + bounding box
-//-----------------------------------------------------------------------------
-void CSpriteTrail::UpdateBoundingBox( void )
-{
- Vector vecRenderOrigin = GetRenderOrigin();
- m_vecRenderMins = vecRenderOrigin;
- m_vecRenderMaxs = vecRenderOrigin;
-
- float flMaxWidth = m_flStartWidth;
- if (( m_flEndWidth >= 0.0f ) && ( m_flEndWidth > m_flStartWidth ))
- {
- flMaxWidth = m_flEndWidth;
- }
-
- Vector mins, maxs;
- for ( int i = 0; i < m_nStepCount; ++i )
- {
- TrailPoint_t *pPoint = GetTrailPoint(i);
-
- float flActualWidth = (flMaxWidth + pPoint->m_flWidthVariance) * 0.5f;
- Vector size( flActualWidth, flActualWidth, flActualWidth );
- VectorSubtract( pPoint->m_vecScreenPos, size, mins );
- VectorAdd( pPoint->m_vecScreenPos, size, maxs );
-
- VectorMin( m_vecRenderMins, mins, m_vecRenderMins );
- VectorMax( m_vecRenderMaxs, maxs, m_vecRenderMaxs );
- }
-
- m_vecRenderMins -= vecRenderOrigin;
- m_vecRenderMaxs -= vecRenderOrigin;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CSpriteTrail::UpdateTrail( void )
-{
- // Can't update too quickly
- if ( m_flUpdateTime > gpGlobals->curtime )
- return;
-
- Vector screenPos;
- ComputeScreenPosition( &screenPos );
- TrailPoint_t *pLast = m_nStepCount ? GetTrailPoint( m_nStepCount-1 ) : NULL;
- if ( ( pLast == NULL ) || ( pLast->m_vecScreenPos.DistToSqr( screenPos ) > 4.0f ) )
- {
- // If we're over our limit, steal the last point and put it up front
- if ( m_nStepCount >= MAX_SPRITE_TRAIL_POINTS )
- {
- --m_nStepCount;
- ++m_nFirstStep;
- }
-
- // Save off its screen position, not its world position
- TrailPoint_t *pNewPoint = GetTrailPoint( m_nStepCount );
- pNewPoint->m_vecScreenPos = screenPos;
- pNewPoint->m_flDieTime = gpGlobals->curtime + m_flLifeTime;
- pNewPoint->m_flWidthVariance = random->RandomFloat( -m_flStartWidthVariance, m_flStartWidthVariance );
- if (pLast)
- {
- pNewPoint->m_flTexCoord = pLast->m_flTexCoord + pLast->m_vecScreenPos.DistTo( screenPos ) * m_flTextureRes;
- }
- else
- {
- pNewPoint->m_flTexCoord = 0.0f;
- }
-
- ++m_nStepCount;
- }
-
- // Don't update again for a bit
- m_flUpdateTime = gpGlobals->curtime + ( m_flLifeTime / (float) MAX_SPRITE_TRAIL_POINTS );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-int CSpriteTrail::DrawModel( int flags )
-{
- VPROF_BUDGET( "CSpriteTrail::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
-
- // Must have at least one point
- if ( m_nStepCount < 1 )
- return 1;
-
- //See if we should draw
- if ( !IsVisible() || ( m_bReadyToDraw == false ) )
- return 0;
-
- CEngineSprite *pSprite = Draw_SetSpriteTexture( GetModel(), m_flFrame, GetRenderMode() );
- if ( pSprite == NULL )
- return 0;
-
- // Specify all the segments.
- CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
- CBeamSegDraw segDraw;
- segDraw.Start( pRenderContext, m_nStepCount + 1, pSprite->GetMaterial( GetRenderMode() ) );
-
- // Setup the first point, always emanating from the attachment point
- TrailPoint_t *pLast = GetTrailPoint( m_nStepCount-1 );
- TrailPoint_t currentPoint;
- currentPoint.m_flDieTime = gpGlobals->curtime + m_flLifeTime;
- ComputeScreenPosition( ¤tPoint.m_vecScreenPos );
- currentPoint.m_flTexCoord = pLast->m_flTexCoord + currentPoint.m_vecScreenPos.DistTo(pLast->m_vecScreenPos) * m_flTextureRes;
- currentPoint.m_flWidthVariance = 0.0f;
-
-#if SCREEN_SPACE_TRAILS
- VMatrix viewMatrix;
- materials->GetMatrix( MATERIAL_VIEW, &viewMatrix );
- viewMatrix = viewMatrix.InverseTR();
-#endif
-
- TrailPoint_t *pPrevPoint = NULL;
- float flTailAlphaDist = m_flMinFadeLength;
- for ( int i = 0; i <= m_nStepCount; ++i )
- {
- // This makes it so that we're always drawing to the current location
- TrailPoint_t *pPoint = (i != m_nStepCount) ? GetTrailPoint(i) : ¤tPoint;
-
- float flLifePerc = (pPoint->m_flDieTime - gpGlobals->curtime) / m_flLifeTime;
- flLifePerc = clamp( flLifePerc, 0.0f, 1.0f );
-
- BeamSeg_t curSeg;
- curSeg.m_vColor.x = (float) m_clrRender->r / 255.0f;
- curSeg.m_vColor.y = (float) m_clrRender->g / 255.0f;
- curSeg.m_vColor.z = (float) m_clrRender->b / 255.0f;
-
- float flAlphaFade = flLifePerc;
- if ( flTailAlphaDist > 0.0f )
- {
- if ( pPrevPoint )
- {
- float flDist = pPoint->m_vecScreenPos.DistTo( pPrevPoint->m_vecScreenPos );
- flTailAlphaDist -= flDist;
- }
-
- if ( flTailAlphaDist > 0.0f )
- {
- float flTailFade = Lerp( (m_flMinFadeLength - flTailAlphaDist) / m_flMinFadeLength, 0.0f, 1.0f );
- if ( flTailFade < flAlphaFade )
- {
- flAlphaFade = flTailFade;
- }
- }
- }
- curSeg.m_flAlpha = ( (float) GetRenderBrightness() / 255.0f ) * flAlphaFade;
-
-#if SCREEN_SPACE_TRAILS
- curSeg.m_vPos = viewMatrix * pPoint->m_vecScreenPos;
-#else
- curSeg.m_vPos = pPoint->m_vecScreenPos;
-#endif
-
- if ( m_flEndWidth >= 0.0f )
- {
- curSeg.m_flWidth = Lerp( flLifePerc, m_flEndWidth.Get(), m_flStartWidth.Get() );
- }
- else
- {
- curSeg.m_flWidth = m_flStartWidth.Get();
- }
- curSeg.m_flWidth += pPoint->m_flWidthVariance;
- if ( curSeg.m_flWidth < 0.0f )
- {
- curSeg.m_flWidth = 0.0f;
- }
-
- curSeg.m_flTexCoord = pPoint->m_flTexCoord;
-
- segDraw.NextSeg( &curSeg );
-
- // See if we're done with this bad boy
- if ( pPoint->m_flDieTime <= gpGlobals->curtime )
- {
- // Push this back onto the top for use
- ++m_nFirstStep;
- --i;
- --m_nStepCount;
- }
-
- pPrevPoint = pPoint;
- }
-
- segDraw.End();
-
- return 1;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Output : Vector const&
-//-----------------------------------------------------------------------------
-const Vector &CSpriteTrail::GetRenderOrigin( void )
-{
- static Vector vOrigin;
- vOrigin = GetAbsOrigin();
-
- if ( m_hAttachedToEntity )
- {
- C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity();
- if ( ent )
- {
- QAngle dummyAngles;
- ent->GetAttachment( m_nAttachment, vOrigin, dummyAngles );
- }
- }
-
- return vOrigin;
-}
-
-const QAngle &CSpriteTrail::GetRenderAngles( void )
-{
- return vec3_angle;
-}
-
-#endif //CLIENT_DLL
-
-#if !defined( CLIENT_DLL )
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pSpriteName -
-// &origin -
-// animate -
-// Output : CSpriteTrail
-//-----------------------------------------------------------------------------
-CSpriteTrail *CSpriteTrail::SpriteTrailCreate( const char *pSpriteName, const Vector &origin, bool animate )
-{
- CSpriteTrail *pSprite = CREATE_ENTITY( CSpriteTrail, "env_spritetrail" );
-
- pSprite->SpriteInit( pSpriteName, origin );
- pSprite->SetSolid( SOLID_NONE );
- pSprite->SetMoveType( MOVETYPE_NOCLIP );
-
- UTIL_SetSize( pSprite, vec3_origin, vec3_origin );
-
- if ( animate )
- {
- pSprite->TurnOn();
- }
-
- return pSprite;
-}
-
-//-----------------------------------------------------------------------------
-//
-//-----------------------------------------------------------------------------
-
-int CSpriteTrail::ShouldTransmit( const CCheckTransmitInfo *pInfo )
-{
- CBaseEntity *pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt );
-
- Assert( pRecipientEntity->IsPlayer() );
-
- CBasePlayer *pRecipientPlayer = static_cast<CBasePlayer*>( pRecipientEntity );
-
- if ( !m_bDrawForMoveParent )
- {
- if ( GetMoveParent() && !GetMoveParent()->IsPlayer() )
- {
- if ( GetMoveParent()->GetMoveParent() == pRecipientPlayer )
- {
- return FL_EDICT_DONTSEND;
- }
- }
- else if ( GetMoveParent() == pRecipientPlayer )
- {
- return FL_EDICT_DONTSEND;
- }
-
- }
-
- return BaseClass::ShouldTransmit( pInfo );
-}
-
-#endif //CLIENT_DLL == false
-
-#if defined( CLIENT_DLL )
-// It's okay to draw attached entities with these sprites.
-const char* g_spriteWhiteList[] =
-{
- "effects/beam001_white.vmt",
- "effects/beam001_red.vmt",
- "effects/beam001_blu.vmt",
-};
-
-//-----------------------------------------------------------------------------
-// Purpose: TF prevents drawing of any entity attached to players that aren't items in the inventory of the player.
-// This is to prevent servers creating fake cosmetic items and attaching them to players.
-//-----------------------------------------------------------------------------
-bool CSpriteTrail::ValidateEntityAttachedToPlayer( bool &bShouldRetry )
-{
- bShouldRetry = false;
- return true;
-
- /*
-#if defined( TF_CLIENT_DLL )
-
- const char *pszModelName = modelinfo->GetModelName( GetModel() );
- if ( pszModelName && pszModelName[0] )
- {
- // We attach sprites directly to players in some cases, such as phase trails on an evading scout
- for ( int i=0; i<ARRAYSIZE( g_spriteWhiteList ); ++i )
- {
- if ( FStrEq( pszModelName, g_spriteWhiteList[i] ) )
- return true;
- }
- }
-
- return false;
-
-#else
- return false;
-#endif
- */
-}
-
-#endif
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "SpriteTrail.h" + +#ifdef CLIENT_DLL + +#include "clientsideeffects.h" +#include "materialsystem/imaterialsystem.h" +#include "materialsystem/imesh.h" +#include "mathlib/vmatrix.h" +#include "view.h" +#include "beamdraw.h" +#include "enginesprite.h" +#include "tier0/vprof.h" + +extern CEngineSprite *Draw_SetSpriteTexture( const model_t *pSpriteModel, int frame, int rendermode ); + +#endif // CLIENT_DLL + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// constants +//----------------------------------------------------------------------------- +#define SCREEN_SPACE_TRAILS 0 + + +//----------------------------------------------------------------------------- +// Save/Restore +//----------------------------------------------------------------------------- +#if defined( CLIENT_DLL ) + +BEGIN_SIMPLE_DATADESC( TrailPoint_t ) +#if SCREEN_SPACE_TRAILS + DEFINE_FIELD( m_vecScreenPos, FIELD_VECTOR ), +#else + DEFINE_FIELD( m_vecScreenPos, FIELD_POSITION_VECTOR ), +#endif + + DEFINE_FIELD( m_flDieTime, FIELD_TIME ), + DEFINE_FIELD( m_flTexCoord, FIELD_FLOAT ), + DEFINE_FIELD( m_flWidthVariance,FIELD_FLOAT ), +END_DATADESC() + +#endif + +BEGIN_DATADESC( CSpriteTrail ) + + DEFINE_KEYFIELD( m_flLifeTime, FIELD_FLOAT, "lifetime" ), + DEFINE_KEYFIELD( m_flStartWidth, FIELD_FLOAT, "startwidth" ), + DEFINE_KEYFIELD( m_flEndWidth, FIELD_FLOAT, "endwidth" ), + DEFINE_KEYFIELD( m_iszSpriteName, FIELD_STRING, "spritename" ), + DEFINE_KEYFIELD( m_bAnimate, FIELD_BOOLEAN, "animate" ), + DEFINE_FIELD( m_flStartWidthVariance, FIELD_FLOAT ), + DEFINE_FIELD( m_flTextureRes, FIELD_FLOAT ), + DEFINE_FIELD( m_flMinFadeLength, FIELD_FLOAT ), + DEFINE_FIELD( m_vecSkyboxOrigin, FIELD_POSITION_VECTOR ), + DEFINE_FIELD( m_flSkyboxScale, FIELD_FLOAT ), + + // These are client-only +#if defined( CLIENT_DLL ) + DEFINE_EMBEDDED_AUTO_ARRAY( m_vecSteps ), + DEFINE_FIELD( m_nFirstStep, FIELD_INTEGER ), + DEFINE_FIELD( m_nStepCount, FIELD_INTEGER ), + DEFINE_FIELD( m_flUpdateTime, FIELD_TIME ), + DEFINE_FIELD( m_vecPrevSkyboxOrigin, FIELD_POSITION_VECTOR ), + DEFINE_FIELD( m_flPrevSkyboxScale, FIELD_FLOAT ), + DEFINE_FIELD( m_vecRenderMins, FIELD_VECTOR ), + DEFINE_FIELD( m_vecRenderMaxs, FIELD_VECTOR ), +#endif + +END_DATADESC() + +LINK_ENTITY_TO_CLASS( env_spritetrail, CSpriteTrail ); + + +//----------------------------------------------------------------------------- +// Networking +//----------------------------------------------------------------------------- +IMPLEMENT_NETWORKCLASS_ALIASED( SpriteTrail, DT_SpriteTrail ); + +BEGIN_NETWORK_TABLE( CSpriteTrail, DT_SpriteTrail ) +#if !defined( CLIENT_DLL ) + SendPropFloat( SENDINFO(m_flLifeTime), 0, SPROP_NOSCALE ), + SendPropFloat( SENDINFO(m_flStartWidth), 0, SPROP_NOSCALE ), + SendPropFloat( SENDINFO(m_flEndWidth), 0, SPROP_NOSCALE ), + SendPropFloat( SENDINFO(m_flStartWidthVariance), 0, SPROP_NOSCALE ), + SendPropFloat( SENDINFO(m_flTextureRes), 0, SPROP_NOSCALE ), + SendPropFloat( SENDINFO(m_flMinFadeLength), 0, SPROP_NOSCALE ), + SendPropVector( SENDINFO(m_vecSkyboxOrigin),0, SPROP_NOSCALE ), + SendPropFloat( SENDINFO(m_flSkyboxScale), 0, SPROP_NOSCALE ), +#else + RecvPropFloat( RECVINFO(m_flLifeTime)), + RecvPropFloat( RECVINFO(m_flStartWidth)), + RecvPropFloat( RECVINFO(m_flEndWidth)), + RecvPropFloat( RECVINFO(m_flStartWidthVariance)), + RecvPropFloat( RECVINFO(m_flTextureRes)), + RecvPropFloat( RECVINFO(m_flMinFadeLength)), + RecvPropVector( RECVINFO(m_vecSkyboxOrigin)), + RecvPropFloat( RECVINFO(m_flSkyboxScale)), +#endif +END_NETWORK_TABLE() + +//----------------------------------------------------------------------------- +// Prediction +//----------------------------------------------------------------------------- +BEGIN_PREDICTION_DATA( CSpriteTrail ) +END_PREDICTION_DATA() + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CSpriteTrail::CSpriteTrail( void ) +{ +#ifdef CLIENT_DLL + m_nFirstStep = 0; + m_nStepCount = 0; +#endif + + m_flStartWidthVariance = 0; + m_vecSkyboxOrigin.Init( 0, 0, 0 ); + m_flSkyboxScale = 1.0f; + m_flEndWidth = -1.0f; + m_bDrawForMoveParent = true; +} + +void CSpriteTrail::Spawn( void ) +{ +#ifdef CLIENT_DLL + BaseClass::Spawn(); +#else + + if ( GetModelName() != NULL_STRING ) + { + BaseClass::Spawn(); + return; + } + + SetModelName( m_iszSpriteName ); + BaseClass::Spawn(); + + SetSolid( SOLID_NONE ); + SetMoveType( MOVETYPE_NOCLIP ); + + SetCollisionBounds( vec3_origin, vec3_origin ); + TurnOn(); + +#endif +} + +//----------------------------------------------------------------------------- +// Sets parameters of the sprite trail +//----------------------------------------------------------------------------- +void CSpriteTrail::Precache( void ) +{ + BaseClass::Precache(); + + if ( m_iszSpriteName != NULL_STRING ) + { + PrecacheModel( STRING(m_iszSpriteName) ); + } +} + +//----------------------------------------------------------------------------- +// Sets parameters of the sprite trail +//----------------------------------------------------------------------------- +void CSpriteTrail::SetLifeTime( float time ) +{ + m_flLifeTime = time; +} + +void CSpriteTrail::SetStartWidth( float flStartWidth ) +{ + m_flStartWidth = flStartWidth; + m_flStartWidth /= m_flSkyboxScale; +} + +void CSpriteTrail::SetStartWidthVariance( float flStartWidthVariance ) +{ + m_flStartWidthVariance = flStartWidthVariance; + m_flStartWidthVariance /= m_flSkyboxScale; +} + +void CSpriteTrail::SetEndWidth( float flEndWidth ) +{ + m_flEndWidth = flEndWidth; + m_flEndWidth /= m_flSkyboxScale; +} + +void CSpriteTrail::SetTextureResolution( float flTexelsPerInch ) +{ + m_flTextureRes = flTexelsPerInch; + m_flTextureRes *= m_flSkyboxScale; +} + +void CSpriteTrail::SetMinFadeLength( float flMinFadeLength ) +{ + m_flMinFadeLength = flMinFadeLength; + m_flMinFadeLength /= m_flSkyboxScale; +} + +void CSpriteTrail::SetSkybox( const Vector &vecSkyboxOrigin, float flSkyboxScale ) +{ + m_flTextureRes /= m_flSkyboxScale; + m_flMinFadeLength *= m_flSkyboxScale; + m_flStartWidth *= m_flSkyboxScale; + m_flEndWidth *= m_flSkyboxScale; + m_flStartWidthVariance *= m_flSkyboxScale; + + m_vecSkyboxOrigin = vecSkyboxOrigin; + m_flSkyboxScale = flSkyboxScale; + + m_flTextureRes *= m_flSkyboxScale; + m_flMinFadeLength /= m_flSkyboxScale; + m_flStartWidth /= m_flSkyboxScale; + m_flEndWidth /= m_flSkyboxScale; + m_flStartWidthVariance /= m_flSkyboxScale; + + if ( IsInSkybox() ) + { + AddEFlags( EFL_IN_SKYBOX ); + } + else + { + RemoveEFlags( EFL_IN_SKYBOX ); + } +} + + +//----------------------------------------------------------------------------- +// Is the trail in the skybox? +//----------------------------------------------------------------------------- +bool CSpriteTrail::IsInSkybox() const +{ + return (m_flSkyboxScale != 1.0f) || (m_vecSkyboxOrigin != vec3_origin); +} + + + +#ifdef CLIENT_DLL + + +//----------------------------------------------------------------------------- +// On data update +//----------------------------------------------------------------------------- +void CSpriteTrail::OnPreDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnPreDataChanged( updateType ); + m_vecPrevSkyboxOrigin = m_vecSkyboxOrigin; + m_flPrevSkyboxScale = m_flSkyboxScale; +} + +void CSpriteTrail::OnDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnDataChanged( updateType ); + if ( updateType == DATA_UPDATE_CREATED ) + { + SetNextClientThink( CLIENT_THINK_ALWAYS ); + } + else + { + if ((m_flPrevSkyboxScale != m_flSkyboxScale) || (m_vecPrevSkyboxOrigin != m_vecSkyboxOrigin)) + { + ConvertSkybox(); + } + } +} + + +//----------------------------------------------------------------------------- +// Compute position + bounding box +//----------------------------------------------------------------------------- +void CSpriteTrail::ClientThink() +{ + // Update the trail + bounding box + UpdateTrail(); + UpdateBoundingBox(); +} + + +//----------------------------------------------------------------------------- +// Render bounds +//----------------------------------------------------------------------------- +void CSpriteTrail::GetRenderBounds( Vector& mins, Vector& maxs ) +{ + mins = m_vecRenderMins; + maxs = m_vecRenderMaxs; +} + + +//----------------------------------------------------------------------------- +// Converts the trail when it changes skyboxes +//----------------------------------------------------------------------------- +void CSpriteTrail::ConvertSkybox() +{ + for ( int i = 0; i < m_nStepCount; ++i ) + { + // This makes it so that we're always drawing to the current location + TrailPoint_t *pPoint = GetTrailPoint(i); + + VectorSubtract( pPoint->m_vecScreenPos, m_vecPrevSkyboxOrigin, pPoint->m_vecScreenPos ); + pPoint->m_vecScreenPos *= m_flPrevSkyboxScale / m_flSkyboxScale; + VectorSubtract( pPoint->m_vecScreenPos, m_vecSkyboxOrigin, pPoint->m_vecScreenPos ); + pPoint->m_flWidthVariance *= m_flPrevSkyboxScale / m_flSkyboxScale; + } +} + + +//----------------------------------------------------------------------------- +// Gets at the nth item in the list +//----------------------------------------------------------------------------- +TrailPoint_t *CSpriteTrail::GetTrailPoint( int n ) +{ + Assert( n < MAX_SPRITE_TRAIL_POINTS ); + COMPILE_TIME_ASSERT( (MAX_SPRITE_TRAIL_POINTS & (MAX_SPRITE_TRAIL_POINTS-1)) == 0 ); + int nIndex = (n + m_nFirstStep) & MAX_SPRITE_TRAIL_MASK; + return &m_vecSteps[nIndex]; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSpriteTrail::ComputeScreenPosition( Vector *pScreenPos ) +{ +#if SCREEN_SPACE_TRAILS + VMatrix viewMatrix; + materials->GetMatrix( MATERIAL_VIEW, &viewMatrix ); + *pScreenPos = viewMatrix * GetRenderOrigin(); +#else + *pScreenPos = GetRenderOrigin(); +#endif +} + + +//----------------------------------------------------------------------------- +// Compute position + bounding box +//----------------------------------------------------------------------------- +void CSpriteTrail::UpdateBoundingBox( void ) +{ + Vector vecRenderOrigin = GetRenderOrigin(); + m_vecRenderMins = vecRenderOrigin; + m_vecRenderMaxs = vecRenderOrigin; + + float flMaxWidth = m_flStartWidth; + if (( m_flEndWidth >= 0.0f ) && ( m_flEndWidth > m_flStartWidth )) + { + flMaxWidth = m_flEndWidth; + } + + Vector mins, maxs; + for ( int i = 0; i < m_nStepCount; ++i ) + { + TrailPoint_t *pPoint = GetTrailPoint(i); + + float flActualWidth = (flMaxWidth + pPoint->m_flWidthVariance) * 0.5f; + Vector size( flActualWidth, flActualWidth, flActualWidth ); + VectorSubtract( pPoint->m_vecScreenPos, size, mins ); + VectorAdd( pPoint->m_vecScreenPos, size, maxs ); + + VectorMin( m_vecRenderMins, mins, m_vecRenderMins ); + VectorMax( m_vecRenderMaxs, maxs, m_vecRenderMaxs ); + } + + m_vecRenderMins -= vecRenderOrigin; + m_vecRenderMaxs -= vecRenderOrigin; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSpriteTrail::UpdateTrail( void ) +{ + // Can't update too quickly + if ( m_flUpdateTime > gpGlobals->curtime ) + return; + + Vector screenPos; + ComputeScreenPosition( &screenPos ); + TrailPoint_t *pLast = m_nStepCount ? GetTrailPoint( m_nStepCount-1 ) : NULL; + if ( ( pLast == NULL ) || ( pLast->m_vecScreenPos.DistToSqr( screenPos ) > 4.0f ) ) + { + // If we're over our limit, steal the last point and put it up front + if ( m_nStepCount >= MAX_SPRITE_TRAIL_POINTS ) + { + --m_nStepCount; + ++m_nFirstStep; + } + + // Save off its screen position, not its world position + TrailPoint_t *pNewPoint = GetTrailPoint( m_nStepCount ); + pNewPoint->m_vecScreenPos = screenPos; + pNewPoint->m_flDieTime = gpGlobals->curtime + m_flLifeTime; + pNewPoint->m_flWidthVariance = random->RandomFloat( -m_flStartWidthVariance, m_flStartWidthVariance ); + if (pLast) + { + pNewPoint->m_flTexCoord = pLast->m_flTexCoord + pLast->m_vecScreenPos.DistTo( screenPos ) * m_flTextureRes; + } + else + { + pNewPoint->m_flTexCoord = 0.0f; + } + + ++m_nStepCount; + } + + // Don't update again for a bit + m_flUpdateTime = gpGlobals->curtime + ( m_flLifeTime / (float) MAX_SPRITE_TRAIL_POINTS ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CSpriteTrail::DrawModel( int flags ) +{ + VPROF_BUDGET( "CSpriteTrail::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); + + // Must have at least one point + if ( m_nStepCount < 1 ) + return 1; + + //See if we should draw + if ( !IsVisible() || ( m_bReadyToDraw == false ) ) + return 0; + + CEngineSprite *pSprite = Draw_SetSpriteTexture( GetModel(), m_flFrame, GetRenderMode() ); + if ( pSprite == NULL ) + return 0; + + // Specify all the segments. + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + CBeamSegDraw segDraw; + segDraw.Start( pRenderContext, m_nStepCount + 1, pSprite->GetMaterial( GetRenderMode() ) ); + + // Setup the first point, always emanating from the attachment point + TrailPoint_t *pLast = GetTrailPoint( m_nStepCount-1 ); + TrailPoint_t currentPoint; + currentPoint.m_flDieTime = gpGlobals->curtime + m_flLifeTime; + ComputeScreenPosition( ¤tPoint.m_vecScreenPos ); + currentPoint.m_flTexCoord = pLast->m_flTexCoord + currentPoint.m_vecScreenPos.DistTo(pLast->m_vecScreenPos) * m_flTextureRes; + currentPoint.m_flWidthVariance = 0.0f; + +#if SCREEN_SPACE_TRAILS + VMatrix viewMatrix; + materials->GetMatrix( MATERIAL_VIEW, &viewMatrix ); + viewMatrix = viewMatrix.InverseTR(); +#endif + + TrailPoint_t *pPrevPoint = NULL; + float flTailAlphaDist = m_flMinFadeLength; + for ( int i = 0; i <= m_nStepCount; ++i ) + { + // This makes it so that we're always drawing to the current location + TrailPoint_t *pPoint = (i != m_nStepCount) ? GetTrailPoint(i) : ¤tPoint; + + float flLifePerc = (pPoint->m_flDieTime - gpGlobals->curtime) / m_flLifeTime; + flLifePerc = clamp( flLifePerc, 0.0f, 1.0f ); + + BeamSeg_t curSeg; + curSeg.m_vColor.x = (float) m_clrRender->r / 255.0f; + curSeg.m_vColor.y = (float) m_clrRender->g / 255.0f; + curSeg.m_vColor.z = (float) m_clrRender->b / 255.0f; + + float flAlphaFade = flLifePerc; + if ( flTailAlphaDist > 0.0f ) + { + if ( pPrevPoint ) + { + float flDist = pPoint->m_vecScreenPos.DistTo( pPrevPoint->m_vecScreenPos ); + flTailAlphaDist -= flDist; + } + + if ( flTailAlphaDist > 0.0f ) + { + float flTailFade = Lerp( (m_flMinFadeLength - flTailAlphaDist) / m_flMinFadeLength, 0.0f, 1.0f ); + if ( flTailFade < flAlphaFade ) + { + flAlphaFade = flTailFade; + } + } + } + curSeg.m_flAlpha = ( (float) GetRenderBrightness() / 255.0f ) * flAlphaFade; + +#if SCREEN_SPACE_TRAILS + curSeg.m_vPos = viewMatrix * pPoint->m_vecScreenPos; +#else + curSeg.m_vPos = pPoint->m_vecScreenPos; +#endif + + if ( m_flEndWidth >= 0.0f ) + { + curSeg.m_flWidth = Lerp( flLifePerc, m_flEndWidth.Get(), m_flStartWidth.Get() ); + } + else + { + curSeg.m_flWidth = m_flStartWidth.Get(); + } + curSeg.m_flWidth += pPoint->m_flWidthVariance; + if ( curSeg.m_flWidth < 0.0f ) + { + curSeg.m_flWidth = 0.0f; + } + + curSeg.m_flTexCoord = pPoint->m_flTexCoord; + + segDraw.NextSeg( &curSeg ); + + // See if we're done with this bad boy + if ( pPoint->m_flDieTime <= gpGlobals->curtime ) + { + // Push this back onto the top for use + ++m_nFirstStep; + --i; + --m_nStepCount; + } + + pPrevPoint = pPoint; + } + + segDraw.End(); + + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Vector const& +//----------------------------------------------------------------------------- +const Vector &CSpriteTrail::GetRenderOrigin( void ) +{ + static Vector vOrigin; + vOrigin = GetAbsOrigin(); + + if ( m_hAttachedToEntity ) + { + C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity(); + if ( ent ) + { + QAngle dummyAngles; + ent->GetAttachment( m_nAttachment, vOrigin, dummyAngles ); + } + } + + return vOrigin; +} + +const QAngle &CSpriteTrail::GetRenderAngles( void ) +{ + return vec3_angle; +} + +#endif //CLIENT_DLL + +#if !defined( CLIENT_DLL ) + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSpriteName - +// &origin - +// animate - +// Output : CSpriteTrail +//----------------------------------------------------------------------------- +CSpriteTrail *CSpriteTrail::SpriteTrailCreate( const char *pSpriteName, const Vector &origin, bool animate ) +{ + CSpriteTrail *pSprite = CREATE_ENTITY( CSpriteTrail, "env_spritetrail" ); + + pSprite->SpriteInit( pSpriteName, origin ); + pSprite->SetSolid( SOLID_NONE ); + pSprite->SetMoveType( MOVETYPE_NOCLIP ); + + UTIL_SetSize( pSprite, vec3_origin, vec3_origin ); + + if ( animate ) + { + pSprite->TurnOn(); + } + + return pSprite; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +int CSpriteTrail::ShouldTransmit( const CCheckTransmitInfo *pInfo ) +{ + CBaseEntity *pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt ); + + Assert( pRecipientEntity->IsPlayer() ); + + CBasePlayer *pRecipientPlayer = static_cast<CBasePlayer*>( pRecipientEntity ); + + if ( !m_bDrawForMoveParent ) + { + if ( GetMoveParent() && !GetMoveParent()->IsPlayer() ) + { + if ( GetMoveParent()->GetMoveParent() == pRecipientPlayer ) + { + return FL_EDICT_DONTSEND; + } + } + else if ( GetMoveParent() == pRecipientPlayer ) + { + return FL_EDICT_DONTSEND; + } + + } + + return BaseClass::ShouldTransmit( pInfo ); +} + +#endif //CLIENT_DLL == false + +#if defined( CLIENT_DLL ) +// It's okay to draw attached entities with these sprites. +const char* g_spriteWhiteList[] = +{ + "effects/beam001_white.vmt", + "effects/beam001_red.vmt", + "effects/beam001_blu.vmt", +}; + +//----------------------------------------------------------------------------- +// Purpose: TF prevents drawing of any entity attached to players that aren't items in the inventory of the player. +// This is to prevent servers creating fake cosmetic items and attaching them to players. +//----------------------------------------------------------------------------- +bool CSpriteTrail::ValidateEntityAttachedToPlayer( bool &bShouldRetry ) +{ + bShouldRetry = false; + return true; + + /* +#if defined( TF_CLIENT_DLL ) + + const char *pszModelName = modelinfo->GetModelName( GetModel() ); + if ( pszModelName && pszModelName[0] ) + { + // We attach sprites directly to players in some cases, such as phase trails on an evading scout + for ( int i=0; i<ARRAYSIZE( g_spriteWhiteList ); ++i ) + { + if ( FStrEq( pszModelName, g_spriteWhiteList[i] ) ) + return true; + } + } + + return false; + +#else + return false; +#endif + */ +} + +#endif |