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.

793 lines
24 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "toolframework/itoolentity.h"
  8. #include "tier1/KeyValues.h"
  9. #include "Sprite.h"
  10. #include "enginesprite.h"
  11. #include "toolframework_client.h"
  12. #include "particles/particles.h"
  13. #include "particle_parse.h"
  14. #include "rendertexture.h"
  15. #ifdef PORTAL
  16. #include "PortalRender.h"
  17. #endif
  18. #pragma warning( disable: 4355 ) // warning C4355: 'this' : used in base member initializer list
  19. class CClientTools;
  20. void DrawSpriteModel( IClientEntity *baseentity, CEngineSprite *psprite,
  21. const Vector &origin, float fscale, float frame,
  22. int rendermode, int r, int g, int b, int a,
  23. const Vector& forward, const Vector& right, const Vector& up, float flHDRColorScale = 1.0f );
  24. float StandardGlowBlend( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle,
  25. int rendermode, int renderfx, int alpha, float *pscale );
  26. // Interface from engine to tools for manipulating entities
  27. class CClientTools : public IClientTools, public IClientEntityListener
  28. {
  29. public:
  30. CClientTools();
  31. virtual HTOOLHANDLE AttachToEntity( EntitySearchResult entityToAttach );
  32. virtual void DetachFromEntity( EntitySearchResult entityToDetach );
  33. virtual bool IsValidHandle( HTOOLHANDLE handle );
  34. virtual int GetNumRecordables();
  35. virtual HTOOLHANDLE GetRecordable( int index );
  36. // Iterates through ALL entities (separate list for client vs. server)
  37. virtual EntitySearchResult NextEntity( EntitySearchResult currentEnt );
  38. // Use this to turn on/off the presence of an underlying game entity
  39. virtual void SetEnabled( HTOOLHANDLE handle, bool enabled );
  40. virtual void SetRecording( HTOOLHANDLE handle, bool recording );
  41. virtual bool ShouldRecord( HTOOLHANDLE handle );
  42. virtual int GetModelIndex( HTOOLHANDLE handle );
  43. virtual const char* GetModelName ( HTOOLHANDLE handle );
  44. virtual const char* GetClassname ( HTOOLHANDLE handle );
  45. virtual HTOOLHANDLE GetToolHandleForEntityByIndex( int entindex );
  46. virtual void AddClientRenderable( IClientRenderable *pRenderable, int renderGroup );
  47. virtual void RemoveClientRenderable( IClientRenderable *pRenderable );
  48. virtual void SetRenderGroup( IClientRenderable *pRenderable, int renderGroup );
  49. virtual void MarkClientRenderableDirty( IClientRenderable *pRenderable );
  50. virtual bool DrawSprite( IClientRenderable *pRenderable,
  51. float scale, float frame,
  52. int rendermode, int renderfx,
  53. const Color &color, float flProxyRadius, int *pVisHandle );
  54. virtual bool GetLocalPlayerEyePosition( Vector& org, QAngle& ang, float &fov );
  55. virtual EntitySearchResult GetLocalPlayer();
  56. virtual ClientShadowHandle_t CreateShadow( CBaseHandle h, int nFlags );
  57. virtual void DestroyShadow( ClientShadowHandle_t h );
  58. virtual ClientShadowHandle_t CreateFlashlight( const FlashlightState_t &lightState );
  59. virtual void DestroyFlashlight( ClientShadowHandle_t h );
  60. virtual void UpdateFlashlightState( ClientShadowHandle_t h, const FlashlightState_t &flashlightState );
  61. virtual void AddToDirtyShadowList( ClientShadowHandle_t h, bool force = false );
  62. virtual void MarkRenderToTextureShadowDirty( ClientShadowHandle_t h );
  63. virtual void UpdateProjectedTexture( ClientShadowHandle_t h, bool bForce );
  64. // Global toggle for recording
  65. virtual void EnableRecordingMode( bool bEnable );
  66. virtual bool IsInRecordingMode() const;
  67. // Trigger a temp entity
  68. virtual void TriggerTempEntity( KeyValues *pKeyValues );
  69. // get owning weapon (for viewmodels)
  70. virtual int GetOwningWeaponEntIndex( int entindex );
  71. virtual int GetEntIndex( EntitySearchResult entityToAttach );
  72. virtual int FindGlobalFlexcontroller( char const *name );
  73. virtual char const *GetGlobalFlexControllerName( int idx );
  74. // helper for traversing ownership hierarchy
  75. virtual EntitySearchResult GetOwnerEntity( EntitySearchResult currentEnt );
  76. // common and useful types to query for hierarchically
  77. virtual bool IsPlayer( EntitySearchResult entityToAttach );
  78. virtual bool IsBaseCombatCharacter( EntitySearchResult entityToAttach );
  79. virtual bool IsNPC( EntitySearchResult entityToAttach );
  80. virtual Vector GetAbsOrigin( HTOOLHANDLE handle );
  81. virtual QAngle GetAbsAngles( HTOOLHANDLE handle );
  82. virtual void ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen );
  83. // Sends a mesage from the tool to the client
  84. virtual void PostToolMessage( KeyValues *pKeyValues );
  85. // Indicates whether the client should render particle systems
  86. virtual void EnableParticleSystems( bool bEnable );
  87. // Is the game rendering in 3rd person mode?
  88. virtual bool IsRenderingThirdPerson() const;
  89. public:
  90. C_BaseEntity *LookupEntity( HTOOLHANDLE handle );
  91. // IClientEntityListener methods
  92. void OnEntityDeleted( C_BaseEntity *pEntity );
  93. void OnEntityCreated( C_BaseEntity *pEntity );
  94. private:
  95. struct HToolEntry_t
  96. {
  97. HToolEntry_t() : m_Handle( 0 ) {}
  98. HToolEntry_t( int handle, C_BaseEntity *pEntity = NULL )
  99. : m_Handle( handle ), m_hEntity( pEntity )
  100. {
  101. if ( pEntity )
  102. {
  103. m_hEntity->SetToolHandle( m_Handle );
  104. }
  105. }
  106. int m_Handle;
  107. EHANDLE m_hEntity;
  108. };
  109. static int s_nNextHandle;
  110. static bool HandleLessFunc( const HToolEntry_t& lhs, const HToolEntry_t& rhs )
  111. {
  112. return lhs.m_Handle < rhs.m_Handle;
  113. }
  114. CUtlRBTree< HToolEntry_t > m_Handles;
  115. CUtlVector< int > m_ActiveHandles;
  116. bool m_bInRecordingMode;
  117. };
  118. //-----------------------------------------------------------------------------
  119. // Statics
  120. //-----------------------------------------------------------------------------
  121. int CClientTools::s_nNextHandle = 1;
  122. //-----------------------------------------------------------------------------
  123. // Singleton instance
  124. //-----------------------------------------------------------------------------
  125. static CClientTools s_ClientTools;
  126. IClientTools *clienttools = &s_ClientTools;
  127. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CClientTools, IClientTools, VCLIENTTOOLS_INTERFACE_VERSION, s_ClientTools );
  128. //-----------------------------------------------------------------------------
  129. // Constructor
  130. //-----------------------------------------------------------------------------
  131. CClientTools::CClientTools() : m_Handles( 0, 0, HandleLessFunc )
  132. {
  133. m_bInRecordingMode = false;
  134. cl_entitylist->AddListenerEntity( this );
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Global toggle for recording
  138. //-----------------------------------------------------------------------------
  139. void CClientTools::EnableRecordingMode( bool bEnable )
  140. {
  141. m_bInRecordingMode = bEnable;
  142. }
  143. bool CClientTools::IsInRecordingMode() const
  144. {
  145. return m_bInRecordingMode;
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Trigger a temp entity
  149. //-----------------------------------------------------------------------------
  150. void CClientTools::TriggerTempEntity( KeyValues *pKeyValues )
  151. {
  152. te->TriggerTempEntity( pKeyValues );
  153. }
  154. //-----------------------------------------------------------------------------
  155. // get owning weapon (for viewmodels)
  156. //-----------------------------------------------------------------------------
  157. int CClientTools::GetOwningWeaponEntIndex( int entindex )
  158. {
  159. C_BaseEntity *pEnt = C_BaseEntity::Instance( entindex );
  160. C_BaseViewModel *pViewModel = dynamic_cast< C_BaseViewModel* >( pEnt );
  161. if ( pViewModel )
  162. {
  163. C_BaseCombatWeapon *pWeapon = pViewModel->GetOwningWeapon();
  164. if ( pWeapon )
  165. {
  166. return pWeapon->entindex();
  167. }
  168. }
  169. return -1;
  170. }
  171. int CClientTools::GetEntIndex( EntitySearchResult entityToAttach )
  172. {
  173. C_BaseEntity *ent = reinterpret_cast< C_BaseEntity * >( entityToAttach );
  174. return ent ? ent->entindex() : 0;
  175. }
  176. void CClientTools::AddClientRenderable( IClientRenderable *pRenderable, int renderGroup )
  177. {
  178. Assert( pRenderable );
  179. cl_entitylist->AddNonNetworkableEntity( pRenderable->GetIClientUnknown() );
  180. ClientRenderHandle_t handle = pRenderable->RenderHandle();
  181. if ( INVALID_CLIENT_RENDER_HANDLE == handle )
  182. {
  183. // create new renderer handle
  184. ClientLeafSystem()->AddRenderable( pRenderable, (RenderGroup_t)renderGroup );
  185. }
  186. else
  187. {
  188. // handle already exists, just update group & origin
  189. ClientLeafSystem()->SetRenderGroup( pRenderable->RenderHandle(), (RenderGroup_t)renderGroup );
  190. ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() );
  191. }
  192. }
  193. void CClientTools::RemoveClientRenderable( IClientRenderable *pRenderable )
  194. {
  195. ClientRenderHandle_t handle = pRenderable->RenderHandle();
  196. if( handle != INVALID_CLIENT_RENDER_HANDLE )
  197. {
  198. ClientLeafSystem()->RemoveRenderable( handle );
  199. }
  200. cl_entitylist->RemoveEntity( pRenderable->GetIClientUnknown()->GetRefEHandle() );
  201. }
  202. void CClientTools::MarkClientRenderableDirty( IClientRenderable *pRenderable )
  203. {
  204. ClientRenderHandle_t handle = pRenderable->RenderHandle();
  205. if ( INVALID_CLIENT_RENDER_HANDLE != handle )
  206. {
  207. // handle already exists, just update group & origin
  208. ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() );
  209. }
  210. }
  211. void CClientTools::SetRenderGroup( IClientRenderable *pRenderable, int renderGroup )
  212. {
  213. ClientRenderHandle_t handle = pRenderable->RenderHandle();
  214. if ( INVALID_CLIENT_RENDER_HANDLE == handle )
  215. {
  216. // create new renderer handle
  217. ClientLeafSystem()->AddRenderable( pRenderable, (RenderGroup_t)renderGroup );
  218. }
  219. else
  220. {
  221. // handle already exists, just update group & origin
  222. ClientLeafSystem()->SetRenderGroup( pRenderable->RenderHandle(), (RenderGroup_t)renderGroup );
  223. ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() );
  224. }
  225. }
  226. bool CClientTools::DrawSprite( IClientRenderable *pRenderable, float scale, float frame, int rendermode, int renderfx, const Color &color, float flProxyRadius, int *pVisHandle )
  227. {
  228. Vector origin = pRenderable->GetRenderOrigin();
  229. QAngle angles = pRenderable->GetRenderAngles();
  230. // Get extra data
  231. CEngineSprite *psprite = (CEngineSprite *)modelinfo->GetModelExtraData( pRenderable->GetModel() );
  232. if ( !psprite )
  233. return false;
  234. // Get orthonormal bases for current view - re-align to current camera (vs. recorded camera)
  235. Vector forward, right, up;
  236. C_SpriteRenderer::GetSpriteAxes( ( C_SpriteRenderer::SPRITETYPE )psprite->GetOrientation(), origin, angles, forward, right, up );
  237. int r = color.r();
  238. int g = color.g();
  239. int b = color.b();
  240. float oldBlend = render->GetBlend();
  241. if ( rendermode != kRenderNormal )
  242. {
  243. // kRenderGlow and kRenderWorldGlow have a special blending function
  244. if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow ))
  245. {
  246. pixelvis_queryparams_t params;
  247. if ( flProxyRadius != 0.0f )
  248. {
  249. params.Init( origin, flProxyRadius );
  250. params.bSizeInScreenspace = true;
  251. }
  252. else
  253. {
  254. params.Init( origin );
  255. }
  256. float blend = oldBlend * StandardGlowBlend( params, ( pixelvis_handle_t* )pVisHandle, rendermode, renderfx, color.a(), &scale );
  257. if ( blend <= 0.0f )
  258. return false;
  259. //Fade out the sprite depending on distance from the view origin.
  260. r *= blend;
  261. g *= blend;
  262. b *= blend;
  263. render->SetBlend( blend );
  264. }
  265. }
  266. DrawSpriteModel( ( IClientEntity* )pRenderable, psprite, origin, scale, frame, rendermode, r, g, b, color.a(), forward, right, up );
  267. if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow ))
  268. {
  269. render->SetBlend( oldBlend );
  270. }
  271. return true;
  272. }
  273. HTOOLHANDLE CClientTools::AttachToEntity( EntitySearchResult entityToAttach )
  274. {
  275. C_BaseEntity *ent = reinterpret_cast< C_BaseEntity * >( entityToAttach );
  276. Assert( ent );
  277. if ( !ent )
  278. return (HTOOLHANDLE)0;
  279. HTOOLHANDLE curHandle = ent->GetToolHandle();
  280. if ( curHandle != 0 )
  281. return curHandle; // Already attaached
  282. HToolEntry_t newHandle( s_nNextHandle++, ent );
  283. m_Handles.Insert( newHandle );
  284. m_ActiveHandles.AddToTail( newHandle.m_Handle );
  285. return (HTOOLHANDLE)newHandle.m_Handle;
  286. }
  287. void CClientTools::DetachFromEntity( EntitySearchResult entityToDetach )
  288. {
  289. C_BaseEntity *ent = reinterpret_cast< C_BaseEntity * >( entityToDetach );
  290. Assert( ent );
  291. if ( !ent )
  292. return;
  293. HTOOLHANDLE handle = ent->GetToolHandle();
  294. ent->SetToolHandle( (HTOOLHANDLE)0 );
  295. if ( handle == (HTOOLHANDLE)0 )
  296. {
  297. Assert( 0 );
  298. return;
  299. }
  300. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  301. if ( idx == m_Handles.InvalidIndex() )
  302. {
  303. Assert( 0 );
  304. return;
  305. }
  306. m_Handles.RemoveAt( idx );
  307. m_ActiveHandles.FindAndRemove( handle );
  308. }
  309. //-----------------------------------------------------------------------------
  310. // Purpose:
  311. // Input : handle -
  312. // Output : C_BaseEntity
  313. //-----------------------------------------------------------------------------
  314. C_BaseEntity *CClientTools::LookupEntity( HTOOLHANDLE handle )
  315. {
  316. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  317. if ( idx == m_Handles.InvalidIndex() )
  318. return NULL;
  319. return m_Handles[ idx ].m_hEntity;
  320. }
  321. int CClientTools::GetNumRecordables()
  322. {
  323. return m_ActiveHandles.Count();
  324. }
  325. HTOOLHANDLE CClientTools::GetRecordable( int index )
  326. {
  327. if ( index < 0 || index >= m_ActiveHandles.Count() )
  328. {
  329. Assert( 0 );
  330. return (HTOOLHANDLE)0;
  331. }
  332. return m_ActiveHandles[ index ];
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Iterates through ALL entities (separate list for client vs. server)
  336. //-----------------------------------------------------------------------------
  337. EntitySearchResult CClientTools::NextEntity( EntitySearchResult currentEnt )
  338. {
  339. C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
  340. if ( ent == NULL )
  341. {
  342. ent = cl_entitylist->FirstBaseEntity();
  343. }
  344. else
  345. {
  346. ent = cl_entitylist->NextBaseEntity( ent );
  347. }
  348. return reinterpret_cast< EntitySearchResult >( ent );
  349. }
  350. //-----------------------------------------------------------------------------
  351. // Use this to turn on/off the presence of an underlying game entity
  352. //-----------------------------------------------------------------------------
  353. void CClientTools::SetEnabled( HTOOLHANDLE handle, bool enabled )
  354. {
  355. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  356. if ( idx == m_Handles.InvalidIndex() )
  357. return;
  358. HToolEntry_t *slot = &m_Handles[ idx ];
  359. Assert( slot );
  360. if ( slot == NULL )
  361. return;
  362. C_BaseEntity *ent = slot->m_hEntity.Get();
  363. if ( ent == NULL || ent->entindex() == 0 )
  364. return; // Don't disable/enable the "world"
  365. ent->EnableInToolView( enabled );
  366. }
  367. //-----------------------------------------------------------------------------
  368. // Purpose:
  369. //-----------------------------------------------------------------------------
  370. void CClientTools::SetRecording( HTOOLHANDLE handle, bool recording )
  371. {
  372. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  373. if ( idx == m_Handles.InvalidIndex() )
  374. return;
  375. HToolEntry_t &entry = m_Handles[ idx ];
  376. if ( entry.m_hEntity )
  377. {
  378. entry.m_hEntity->SetToolRecording( recording );
  379. }
  380. }
  381. bool CClientTools::ShouldRecord( HTOOLHANDLE handle )
  382. {
  383. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  384. if ( idx == m_Handles.InvalidIndex() )
  385. return false;
  386. HToolEntry_t &entry = m_Handles[ idx ];
  387. return entry.m_hEntity && entry.m_hEntity->ShouldRecordInTools();
  388. }
  389. //-----------------------------------------------------------------------------
  390. // Purpose:
  391. //-----------------------------------------------------------------------------
  392. int CClientTools::GetModelIndex( HTOOLHANDLE handle )
  393. {
  394. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  395. if ( idx == m_Handles.InvalidIndex() )
  396. return NULL;
  397. HToolEntry_t &entry = m_Handles[ idx ];
  398. if ( entry.m_hEntity )
  399. {
  400. return entry.m_hEntity->GetModelIndex();
  401. }
  402. Assert( 0 );
  403. return 0;
  404. }
  405. //-----------------------------------------------------------------------------
  406. // Purpose:
  407. //-----------------------------------------------------------------------------
  408. const char* CClientTools::GetModelName( HTOOLHANDLE handle )
  409. {
  410. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  411. if ( idx == m_Handles.InvalidIndex() )
  412. return NULL;
  413. HToolEntry_t &entry = m_Handles[ idx ];
  414. if ( entry.m_hEntity )
  415. {
  416. return STRING( entry.m_hEntity->GetModelName() );
  417. }
  418. Assert( 0 );
  419. return NULL;
  420. }
  421. //-----------------------------------------------------------------------------
  422. // Purpose:
  423. //-----------------------------------------------------------------------------
  424. const char* CClientTools::GetClassname( HTOOLHANDLE handle )
  425. {
  426. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  427. if ( idx == m_Handles.InvalidIndex() )
  428. return NULL;
  429. HToolEntry_t &entry = m_Handles[ idx ];
  430. if ( entry.m_hEntity )
  431. {
  432. return STRING( entry.m_hEntity->GetClassname() );
  433. }
  434. Assert( 0 );
  435. return NULL;
  436. }
  437. //-----------------------------------------------------------------------------
  438. // Purpose:
  439. // Input : handle -
  440. //-----------------------------------------------------------------------------
  441. bool CClientTools::IsValidHandle( HTOOLHANDLE handle )
  442. {
  443. return m_Handles.Find( HToolEntry_t( handle ) ) != m_Handles.InvalidIndex();
  444. }
  445. void CClientTools::OnEntityDeleted( CBaseEntity *pEntity )
  446. {
  447. HTOOLHANDLE handle = pEntity ? pEntity->GetToolHandle() : (HTOOLHANDLE)0;
  448. if ( handle == (HTOOLHANDLE)0 )
  449. return;
  450. if ( m_bInRecordingMode )
  451. {
  452. // Send deletion message to tool interface
  453. KeyValues *kv = new KeyValues( "deleted" );
  454. ToolFramework_PostToolMessage( handle, kv );
  455. kv->deleteThis();
  456. }
  457. DetachFromEntity( pEntity );
  458. }
  459. void CClientTools::OnEntityCreated( CBaseEntity *pEntity )
  460. {
  461. if ( !m_bInRecordingMode )
  462. return;
  463. HTOOLHANDLE h = AttachToEntity( pEntity );
  464. // Send deletion message to tool interface
  465. KeyValues *kv = new KeyValues( "created" );
  466. ToolFramework_PostToolMessage( h, kv );
  467. kv->deleteThis();
  468. }
  469. HTOOLHANDLE CClientTools::GetToolHandleForEntityByIndex( int entindex )
  470. {
  471. C_BaseEntity *ent = C_BaseEntity::Instance( entindex );
  472. if ( !ent )
  473. return (HTOOLHANDLE)0;
  474. return ent->GetToolHandle();
  475. }
  476. EntitySearchResult CClientTools::GetLocalPlayer()
  477. {
  478. C_BasePlayer *p = C_BasePlayer::GetLocalPlayer();
  479. return reinterpret_cast< EntitySearchResult >( p );
  480. }
  481. bool CClientTools::GetLocalPlayerEyePosition( Vector& org, QAngle& ang, float &fov )
  482. {
  483. C_BasePlayer *pl = C_BasePlayer::GetLocalPlayer();
  484. if ( pl == NULL )
  485. return false;
  486. org = pl->EyePosition();
  487. ang = pl->EyeAngles();
  488. fov = pl->GetFOV();
  489. return true;
  490. }
  491. //-----------------------------------------------------------------------------
  492. // Create, destroy shadow
  493. //-----------------------------------------------------------------------------
  494. ClientShadowHandle_t CClientTools::CreateShadow( CBaseHandle h, int nFlags )
  495. {
  496. return g_pClientShadowMgr->CreateShadow( h, nFlags );
  497. }
  498. void CClientTools::DestroyShadow( ClientShadowHandle_t h )
  499. {
  500. g_pClientShadowMgr->DestroyShadow( h );
  501. }
  502. ClientShadowHandle_t CClientTools::CreateFlashlight( const FlashlightState_t &lightState )
  503. {
  504. return g_pClientShadowMgr->CreateFlashlight( lightState );
  505. }
  506. void CClientTools::DestroyFlashlight( ClientShadowHandle_t h )
  507. {
  508. g_pClientShadowMgr->DestroyFlashlight( h );
  509. }
  510. void CClientTools::UpdateFlashlightState( ClientShadowHandle_t h, const FlashlightState_t &lightState )
  511. {
  512. g_pClientShadowMgr->UpdateFlashlightState( h, lightState );
  513. }
  514. void CClientTools::AddToDirtyShadowList( ClientShadowHandle_t h, bool force )
  515. {
  516. g_pClientShadowMgr->AddToDirtyShadowList( h, force );
  517. }
  518. void CClientTools::MarkRenderToTextureShadowDirty( ClientShadowHandle_t h )
  519. {
  520. g_pClientShadowMgr->MarkRenderToTextureShadowDirty( h );
  521. }
  522. void CClientTools::UpdateProjectedTexture( ClientShadowHandle_t h, bool bForce )
  523. {
  524. g_pClientShadowMgr->UpdateProjectedTexture( h, bForce );
  525. }
  526. int CClientTools::FindGlobalFlexcontroller( char const *name )
  527. {
  528. return C_BaseFlex::AddGlobalFlexController( (char *)name );
  529. }
  530. char const *CClientTools::GetGlobalFlexControllerName( int idx )
  531. {
  532. return C_BaseFlex::GetGlobalFlexControllerName( idx );
  533. }
  534. //-----------------------------------------------------------------------------
  535. // helper for traversing ownership hierarchy
  536. //-----------------------------------------------------------------------------
  537. EntitySearchResult CClientTools::GetOwnerEntity( EntitySearchResult currentEnt )
  538. {
  539. C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
  540. return ent ? ent->GetOwnerEntity() : NULL;
  541. }
  542. //-----------------------------------------------------------------------------
  543. // common and useful types to query for hierarchically
  544. //-----------------------------------------------------------------------------
  545. bool CClientTools::IsPlayer( EntitySearchResult currentEnt )
  546. {
  547. C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
  548. return ent ? ent->IsPlayer() : false;
  549. }
  550. bool CClientTools::IsBaseCombatCharacter( EntitySearchResult currentEnt )
  551. {
  552. C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
  553. return ent ? ent->IsBaseCombatCharacter() : false;
  554. }
  555. bool CClientTools::IsNPC( EntitySearchResult currentEnt )
  556. {
  557. C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
  558. return ent ? ent->IsNPC() : false;
  559. }
  560. Vector CClientTools::GetAbsOrigin( HTOOLHANDLE handle )
  561. {
  562. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  563. if ( idx == m_Handles.InvalidIndex() )
  564. return vec3_origin;
  565. HToolEntry_t &entry = m_Handles[ idx ];
  566. if ( entry.m_hEntity )
  567. {
  568. return entry.m_hEntity->GetAbsOrigin();
  569. }
  570. Assert( 0 );
  571. return vec3_origin;
  572. }
  573. QAngle CClientTools::GetAbsAngles( HTOOLHANDLE handle )
  574. {
  575. int idx = m_Handles.Find( HToolEntry_t( handle ) );
  576. if ( idx == m_Handles.InvalidIndex() )
  577. return vec3_angle;
  578. HToolEntry_t &entry = m_Handles[ idx ];
  579. if ( entry.m_hEntity )
  580. {
  581. return entry.m_hEntity->GetAbsAngles();
  582. }
  583. Assert( 0 );
  584. return vec3_angle;
  585. }
  586. //-----------------------------------------------------------------------------
  587. // Sends a mesage from the tool to the client
  588. //-----------------------------------------------------------------------------
  589. void CClientTools::PostToolMessage( KeyValues *pKeyValues )
  590. {
  591. if ( !Q_stricmp( pKeyValues->GetName(), "QueryParticleManifest" ) )
  592. {
  593. // NOTE: This cannot be done during particle system init because tools aren't set up at that point
  594. CUtlVector<CUtlString> files;
  595. GetParticleManifest( files );
  596. int nCount = files.Count();
  597. for ( int i = 0; i < nCount; ++i )
  598. {
  599. char pTemp[256];
  600. Q_snprintf( pTemp, sizeof(pTemp), "%d", i );
  601. KeyValues *pSubKey = pKeyValues->FindKey( pTemp, true );
  602. pSubKey->SetString( "file", files[i] );
  603. }
  604. return;
  605. }
  606. if ( !Q_stricmp( pKeyValues->GetName(), "QueryMonitorTexture" ) )
  607. {
  608. pKeyValues->SetPtr( "texture", GetCameraTexture() );
  609. return;
  610. }
  611. #ifdef PORTAL
  612. if ( !Q_stricmp( pKeyValues->GetName(), "portals" ) )
  613. {
  614. g_pPortalRender->HandlePortalPlaybackMessage( pKeyValues );
  615. return;
  616. }
  617. if ( !Q_stricmp( pKeyValues->GetName(), "query CPortalRenderer" ) )
  618. {
  619. pKeyValues->SetInt( "IsRenderingPortal", g_pPortalRender->IsRenderingPortal() ? 1 : 0 );
  620. return;
  621. }
  622. #endif
  623. }
  624. //-----------------------------------------------------------------------------
  625. // Indicates whether the client should render particle systems
  626. //-----------------------------------------------------------------------------
  627. void CClientTools::EnableParticleSystems( bool bEnable )
  628. {
  629. ParticleMgr()->RenderParticleSystems( bEnable );
  630. }
  631. //-----------------------------------------------------------------------------
  632. // Is the game rendering in 3rd person mode?
  633. //-----------------------------------------------------------------------------
  634. bool CClientTools::IsRenderingThirdPerson() const
  635. {
  636. return !C_BasePlayer::LocalPlayerInFirstPersonView();
  637. }
  638. //-----------------------------------------------------------------------------
  639. // Reload particle definitions
  640. //-----------------------------------------------------------------------------
  641. void CClientTools::ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen )
  642. {
  643. // Remove all new effects, because we are going to free internal structures they point to
  644. ParticleMgr()->RemoveAllNewEffects();
  645. // FIXME: Use file name to determine if we care about this data
  646. CUtlBuffer buf( pBufData, nLen, CUtlBuffer::READ_ONLY );
  647. g_pParticleSystemMgr->ReadParticleConfigFile( buf, true );
  648. }