//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include #include "materialsystem/IMaterialVar.h" #include "materialsystem/IMaterial.h" #include "materialsystem/ITexture.h" #include "materialsystem/IMaterialSystem.h" #include "FunctionProxy.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" //----------------------------------------------------------------------------- // Returns the proximity of the player to the entity //----------------------------------------------------------------------------- class CPlayerProximityProxy : public CResultProxy { public: bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); void OnBind( void *pC_BaseEntity ); private: float m_Factor; }; bool CPlayerProximityProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) { if (!CResultProxy::Init( pMaterial, pKeyValues )) return false; m_Factor = pKeyValues->GetFloat( "scale", 0.002 ); return true; } void CPlayerProximityProxy::OnBind( void *pC_BaseEntity ) { if (!pC_BaseEntity) return; // Find the distance between the player and this entity.... C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity ); C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer(); if (!pPlayer) return; Vector delta; VectorSubtract( pEntity->WorldSpaceCenter(), pPlayer->WorldSpaceCenter(), delta ); Assert( m_pResult ); SetFloatResult( delta.Length() * m_Factor ); } EXPOSE_INTERFACE( CPlayerProximityProxy, IMaterialProxy, "PlayerProximity" IMATERIAL_PROXY_INTERFACE_VERSION ); //----------------------------------------------------------------------------- // Returns the player view direction //----------------------------------------------------------------------------- class CPlayerViewProxy : public CResultProxy { public: bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); void OnBind( void *pC_BaseEntity ); private: float m_Factor; }; bool CPlayerViewProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) { if (!CResultProxy::Init( pMaterial, pKeyValues )) return false; m_Factor = pKeyValues->GetFloat( "scale", 2 ); return true; } void CPlayerViewProxy::OnBind( void *pC_BaseEntity ) { if (!pC_BaseEntity) return; // Find the view angle between the player and this entity.... C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity ); C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer(); if (!pPlayer) return; Vector delta; VectorSubtract( pEntity->WorldSpaceCenter(), pPlayer->WorldSpaceCenter(), delta ); VectorNormalize( delta ); Vector forward; AngleVectors( pPlayer->GetAbsAngles(), &forward ); Assert( m_pResult ); SetFloatResult( DotProduct( forward, delta ) * m_Factor ); } EXPOSE_INTERFACE( CPlayerViewProxy, IMaterialProxy, "PlayerView" IMATERIAL_PROXY_INTERFACE_VERSION ); //----------------------------------------------------------------------------- // Returns the player speed //----------------------------------------------------------------------------- class CPlayerSpeedProxy : public CResultProxy { public: bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); void OnBind( void *pC_BaseEntity ); private: float m_Factor; }; bool CPlayerSpeedProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) { if (!CResultProxy::Init( pMaterial, pKeyValues )) return false; m_Factor = pKeyValues->GetFloat( "scale", 0.005 ); return true; } void CPlayerSpeedProxy::OnBind( void *pC_BaseEntity ) { // Find the player speed.... C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer(); if (!pPlayer) return; Assert( m_pResult ); SetFloatResult( pPlayer->GetLocalVelocity().Length() * m_Factor ); } EXPOSE_INTERFACE( CPlayerSpeedProxy, IMaterialProxy, "PlayerSpeed" IMATERIAL_PROXY_INTERFACE_VERSION ); //----------------------------------------------------------------------------- // Returns the player position //----------------------------------------------------------------------------- class CPlayerPositionProxy : public CResultProxy { public: bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); void OnBind( void *pC_BaseEntity ); private: float m_Factor; }; bool CPlayerPositionProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) { if (!CResultProxy::Init( pMaterial, pKeyValues )) return false; m_Factor = pKeyValues->GetFloat( "scale", 0.005 ); return true; } void CPlayerPositionProxy::OnBind( void *pC_BaseEntity ) { // Find the player speed.... C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer(); if (!pPlayer) return; // This is actually a vector... Assert( m_pResult ); Vector res; VectorMultiply( pPlayer->WorldSpaceCenter(), m_Factor, res ); m_pResult->SetVecValue( res.Base(), 3 ); } EXPOSE_INTERFACE( CPlayerPositionProxy, IMaterialProxy, "PlayerPosition" IMATERIAL_PROXY_INTERFACE_VERSION ); //----------------------------------------------------------------------------- // Returns the entity speed //----------------------------------------------------------------------------- class CEntitySpeedProxy : public CResultProxy { public: void OnBind( void *pC_BaseEntity ); }; void CEntitySpeedProxy::OnBind( void *pC_BaseEntity ) { // Find the view angle between the player and this entity.... if (!pC_BaseEntity) return; // Find the view angle between the player and this entity.... C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity ); Assert( m_pResult ); m_pResult->SetFloatValue( pEntity->GetLocalVelocity().Length() ); } EXPOSE_INTERFACE( CEntitySpeedProxy, IMaterialProxy, "EntitySpeed" IMATERIAL_PROXY_INTERFACE_VERSION ); //----------------------------------------------------------------------------- // Returns a random # from 0 - 1 specific to the entity it's applied to //----------------------------------------------------------------------------- class CEntityRandomProxy : public CResultProxy { public: bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); void OnBind( void *pC_BaseEntity ); private: CFloatInput m_Factor; }; bool CEntityRandomProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) { if (!CResultProxy::Init( pMaterial, pKeyValues )) return false; if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1 )) return false; return true; } void CEntityRandomProxy::OnBind( void *pC_BaseEntity ) { // Find the view angle between the player and this entity.... if (!pC_BaseEntity) return; // Find the view angle between the player and this entity.... C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity ); Assert( m_pResult ); m_pResult->SetFloatValue( pEntity->ProxyRandomValue() * m_Factor.GetFloat() ); } EXPOSE_INTERFACE( CEntityRandomProxy, IMaterialProxy, "EntityRandom" IMATERIAL_PROXY_INTERFACE_VERSION ); #include "UtlRBTree.h" //----------------------------------------------------------------------------- // Returns the player speed //----------------------------------------------------------------------------- class CPlayerLogoProxy : public IMaterialProxy { public: CPlayerLogoProxy(); virtual bool Init( IMaterial* pMaterial, KeyValues *pKeyValues ); virtual void OnBind( void *pC_BaseEntity ); virtual void Release() { if ( m_pDefaultTexture ) { m_pDefaultTexture->DecrementReferenceCount(); } int c = m_Logos.Count(); int i; for ( i = 0; i < c ; i++ ) { PlayerLogo *logo = &m_Logos[ i ]; if( logo->texture ) { logo->texture->DecrementReferenceCount(); } } m_Logos.RemoveAll(); } private: IMaterialVar *m_pBaseTextureVar; struct PlayerLogo { unsigned int crc; ITexture *texture; }; static bool LogoLessFunc( const PlayerLogo& src1, const PlayerLogo& src2 ) { return src1.crc < src2.crc; } CUtlRBTree< PlayerLogo > m_Logos; ITexture *m_pDefaultTexture; }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CPlayerLogoProxy::CPlayerLogoProxy() : m_Logos( 0, 0, LogoLessFunc ) { m_pDefaultTexture = NULL; } #define DEFAULT_DECAL_NAME "decals/YBlood1" bool CPlayerLogoProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) { bool found = false; m_pBaseTextureVar = pMaterial->FindVar( "$basetexture", &found ); if ( !found ) return false; m_pDefaultTexture = materials->FindTexture( DEFAULT_DECAL_NAME, TEXTURE_GROUP_DECAL ); if ( IsErrorTexture( m_pDefaultTexture ) ) return false; m_pDefaultTexture->IncrementReferenceCount(); return true; } void CPlayerLogoProxy::OnBind( void *pC_BaseEntity ) { // Decal's are bound with the player index as the passed in paramter int playerindex = (int)pC_BaseEntity; if ( playerindex <= 0 ) return; if ( playerindex > gpGlobals->maxClients ) return; if ( !m_pBaseTextureVar ) return; // Find player player_info_t info; engine->GetPlayerInfo( playerindex, &info ); if ( !info.customFiles[0] ) return; // So we don't trash this too hard ITexture *texture = NULL; PlayerLogo logo; logo.crc = (unsigned int)info.customFiles[0]; logo.texture = NULL; int lookup = m_Logos.Find( logo ); if ( lookup == m_Logos.InvalidIndex() ) { char crcfilename[ 512 ]; char logohex[ 16 ]; Q_binarytohex( (byte *)&info.customFiles[0], sizeof( info.customFiles[0] ), logohex, sizeof( logohex ) ); Q_snprintf( crcfilename, sizeof( crcfilename ), "temp/%s", logohex ); texture = materials->FindTexture( crcfilename, TEXTURE_GROUP_DECAL, false ); if ( texture ) { // Make sure it doesn't get flushed texture->IncrementReferenceCount(); logo.texture = texture; } m_Logos.Insert( logo ); } else { texture = m_Logos[ lookup ].texture; } if ( texture ) { m_pBaseTextureVar->SetTextureValue( texture ); return; } if ( m_pDefaultTexture ) { m_pBaseTextureVar->SetTextureValue( m_pDefaultTexture ); return; } } EXPOSE_INTERFACE( CPlayerLogoProxy, IMaterialProxy, "PlayerLogo" IMATERIAL_PROXY_INTERFACE_VERSION );