Team Fortress 2 Source Code as on 22/4/2020
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.

523 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include <KeyValues.h>
  9. #include "materialsystem/imaterialvar.h"
  10. #include "materialsystem/imaterial.h"
  11. #include "materialsystem/itexture.h"
  12. #include "materialsystem/imaterialsystem.h"
  13. #include "functionproxy.h"
  14. #include "toolframework_client.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. // forward declarations
  18. void ToolFramework_RecordMaterialParams( IMaterial *pMaterial );
  19. //-----------------------------------------------------------------------------
  20. // Returns the proximity of the player to the entity
  21. //-----------------------------------------------------------------------------
  22. class CPlayerProximityProxy : public CResultProxy
  23. {
  24. public:
  25. bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
  26. void OnBind( void *pC_BaseEntity );
  27. private:
  28. float m_Factor;
  29. };
  30. bool CPlayerProximityProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  31. {
  32. if (!CResultProxy::Init( pMaterial, pKeyValues ))
  33. return false;
  34. m_Factor = pKeyValues->GetFloat( "scale", 0.002 );
  35. return true;
  36. }
  37. void CPlayerProximityProxy::OnBind( void *pC_BaseEntity )
  38. {
  39. if (!pC_BaseEntity)
  40. return;
  41. // Find the distance between the player and this entity....
  42. C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
  43. C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
  44. if (!pPlayer)
  45. return;
  46. Vector delta;
  47. VectorSubtract( pEntity->WorldSpaceCenter(), pPlayer->WorldSpaceCenter(), delta );
  48. Assert( m_pResult );
  49. SetFloatResult( delta.Length() * m_Factor );
  50. if ( ToolsEnabled() )
  51. {
  52. ToolFramework_RecordMaterialParams( GetMaterial() );
  53. }
  54. }
  55. EXPOSE_INTERFACE( CPlayerProximityProxy, IMaterialProxy, "PlayerProximity" IMATERIAL_PROXY_INTERFACE_VERSION );
  56. //-----------------------------------------------------------------------------
  57. // Returns true if the player's team matches that of the entity the proxy material is attached to
  58. //-----------------------------------------------------------------------------
  59. class CPlayerTeamMatchProxy : public CResultProxy
  60. {
  61. public:
  62. bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
  63. void OnBind( void *pC_BaseEntity );
  64. private:
  65. };
  66. bool CPlayerTeamMatchProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  67. {
  68. if (!CResultProxy::Init( pMaterial, pKeyValues ))
  69. return false;
  70. return true;
  71. }
  72. void CPlayerTeamMatchProxy::OnBind( void *pC_BaseEntity )
  73. {
  74. if (!pC_BaseEntity)
  75. return;
  76. // Find the distance between the player and this entity....
  77. C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
  78. C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
  79. if (!pPlayer)
  80. return;
  81. Assert( m_pResult );
  82. SetFloatResult( (pEntity->GetTeamNumber() == pPlayer->GetTeamNumber()) ? 1.0 : 0.0 );
  83. if ( ToolsEnabled() )
  84. {
  85. ToolFramework_RecordMaterialParams( GetMaterial() );
  86. }
  87. }
  88. EXPOSE_INTERFACE( CPlayerTeamMatchProxy, IMaterialProxy, "PlayerTeamMatch" IMATERIAL_PROXY_INTERFACE_VERSION );
  89. //-----------------------------------------------------------------------------
  90. // Returns the player view direction
  91. //-----------------------------------------------------------------------------
  92. class CPlayerViewProxy : public CResultProxy
  93. {
  94. public:
  95. bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
  96. void OnBind( void *pC_BaseEntity );
  97. private:
  98. float m_Factor;
  99. };
  100. bool CPlayerViewProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  101. {
  102. if (!CResultProxy::Init( pMaterial, pKeyValues ))
  103. return false;
  104. m_Factor = pKeyValues->GetFloat( "scale", 2 );
  105. return true;
  106. }
  107. void CPlayerViewProxy::OnBind( void *pC_BaseEntity )
  108. {
  109. if (!pC_BaseEntity)
  110. return;
  111. // Find the view angle between the player and this entity....
  112. C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
  113. C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
  114. if (!pPlayer)
  115. return;
  116. Vector delta;
  117. VectorSubtract( pEntity->WorldSpaceCenter(), pPlayer->WorldSpaceCenter(), delta );
  118. VectorNormalize( delta );
  119. Vector forward;
  120. AngleVectors( pPlayer->GetAbsAngles(), &forward );
  121. Assert( m_pResult );
  122. SetFloatResult( DotProduct( forward, delta ) * m_Factor );
  123. if ( ToolsEnabled() )
  124. {
  125. ToolFramework_RecordMaterialParams( GetMaterial() );
  126. }
  127. }
  128. EXPOSE_INTERFACE( CPlayerViewProxy, IMaterialProxy, "PlayerView" IMATERIAL_PROXY_INTERFACE_VERSION );
  129. //-----------------------------------------------------------------------------
  130. // Returns the player speed
  131. //-----------------------------------------------------------------------------
  132. class CPlayerSpeedProxy : public CResultProxy
  133. {
  134. public:
  135. bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
  136. void OnBind( void *pC_BaseEntity );
  137. private:
  138. float m_Factor;
  139. };
  140. bool CPlayerSpeedProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  141. {
  142. if (!CResultProxy::Init( pMaterial, pKeyValues ))
  143. return false;
  144. m_Factor = pKeyValues->GetFloat( "scale", 0.005 );
  145. return true;
  146. }
  147. void CPlayerSpeedProxy::OnBind( void *pC_BaseEntity )
  148. {
  149. // Find the player speed....
  150. C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
  151. if (!pPlayer)
  152. return;
  153. Assert( m_pResult );
  154. SetFloatResult( pPlayer->GetLocalVelocity().Length() * m_Factor );
  155. if ( ToolsEnabled() )
  156. {
  157. ToolFramework_RecordMaterialParams( GetMaterial() );
  158. }
  159. }
  160. EXPOSE_INTERFACE( CPlayerSpeedProxy, IMaterialProxy, "PlayerSpeed" IMATERIAL_PROXY_INTERFACE_VERSION );
  161. //-----------------------------------------------------------------------------
  162. // Returns the player position
  163. //-----------------------------------------------------------------------------
  164. class CPlayerPositionProxy : public CResultProxy
  165. {
  166. public:
  167. bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
  168. void OnBind( void *pC_BaseEntity );
  169. private:
  170. float m_Factor;
  171. };
  172. bool CPlayerPositionProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  173. {
  174. if (!CResultProxy::Init( pMaterial, pKeyValues ))
  175. return false;
  176. m_Factor = pKeyValues->GetFloat( "scale", 0.005 );
  177. return true;
  178. }
  179. void CPlayerPositionProxy::OnBind( void *pC_BaseEntity )
  180. {
  181. // Find the player speed....
  182. C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
  183. if (!pPlayer)
  184. return;
  185. // This is actually a vector...
  186. Assert( m_pResult );
  187. Vector res;
  188. VectorMultiply( pPlayer->WorldSpaceCenter(), m_Factor, res );
  189. m_pResult->SetVecValue( res.Base(), 3 );
  190. if ( ToolsEnabled() )
  191. {
  192. ToolFramework_RecordMaterialParams( GetMaterial() );
  193. }
  194. }
  195. EXPOSE_INTERFACE( CPlayerPositionProxy, IMaterialProxy, "PlayerPosition" IMATERIAL_PROXY_INTERFACE_VERSION );
  196. //-----------------------------------------------------------------------------
  197. // Returns the entity speed
  198. //-----------------------------------------------------------------------------
  199. class CEntitySpeedProxy : public CResultProxy
  200. {
  201. public:
  202. void OnBind( void *pC_BaseEntity );
  203. };
  204. void CEntitySpeedProxy::OnBind( void *pC_BaseEntity )
  205. {
  206. // Find the view angle between the player and this entity....
  207. if (!pC_BaseEntity)
  208. return;
  209. // Find the view angle between the player and this entity....
  210. C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
  211. Assert( m_pResult );
  212. m_pResult->SetFloatValue( pEntity->GetLocalVelocity().Length() );
  213. if ( ToolsEnabled() )
  214. {
  215. ToolFramework_RecordMaterialParams( GetMaterial() );
  216. }
  217. }
  218. EXPOSE_INTERFACE( CEntitySpeedProxy, IMaterialProxy, "EntitySpeed" IMATERIAL_PROXY_INTERFACE_VERSION );
  219. //-----------------------------------------------------------------------------
  220. // Returns a random # from 0 - 1 specific to the entity it's applied to
  221. //-----------------------------------------------------------------------------
  222. class CEntityRandomProxy : public CResultProxy
  223. {
  224. public:
  225. bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
  226. void OnBind( void *pC_BaseEntity );
  227. private:
  228. CFloatInput m_Factor;
  229. };
  230. bool CEntityRandomProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  231. {
  232. if (!CResultProxy::Init( pMaterial, pKeyValues ))
  233. return false;
  234. if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1 ))
  235. return false;
  236. return true;
  237. }
  238. void CEntityRandomProxy::OnBind( void *pC_BaseEntity )
  239. {
  240. // Find the view angle between the player and this entity....
  241. if (!pC_BaseEntity)
  242. return;
  243. // Find the view angle between the player and this entity....
  244. C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
  245. Assert( m_pResult );
  246. m_pResult->SetFloatValue( pEntity->ProxyRandomValue() * m_Factor.GetFloat() );
  247. if ( ToolsEnabled() )
  248. {
  249. ToolFramework_RecordMaterialParams( GetMaterial() );
  250. }
  251. }
  252. EXPOSE_INTERFACE( CEntityRandomProxy, IMaterialProxy, "EntityRandom" IMATERIAL_PROXY_INTERFACE_VERSION );
  253. #include "utlrbtree.h"
  254. //-----------------------------------------------------------------------------
  255. // Returns the player speed
  256. //-----------------------------------------------------------------------------
  257. class CPlayerLogoProxy : public IMaterialProxy
  258. {
  259. public:
  260. CPlayerLogoProxy();
  261. virtual bool Init( IMaterial* pMaterial, KeyValues *pKeyValues );
  262. virtual void OnBind( void *pC_BaseEntity );
  263. virtual void Release()
  264. {
  265. if ( m_pDefaultTexture )
  266. {
  267. m_pDefaultTexture->DecrementReferenceCount();
  268. }
  269. int c = m_Logos.Count();
  270. int i;
  271. for ( i = 0; i < c ; i++ )
  272. {
  273. PlayerLogo *logo = &m_Logos[ i ];
  274. if( logo->texture )
  275. {
  276. logo->texture->DecrementReferenceCount();
  277. }
  278. }
  279. m_Logos.RemoveAll();
  280. }
  281. virtual IMaterial *GetMaterial();
  282. protected:
  283. virtual void OnLogoBindInternal( int playerindex );
  284. private:
  285. IMaterialVar *m_pBaseTextureVar;
  286. struct PlayerLogo
  287. {
  288. unsigned int crc;
  289. ITexture *texture;
  290. };
  291. static bool LogoLessFunc( const PlayerLogo& src1, const PlayerLogo& src2 )
  292. {
  293. return src1.crc < src2.crc;
  294. }
  295. CUtlRBTree< PlayerLogo > m_Logos;
  296. ITexture *m_pDefaultTexture;
  297. };
  298. //-----------------------------------------------------------------------------
  299. // Purpose:
  300. //-----------------------------------------------------------------------------
  301. CPlayerLogoProxy::CPlayerLogoProxy()
  302. : m_Logos( 0, 0, LogoLessFunc )
  303. {
  304. m_pDefaultTexture = NULL;
  305. }
  306. #define DEFAULT_DECAL_NAME "decals/YBlood1"
  307. bool CPlayerLogoProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  308. {
  309. bool found = false;
  310. m_pBaseTextureVar = pMaterial->FindVar( "$basetexture", &found );
  311. if ( !found )
  312. return false;
  313. m_pDefaultTexture = materials->FindTexture( DEFAULT_DECAL_NAME, TEXTURE_GROUP_DECAL );
  314. if ( IsErrorTexture( m_pDefaultTexture ) )
  315. return false;
  316. m_pDefaultTexture->IncrementReferenceCount();
  317. return true;
  318. }
  319. void CPlayerLogoProxy::OnBind( void *pC_BaseEntity )
  320. {
  321. // Decal's are bound with the player index as the passed in paramter
  322. int playerindex = (int)pC_BaseEntity;
  323. if ( playerindex <= 0 )
  324. return;
  325. if ( playerindex > gpGlobals->maxClients )
  326. return;
  327. if ( !m_pBaseTextureVar )
  328. return;
  329. OnLogoBindInternal( playerindex );
  330. }
  331. void CPlayerLogoProxy::OnLogoBindInternal( int playerindex )
  332. {
  333. // Find player
  334. player_info_t info;
  335. engine->GetPlayerInfo( playerindex, &info );
  336. if ( !info.customFiles[0] )
  337. return;
  338. // So we don't trash this too hard
  339. ITexture *texture = NULL;
  340. PlayerLogo logo;
  341. logo.crc = (unsigned int)info.customFiles[0];
  342. logo.texture = NULL;
  343. int lookup = m_Logos.Find( logo );
  344. if ( lookup == m_Logos.InvalidIndex() )
  345. {
  346. char crcfilename[ 512 ];
  347. char logohex[ 16 ];
  348. Q_binarytohex( (byte *)&info.customFiles[0], sizeof( info.customFiles[0] ), logohex, sizeof( logohex ) );
  349. Q_snprintf( crcfilename, sizeof( crcfilename ), "temp/%s", logohex );
  350. texture = materials->FindTexture( crcfilename, TEXTURE_GROUP_DECAL, false );
  351. if ( texture )
  352. {
  353. // Make sure it doesn't get flushed
  354. texture->IncrementReferenceCount();
  355. logo.texture = texture;
  356. }
  357. m_Logos.Insert( logo );
  358. }
  359. else
  360. {
  361. texture = m_Logos[ lookup ].texture;
  362. }
  363. if ( texture )
  364. {
  365. m_pBaseTextureVar->SetTextureValue( texture );
  366. }
  367. else if ( m_pDefaultTexture )
  368. {
  369. m_pBaseTextureVar->SetTextureValue( m_pDefaultTexture );
  370. }
  371. if ( ToolsEnabled() )
  372. {
  373. ToolFramework_RecordMaterialParams( GetMaterial() );
  374. }
  375. }
  376. IMaterial *CPlayerLogoProxy::GetMaterial()
  377. {
  378. return m_pBaseTextureVar->GetOwningMaterial();
  379. }
  380. EXPOSE_INTERFACE( CPlayerLogoProxy, IMaterialProxy, "PlayerLogo" IMATERIAL_PROXY_INTERFACE_VERSION );
  381. /* @note Tom Bui: This is here for reference, but we don't want people to use it!
  382. //-----------------------------------------------------------------------------
  383. //
  384. //-----------------------------------------------------------------------------
  385. class CPlayerLogoOnModelProxy : public CPlayerLogoProxy
  386. {
  387. public:
  388. virtual void OnBind( void *pC_BaseEntity );
  389. };
  390. void CPlayerLogoOnModelProxy::OnBind( void *pC_BaseEntity )
  391. {
  392. if ( pC_BaseEntity )
  393. {
  394. IClientRenderable *pRend = (IClientRenderable *)pC_BaseEntity;
  395. C_BaseEntity *pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
  396. if ( pEntity )
  397. {
  398. if ( !pEntity->IsPlayer() )
  399. {
  400. pEntity = pEntity->GetRootMoveParent();
  401. }
  402. if ( pEntity && pEntity->IsPlayer() )
  403. {
  404. int iPlayerIndex = pEntity->entindex();
  405. OnLogoBindInternal( iPlayerIndex );
  406. }
  407. }
  408. }
  409. }
  410. EXPOSE_INTERFACE( CPlayerLogoOnModelProxy, IMaterialProxy, "PlayerLogoOnModel" IMATERIAL_PROXY_INTERFACE_VERSION );
  411. */