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.
793 lines
24 KiB
793 lines
24 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
#include "cbase.h" |
|
#include "toolframework/itoolentity.h" |
|
#include "tier1/KeyValues.h" |
|
#include "Sprite.h" |
|
#include "enginesprite.h" |
|
#include "toolframework_client.h" |
|
#include "particles/particles.h" |
|
#include "particle_parse.h" |
|
#include "rendertexture.h" |
|
|
|
#ifdef PORTAL |
|
#include "PortalRender.h" |
|
#endif |
|
|
|
#pragma warning( disable: 4355 ) // warning C4355: 'this' : used in base member initializer list |
|
|
|
class CClientTools; |
|
|
|
void DrawSpriteModel( IClientEntity *baseentity, CEngineSprite *psprite, |
|
const Vector &origin, float fscale, float frame, |
|
int rendermode, int r, int g, int b, int a, |
|
const Vector& forward, const Vector& right, const Vector& up, float flHDRColorScale = 1.0f ); |
|
float StandardGlowBlend( const pixelvis_queryparams_t ¶ms, pixelvis_handle_t *queryHandle, |
|
int rendermode, int renderfx, int alpha, float *pscale ); |
|
|
|
|
|
// Interface from engine to tools for manipulating entities |
|
class CClientTools : public IClientTools, public IClientEntityListener |
|
{ |
|
public: |
|
CClientTools(); |
|
|
|
virtual HTOOLHANDLE AttachToEntity( EntitySearchResult entityToAttach ); |
|
virtual void DetachFromEntity( EntitySearchResult entityToDetach ); |
|
virtual bool IsValidHandle( HTOOLHANDLE handle ); |
|
|
|
virtual int GetNumRecordables(); |
|
virtual HTOOLHANDLE GetRecordable( int index ); |
|
|
|
// Iterates through ALL entities (separate list for client vs. server) |
|
virtual EntitySearchResult NextEntity( EntitySearchResult currentEnt ); |
|
|
|
// Use this to turn on/off the presence of an underlying game entity |
|
virtual void SetEnabled( HTOOLHANDLE handle, bool enabled ); |
|
|
|
virtual void SetRecording( HTOOLHANDLE handle, bool recording ); |
|
virtual bool ShouldRecord( HTOOLHANDLE handle ); |
|
|
|
virtual int GetModelIndex( HTOOLHANDLE handle ); |
|
virtual const char* GetModelName ( HTOOLHANDLE handle ); |
|
virtual const char* GetClassname ( HTOOLHANDLE handle ); |
|
|
|
virtual HTOOLHANDLE GetToolHandleForEntityByIndex( int entindex ); |
|
|
|
virtual void AddClientRenderable( IClientRenderable *pRenderable, int renderGroup ); |
|
virtual void RemoveClientRenderable( IClientRenderable *pRenderable ); |
|
virtual void SetRenderGroup( IClientRenderable *pRenderable, int renderGroup ); |
|
virtual void MarkClientRenderableDirty( IClientRenderable *pRenderable ); |
|
|
|
virtual bool DrawSprite( IClientRenderable *pRenderable, |
|
float scale, float frame, |
|
int rendermode, int renderfx, |
|
const Color &color, float flProxyRadius, int *pVisHandle ); |
|
|
|
virtual bool GetLocalPlayerEyePosition( Vector& org, QAngle& ang, float &fov ); |
|
virtual EntitySearchResult GetLocalPlayer(); |
|
|
|
virtual ClientShadowHandle_t CreateShadow( CBaseHandle h, int nFlags ); |
|
virtual void DestroyShadow( ClientShadowHandle_t h ); |
|
virtual ClientShadowHandle_t CreateFlashlight( const FlashlightState_t &lightState ); |
|
virtual void DestroyFlashlight( ClientShadowHandle_t h ); |
|
virtual void UpdateFlashlightState( ClientShadowHandle_t h, const FlashlightState_t &flashlightState ); |
|
virtual void AddToDirtyShadowList( ClientShadowHandle_t h, bool force = false ); |
|
virtual void MarkRenderToTextureShadowDirty( ClientShadowHandle_t h ); |
|
virtual void UpdateProjectedTexture( ClientShadowHandle_t h, bool bForce ); |
|
|
|
// Global toggle for recording |
|
virtual void EnableRecordingMode( bool bEnable ); |
|
virtual bool IsInRecordingMode() const; |
|
|
|
// Trigger a temp entity |
|
virtual void TriggerTempEntity( KeyValues *pKeyValues ); |
|
|
|
// get owning weapon (for viewmodels) |
|
virtual int GetOwningWeaponEntIndex( int entindex ); |
|
virtual int GetEntIndex( EntitySearchResult entityToAttach ); |
|
|
|
virtual int FindGlobalFlexcontroller( char const *name ); |
|
virtual char const *GetGlobalFlexControllerName( int idx ); |
|
|
|
// helper for traversing ownership hierarchy |
|
virtual EntitySearchResult GetOwnerEntity( EntitySearchResult currentEnt ); |
|
|
|
// common and useful types to query for hierarchically |
|
virtual bool IsPlayer( EntitySearchResult entityToAttach ); |
|
virtual bool IsBaseCombatCharacter( EntitySearchResult entityToAttach ); |
|
virtual bool IsNPC( EntitySearchResult entityToAttach ); |
|
|
|
virtual Vector GetAbsOrigin( HTOOLHANDLE handle ); |
|
virtual QAngle GetAbsAngles( HTOOLHANDLE handle ); |
|
virtual void ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen ); |
|
|
|
// Sends a mesage from the tool to the client |
|
virtual void PostToolMessage( KeyValues *pKeyValues ); |
|
|
|
// Indicates whether the client should render particle systems |
|
virtual void EnableParticleSystems( bool bEnable ); |
|
|
|
// Is the game rendering in 3rd person mode? |
|
virtual bool IsRenderingThirdPerson() const; |
|
|
|
public: |
|
C_BaseEntity *LookupEntity( HTOOLHANDLE handle ); |
|
|
|
// IClientEntityListener methods |
|
void OnEntityDeleted( C_BaseEntity *pEntity ); |
|
void OnEntityCreated( C_BaseEntity *pEntity ); |
|
|
|
private: |
|
struct HToolEntry_t |
|
{ |
|
HToolEntry_t() : m_Handle( 0 ) {} |
|
HToolEntry_t( int handle, C_BaseEntity *pEntity = NULL ) |
|
: m_Handle( handle ), m_hEntity( pEntity ) |
|
{ |
|
if ( pEntity ) |
|
{ |
|
m_hEntity->SetToolHandle( m_Handle ); |
|
} |
|
} |
|
|
|
int m_Handle; |
|
EHANDLE m_hEntity; |
|
}; |
|
|
|
static int s_nNextHandle; |
|
|
|
static bool HandleLessFunc( const HToolEntry_t& lhs, const HToolEntry_t& rhs ) |
|
{ |
|
return lhs.m_Handle < rhs.m_Handle; |
|
} |
|
|
|
CUtlRBTree< HToolEntry_t > m_Handles; |
|
CUtlVector< int > m_ActiveHandles; |
|
bool m_bInRecordingMode; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Statics |
|
//----------------------------------------------------------------------------- |
|
int CClientTools::s_nNextHandle = 1; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Singleton instance |
|
//----------------------------------------------------------------------------- |
|
static CClientTools s_ClientTools; |
|
IClientTools *clienttools = &s_ClientTools; |
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CClientTools, IClientTools, VCLIENTTOOLS_INTERFACE_VERSION, s_ClientTools ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Constructor |
|
//----------------------------------------------------------------------------- |
|
CClientTools::CClientTools() : m_Handles( 0, 0, HandleLessFunc ) |
|
{ |
|
m_bInRecordingMode = false; |
|
cl_entitylist->AddListenerEntity( this ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Global toggle for recording |
|
//----------------------------------------------------------------------------- |
|
void CClientTools::EnableRecordingMode( bool bEnable ) |
|
{ |
|
m_bInRecordingMode = bEnable; |
|
} |
|
|
|
bool CClientTools::IsInRecordingMode() const |
|
{ |
|
return m_bInRecordingMode; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Trigger a temp entity |
|
//----------------------------------------------------------------------------- |
|
void CClientTools::TriggerTempEntity( KeyValues *pKeyValues ) |
|
{ |
|
te->TriggerTempEntity( pKeyValues ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// get owning weapon (for viewmodels) |
|
//----------------------------------------------------------------------------- |
|
int CClientTools::GetOwningWeaponEntIndex( int entindex ) |
|
{ |
|
C_BaseEntity *pEnt = C_BaseEntity::Instance( entindex ); |
|
C_BaseViewModel *pViewModel = dynamic_cast< C_BaseViewModel* >( pEnt ); |
|
if ( pViewModel ) |
|
{ |
|
C_BaseCombatWeapon *pWeapon = pViewModel->GetOwningWeapon(); |
|
if ( pWeapon ) |
|
{ |
|
return pWeapon->entindex(); |
|
} |
|
} |
|
|
|
return -1; |
|
} |
|
|
|
int CClientTools::GetEntIndex( EntitySearchResult entityToAttach ) |
|
{ |
|
C_BaseEntity *ent = reinterpret_cast< C_BaseEntity * >( entityToAttach ); |
|
return ent ? ent->entindex() : 0; |
|
} |
|
|
|
void CClientTools::AddClientRenderable( IClientRenderable *pRenderable, int renderGroup ) |
|
{ |
|
Assert( pRenderable ); |
|
|
|
cl_entitylist->AddNonNetworkableEntity( pRenderable->GetIClientUnknown() ); |
|
|
|
ClientRenderHandle_t handle = pRenderable->RenderHandle(); |
|
if ( INVALID_CLIENT_RENDER_HANDLE == handle ) |
|
{ |
|
// create new renderer handle |
|
ClientLeafSystem()->AddRenderable( pRenderable, (RenderGroup_t)renderGroup ); |
|
} |
|
else |
|
{ |
|
// handle already exists, just update group & origin |
|
ClientLeafSystem()->SetRenderGroup( pRenderable->RenderHandle(), (RenderGroup_t)renderGroup ); |
|
ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() ); |
|
} |
|
|
|
} |
|
|
|
void CClientTools::RemoveClientRenderable( IClientRenderable *pRenderable ) |
|
{ |
|
ClientRenderHandle_t handle = pRenderable->RenderHandle(); |
|
if( handle != INVALID_CLIENT_RENDER_HANDLE ) |
|
{ |
|
ClientLeafSystem()->RemoveRenderable( handle ); |
|
} |
|
cl_entitylist->RemoveEntity( pRenderable->GetIClientUnknown()->GetRefEHandle() ); |
|
} |
|
|
|
void CClientTools::MarkClientRenderableDirty( IClientRenderable *pRenderable ) |
|
{ |
|
ClientRenderHandle_t handle = pRenderable->RenderHandle(); |
|
if ( INVALID_CLIENT_RENDER_HANDLE != handle ) |
|
{ |
|
// handle already exists, just update group & origin |
|
ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() ); |
|
} |
|
} |
|
|
|
void CClientTools::SetRenderGroup( IClientRenderable *pRenderable, int renderGroup ) |
|
{ |
|
ClientRenderHandle_t handle = pRenderable->RenderHandle(); |
|
if ( INVALID_CLIENT_RENDER_HANDLE == handle ) |
|
{ |
|
// create new renderer handle |
|
ClientLeafSystem()->AddRenderable( pRenderable, (RenderGroup_t)renderGroup ); |
|
} |
|
else |
|
{ |
|
// handle already exists, just update group & origin |
|
ClientLeafSystem()->SetRenderGroup( pRenderable->RenderHandle(), (RenderGroup_t)renderGroup ); |
|
ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() ); |
|
} |
|
} |
|
|
|
bool CClientTools::DrawSprite( IClientRenderable *pRenderable, float scale, float frame, int rendermode, int renderfx, const Color &color, float flProxyRadius, int *pVisHandle ) |
|
{ |
|
Vector origin = pRenderable->GetRenderOrigin(); |
|
QAngle angles = pRenderable->GetRenderAngles(); |
|
|
|
// Get extra data |
|
CEngineSprite *psprite = (CEngineSprite *)modelinfo->GetModelExtraData( pRenderable->GetModel() ); |
|
if ( !psprite ) |
|
return false; |
|
|
|
// Get orthonormal bases for current view - re-align to current camera (vs. recorded camera) |
|
Vector forward, right, up; |
|
C_SpriteRenderer::GetSpriteAxes( ( C_SpriteRenderer::SPRITETYPE )psprite->GetOrientation(), origin, angles, forward, right, up ); |
|
|
|
int r = color.r(); |
|
int g = color.g(); |
|
int b = color.b(); |
|
|
|
float oldBlend = render->GetBlend(); |
|
if ( rendermode != kRenderNormal ) |
|
{ |
|
// kRenderGlow and kRenderWorldGlow have a special blending function |
|
if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow )) |
|
{ |
|
pixelvis_queryparams_t params; |
|
if ( flProxyRadius != 0.0f ) |
|
{ |
|
params.Init( origin, flProxyRadius ); |
|
params.bSizeInScreenspace = true; |
|
} |
|
else |
|
{ |
|
params.Init( origin ); |
|
} |
|
float blend = oldBlend * StandardGlowBlend( params, ( pixelvis_handle_t* )pVisHandle, rendermode, renderfx, color.a(), &scale ); |
|
|
|
if ( blend <= 0.0f ) |
|
return false; |
|
|
|
//Fade out the sprite depending on distance from the view origin. |
|
r *= blend; |
|
g *= blend; |
|
b *= blend; |
|
|
|
render->SetBlend( blend ); |
|
} |
|
} |
|
|
|
DrawSpriteModel( ( IClientEntity* )pRenderable, psprite, origin, scale, frame, rendermode, r, g, b, color.a(), forward, right, up ); |
|
|
|
if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow )) |
|
{ |
|
render->SetBlend( oldBlend ); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
HTOOLHANDLE CClientTools::AttachToEntity( EntitySearchResult entityToAttach ) |
|
{ |
|
C_BaseEntity *ent = reinterpret_cast< C_BaseEntity * >( entityToAttach ); |
|
Assert( ent ); |
|
if ( !ent ) |
|
return (HTOOLHANDLE)0; |
|
|
|
HTOOLHANDLE curHandle = ent->GetToolHandle(); |
|
if ( curHandle != 0 ) |
|
return curHandle; // Already attaached |
|
|
|
HToolEntry_t newHandle( s_nNextHandle++, ent ); |
|
|
|
m_Handles.Insert( newHandle ); |
|
m_ActiveHandles.AddToTail( newHandle.m_Handle ); |
|
|
|
return (HTOOLHANDLE)newHandle.m_Handle; |
|
} |
|
|
|
void CClientTools::DetachFromEntity( EntitySearchResult entityToDetach ) |
|
{ |
|
C_BaseEntity *ent = reinterpret_cast< C_BaseEntity * >( entityToDetach ); |
|
Assert( ent ); |
|
if ( !ent ) |
|
return; |
|
|
|
HTOOLHANDLE handle = ent->GetToolHandle(); |
|
ent->SetToolHandle( (HTOOLHANDLE)0 ); |
|
|
|
if ( handle == (HTOOLHANDLE)0 ) |
|
{ |
|
Assert( 0 ); |
|
return; |
|
} |
|
|
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
{ |
|
Assert( 0 ); |
|
return; |
|
} |
|
|
|
m_Handles.RemoveAt( idx ); |
|
m_ActiveHandles.FindAndRemove( handle ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : handle - |
|
// Output : C_BaseEntity |
|
//----------------------------------------------------------------------------- |
|
C_BaseEntity *CClientTools::LookupEntity( HTOOLHANDLE handle ) |
|
{ |
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
return NULL; |
|
|
|
return m_Handles[ idx ].m_hEntity; |
|
} |
|
|
|
int CClientTools::GetNumRecordables() |
|
{ |
|
return m_ActiveHandles.Count(); |
|
} |
|
|
|
HTOOLHANDLE CClientTools::GetRecordable( int index ) |
|
{ |
|
if ( index < 0 || index >= m_ActiveHandles.Count() ) |
|
{ |
|
Assert( 0 ); |
|
return (HTOOLHANDLE)0; |
|
} |
|
|
|
return m_ActiveHandles[ index ]; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Iterates through ALL entities (separate list for client vs. server) |
|
//----------------------------------------------------------------------------- |
|
EntitySearchResult CClientTools::NextEntity( EntitySearchResult currentEnt ) |
|
{ |
|
C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt ); |
|
if ( ent == NULL ) |
|
{ |
|
ent = cl_entitylist->FirstBaseEntity(); |
|
} |
|
else |
|
{ |
|
ent = cl_entitylist->NextBaseEntity( ent ); |
|
} |
|
return reinterpret_cast< EntitySearchResult >( ent ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Use this to turn on/off the presence of an underlying game entity |
|
//----------------------------------------------------------------------------- |
|
void CClientTools::SetEnabled( HTOOLHANDLE handle, bool enabled ) |
|
{ |
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
return; |
|
|
|
HToolEntry_t *slot = &m_Handles[ idx ]; |
|
Assert( slot ); |
|
if ( slot == NULL ) |
|
return; |
|
|
|
C_BaseEntity *ent = slot->m_hEntity.Get(); |
|
if ( ent == NULL || ent->entindex() == 0 ) |
|
return; // Don't disable/enable the "world" |
|
|
|
ent->EnableInToolView( enabled ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CClientTools::SetRecording( HTOOLHANDLE handle, bool recording ) |
|
{ |
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
return; |
|
|
|
HToolEntry_t &entry = m_Handles[ idx ]; |
|
if ( entry.m_hEntity ) |
|
{ |
|
entry.m_hEntity->SetToolRecording( recording ); |
|
} |
|
} |
|
|
|
bool CClientTools::ShouldRecord( HTOOLHANDLE handle ) |
|
{ |
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
return false; |
|
|
|
HToolEntry_t &entry = m_Handles[ idx ]; |
|
return entry.m_hEntity && entry.m_hEntity->ShouldRecordInTools(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CClientTools::GetModelIndex( HTOOLHANDLE handle ) |
|
{ |
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
return NULL; |
|
|
|
HToolEntry_t &entry = m_Handles[ idx ]; |
|
if ( entry.m_hEntity ) |
|
{ |
|
return entry.m_hEntity->GetModelIndex(); |
|
} |
|
Assert( 0 ); |
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char* CClientTools::GetModelName( HTOOLHANDLE handle ) |
|
{ |
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
return NULL; |
|
|
|
HToolEntry_t &entry = m_Handles[ idx ]; |
|
if ( entry.m_hEntity ) |
|
{ |
|
return STRING( entry.m_hEntity->GetModelName() ); |
|
} |
|
Assert( 0 ); |
|
return NULL; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char* CClientTools::GetClassname( HTOOLHANDLE handle ) |
|
{ |
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
return NULL; |
|
|
|
HToolEntry_t &entry = m_Handles[ idx ]; |
|
if ( entry.m_hEntity ) |
|
{ |
|
return STRING( entry.m_hEntity->GetClassname() ); |
|
} |
|
Assert( 0 ); |
|
return NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : handle - |
|
//----------------------------------------------------------------------------- |
|
bool CClientTools::IsValidHandle( HTOOLHANDLE handle ) |
|
{ |
|
return m_Handles.Find( HToolEntry_t( handle ) ) != m_Handles.InvalidIndex(); |
|
} |
|
|
|
void CClientTools::OnEntityDeleted( CBaseEntity *pEntity ) |
|
{ |
|
HTOOLHANDLE handle = pEntity ? pEntity->GetToolHandle() : (HTOOLHANDLE)0; |
|
if ( handle == (HTOOLHANDLE)0 ) |
|
return; |
|
|
|
if ( m_bInRecordingMode ) |
|
{ |
|
// Send deletion message to tool interface |
|
KeyValues *kv = new KeyValues( "deleted" ); |
|
ToolFramework_PostToolMessage( handle, kv ); |
|
kv->deleteThis(); |
|
} |
|
|
|
DetachFromEntity( pEntity ); |
|
} |
|
|
|
void CClientTools::OnEntityCreated( CBaseEntity *pEntity ) |
|
{ |
|
if ( !m_bInRecordingMode ) |
|
return; |
|
|
|
HTOOLHANDLE h = AttachToEntity( pEntity ); |
|
|
|
// Send deletion message to tool interface |
|
KeyValues *kv = new KeyValues( "created" ); |
|
ToolFramework_PostToolMessage( h, kv ); |
|
kv->deleteThis(); |
|
} |
|
|
|
HTOOLHANDLE CClientTools::GetToolHandleForEntityByIndex( int entindex ) |
|
{ |
|
C_BaseEntity *ent = C_BaseEntity::Instance( entindex ); |
|
if ( !ent ) |
|
return (HTOOLHANDLE)0; |
|
|
|
return ent->GetToolHandle(); |
|
} |
|
|
|
EntitySearchResult CClientTools::GetLocalPlayer() |
|
{ |
|
C_BasePlayer *p = C_BasePlayer::GetLocalPlayer(); |
|
return reinterpret_cast< EntitySearchResult >( p ); |
|
} |
|
|
|
bool CClientTools::GetLocalPlayerEyePosition( Vector& org, QAngle& ang, float &fov ) |
|
{ |
|
C_BasePlayer *pl = C_BasePlayer::GetLocalPlayer(); |
|
if ( pl == NULL ) |
|
return false; |
|
|
|
org = pl->EyePosition(); |
|
ang = pl->EyeAngles(); |
|
fov = pl->GetFOV(); |
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Create, destroy shadow |
|
//----------------------------------------------------------------------------- |
|
ClientShadowHandle_t CClientTools::CreateShadow( CBaseHandle h, int nFlags ) |
|
{ |
|
return g_pClientShadowMgr->CreateShadow( h, nFlags ); |
|
} |
|
|
|
void CClientTools::DestroyShadow( ClientShadowHandle_t h ) |
|
{ |
|
g_pClientShadowMgr->DestroyShadow( h ); |
|
} |
|
|
|
ClientShadowHandle_t CClientTools::CreateFlashlight( const FlashlightState_t &lightState ) |
|
{ |
|
return g_pClientShadowMgr->CreateFlashlight( lightState ); |
|
} |
|
|
|
void CClientTools::DestroyFlashlight( ClientShadowHandle_t h ) |
|
{ |
|
g_pClientShadowMgr->DestroyFlashlight( h ); |
|
} |
|
|
|
void CClientTools::UpdateFlashlightState( ClientShadowHandle_t h, const FlashlightState_t &lightState ) |
|
{ |
|
g_pClientShadowMgr->UpdateFlashlightState( h, lightState ); |
|
} |
|
|
|
void CClientTools::AddToDirtyShadowList( ClientShadowHandle_t h, bool force ) |
|
{ |
|
g_pClientShadowMgr->AddToDirtyShadowList( h, force ); |
|
} |
|
|
|
void CClientTools::MarkRenderToTextureShadowDirty( ClientShadowHandle_t h ) |
|
{ |
|
g_pClientShadowMgr->MarkRenderToTextureShadowDirty( h ); |
|
} |
|
|
|
void CClientTools::UpdateProjectedTexture( ClientShadowHandle_t h, bool bForce ) |
|
{ |
|
g_pClientShadowMgr->UpdateProjectedTexture( h, bForce ); |
|
} |
|
|
|
int CClientTools::FindGlobalFlexcontroller( char const *name ) |
|
{ |
|
return C_BaseFlex::AddGlobalFlexController( (char *)name ); |
|
} |
|
|
|
char const *CClientTools::GetGlobalFlexControllerName( int idx ) |
|
{ |
|
return C_BaseFlex::GetGlobalFlexControllerName( idx ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// helper for traversing ownership hierarchy |
|
//----------------------------------------------------------------------------- |
|
EntitySearchResult CClientTools::GetOwnerEntity( EntitySearchResult currentEnt ) |
|
{ |
|
C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt ); |
|
return ent ? ent->GetOwnerEntity() : NULL; |
|
} |
|
//----------------------------------------------------------------------------- |
|
// common and useful types to query for hierarchically |
|
//----------------------------------------------------------------------------- |
|
bool CClientTools::IsPlayer( EntitySearchResult currentEnt ) |
|
{ |
|
C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt ); |
|
return ent ? ent->IsPlayer() : false; |
|
} |
|
|
|
bool CClientTools::IsBaseCombatCharacter( EntitySearchResult currentEnt ) |
|
{ |
|
C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt ); |
|
return ent ? ent->IsBaseCombatCharacter() : false; |
|
} |
|
|
|
bool CClientTools::IsNPC( EntitySearchResult currentEnt ) |
|
{ |
|
C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt ); |
|
return ent ? ent->IsNPC() : false; |
|
} |
|
|
|
Vector CClientTools::GetAbsOrigin( HTOOLHANDLE handle ) |
|
{ |
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
return vec3_origin; |
|
|
|
HToolEntry_t &entry = m_Handles[ idx ]; |
|
if ( entry.m_hEntity ) |
|
{ |
|
return entry.m_hEntity->GetAbsOrigin(); |
|
} |
|
Assert( 0 ); |
|
return vec3_origin; |
|
} |
|
|
|
QAngle CClientTools::GetAbsAngles( HTOOLHANDLE handle ) |
|
{ |
|
int idx = m_Handles.Find( HToolEntry_t( handle ) ); |
|
if ( idx == m_Handles.InvalidIndex() ) |
|
return vec3_angle; |
|
|
|
HToolEntry_t &entry = m_Handles[ idx ]; |
|
if ( entry.m_hEntity ) |
|
{ |
|
return entry.m_hEntity->GetAbsAngles(); |
|
} |
|
Assert( 0 ); |
|
return vec3_angle; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Sends a mesage from the tool to the client |
|
//----------------------------------------------------------------------------- |
|
void CClientTools::PostToolMessage( KeyValues *pKeyValues ) |
|
{ |
|
if ( !Q_stricmp( pKeyValues->GetName(), "QueryParticleManifest" ) ) |
|
{ |
|
// NOTE: This cannot be done during particle system init because tools aren't set up at that point |
|
CUtlVector<CUtlString> files; |
|
GetParticleManifest( files ); |
|
int nCount = files.Count(); |
|
for ( int i = 0; i < nCount; ++i ) |
|
{ |
|
char pTemp[256]; |
|
Q_snprintf( pTemp, sizeof(pTemp), "%d", i ); |
|
KeyValues *pSubKey = pKeyValues->FindKey( pTemp, true ); |
|
pSubKey->SetString( "file", files[i] ); |
|
} |
|
return; |
|
} |
|
|
|
if ( !Q_stricmp( pKeyValues->GetName(), "QueryMonitorTexture" ) ) |
|
{ |
|
pKeyValues->SetPtr( "texture", GetCameraTexture() ); |
|
return; |
|
} |
|
|
|
#ifdef PORTAL |
|
if ( !Q_stricmp( pKeyValues->GetName(), "portals" ) ) |
|
{ |
|
g_pPortalRender->HandlePortalPlaybackMessage( pKeyValues ); |
|
return; |
|
} |
|
|
|
if ( !Q_stricmp( pKeyValues->GetName(), "query CPortalRenderer" ) ) |
|
{ |
|
pKeyValues->SetInt( "IsRenderingPortal", g_pPortalRender->IsRenderingPortal() ? 1 : 0 ); |
|
return; |
|
} |
|
#endif |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Indicates whether the client should render particle systems |
|
//----------------------------------------------------------------------------- |
|
void CClientTools::EnableParticleSystems( bool bEnable ) |
|
{ |
|
ParticleMgr()->RenderParticleSystems( bEnable ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Is the game rendering in 3rd person mode? |
|
//----------------------------------------------------------------------------- |
|
bool CClientTools::IsRenderingThirdPerson() const |
|
{ |
|
return !C_BasePlayer::LocalPlayerInFirstPersonView(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Reload particle definitions |
|
//----------------------------------------------------------------------------- |
|
void CClientTools::ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen ) |
|
{ |
|
// Remove all new effects, because we are going to free internal structures they point to |
|
ParticleMgr()->RemoveAllNewEffects(); |
|
|
|
// FIXME: Use file name to determine if we care about this data |
|
CUtlBuffer buf( pBufData, nLen, CUtlBuffer::READ_ONLY ); |
|
g_pParticleSystemMgr->ReadParticleConfigFile( buf, true ); |
|
}
|
|
|