Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

232 lines
5.6 KiB

//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
//=============================================================================//
#include "cbase.h"
#include "paint_stream_shared.h"
#include "paint_stream_manager.h"
#include <functional>
#include <algorithm>
#include "paint_power_user.h"
#include "vstdlib/jobthread.h"
#ifdef CLIENT_DLL
#include "collisionutils.h"
#include "c_paint_stream.h"
#include "c_paintblob.h"
#else
#include "paint_stream.h"
#include "cpaintblob.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define VPROF_BUDGETGROUP_PAINTBLOB _T("Paintblob")
ConVar max_sound_channels_per_paint_stream("max_sound_channels_per_paint_stream", "7", FCVAR_REPLICATED | FCVAR_CHEAT);
IMPLEMENT_SHAREDCLASS_DT( CPaintStream )
SharedProp( m_sharedBlobData )
SharedProp( m_sharedBlobDataMutex )
END_SHARED_TABLE()
void CPaintStream::UpdateOnRemove()
{
RemoveAllPaintBlobs();
BaseClass::UpdateOnRemove();
}
void CPaintStream::RemoveAllPaintBlobs( void )
{
#ifdef CLIENT_DLL
RemoveFromLeafSystem();
#endif
}
unsigned int CPaintStream::GetBlobsCount() const
{
return m_blobs.Count();
}
CPaintBlob* CPaintStream::GetBlob( int id )
{
return m_blobs[id];
}
struct ShouldNotDeleteBlob_t : std::unary_function< CPaintBlob*, bool >
{
inline bool operator()( const CPaintBlob* pBlob ) const
{
return !pBlob->ShouldDeleteThis();
}
};
void CPaintStream::RemoveDeadBlobs()
{
CPaintBlob** begin = GetBegin( m_blobs );
CPaintBlob** end = GetEnd( m_blobs );
CPaintBlob** middle = std::partition( begin, end, ShouldNotDeleteBlob_t() );
for( CPaintBlob** i = middle; i != end; ++i )
{
PaintStreamManager.FreeBlob( *i );
}
int numRemoved = end - middle;
m_blobs.RemoveMultipleFromTail( numRemoved );
}
struct TimeElapsed : public std::unary_function<TimeStamp, bool>
{
TimeStamp m_CurrentTime;
TimeElapsed( TimeStamp currentTime ) : m_CurrentTime( currentTime ) {}
inline bool operator()( TimeStamp time ) const
{
return time <= m_CurrentTime;
}
};
void CPaintStream::QueuePaintEffect()
{
#ifdef GAME_DLL
// if not listen server, don't do anything
if ( engine->IsDedicatedServer() )
return;
#else
// if we are listen server, don't do anything on client
if ( engine->IsClientLocalToActiveServer() )
return;
#endif
// Update how many channels are in use
TimeElapsed timeElapsedPred( gpGlobals->curtime );
TimeStamp* begin = m_UsedChannelTimestamps.Base();
TimeStamp* end = begin + m_UsedChannelTimestamps.Count();
TimeStamp* newEnd = std::remove_if( begin, end, timeElapsedPred );
m_UsedChannelTimestamps.RemoveMultipleFromTail( end - newEnd );
// Try to queue up effects for each impact that occurred
PaintImpactEffect const impactEffect = (m_nRenderMode == BLOB_RENDER_BLOBULATOR) ? PAINT_STREAM_IMPACT_EFFECT : PAINT_DRIP_IMPACT_EFFECT;
int const maxChannels = max_sound_channels_per_paint_stream.GetInt();
CUtlVectorFixedGrowable<Vector, 32> soundPositions;
for ( int i = 0; i < m_blobs.Count(); ++i )
{
CPaintBlob *pBlob = m_blobs[i];
if ( pBlob->ShouldPlayEffect() && !pBlob->IsSilent() )
{
PaintStreamManager.CreatePaintImpactParticles( pBlob->GetPosition(), pBlob->GetContactNormal(), m_nPaintType );
if( pBlob->ShouldPlaySound() )
soundPositions.AddToTail( pBlob->GetPosition() );
}
}
if( soundPositions.Count() != 0 )
PaintStreamManager.PlayMultiplePaintImpactSounds( m_UsedChannelTimestamps, maxChannels, soundPositions, impactEffect );
}
void CPaintStream::PreUpdateBlobs()
{
RemoveDeadBlobs();
DebugDrawBlobs();
}
void CPaintStream::PostUpdateBlobs()
{
RemoveTeleportedThisFrameBlobs();
UpdateRenderBoundsAndOriginWorldspace();
QueuePaintEffect();
#ifdef GAME_DLL
AddPaintToDatabase();
UpdateBlobSharedData();
#endif
// reset blobs teleported this frame flag
ResetBlobsTeleportedThisFrame();
}
const Vector& CPaintStream::WorldAlignMins() const
{
return m_vCachedWorldMins;
}
const Vector& CPaintStream::WorldAlignMaxs() const
{
return m_vCachedWorldMaxs;
}
struct TeleportedThisFrameBlob_t : std::unary_function< CPaintBlob*, bool >
{
TeleportedThisFrameBlob_t( int nMaxTeleportationCount ) : m_nMaxTeleportationCount( nMaxTeleportationCount )
{
}
inline bool operator()( const CPaintBlob* pBlob ) const
{
return pBlob->HasBlobTeleportedThisFrame() && ( pBlob->GetTeleportationCount() >= m_nMaxTeleportationCount );
}
int m_nMaxTeleportationCount;
};
//-----------------------------------------------------------------------------------------------
// Purpose: Remove blobs that have teleported this frame if the stream reaches max blob count
//-----------------------------------------------------------------------------------------------
void CPaintStream::RemoveTeleportedThisFrameBlobs()
{
if ( m_nRenderMode == BLOB_RENDER_FAST_SPHERE )
{
Assert( m_blobs.Count() <= m_nMaxBlobCount );
if ( m_blobs.Count() == m_nMaxBlobCount )
{
CPaintBlob** begin = GetBegin( m_blobs );
CPaintBlob** end = GetEnd( m_blobs );
CPaintBlob** middle = std::partition( begin, end, TeleportedThisFrameBlob_t( 4 ) );
for( CPaintBlob** i = begin; i != middle; ++i )
{
PaintStreamManager.FreeBlob( *i );
}
int numRemoved = middle - begin;
m_blobs.RemoveMultipleFromHead( numRemoved );
}
}
}
void CPaintStream::ResetBlobsTeleportedThisFrame()
{
for ( int i=0; i<m_blobs.Count(); ++i )
{
m_blobs[i]->SetBlobTeleportedThisFrame( false );
}
}