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.

681 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "tf_hud_annotationspanel.h"
  9. #include "vgui_controls/AnimationController.h"
  10. #include "iclientmode.h"
  11. #include "c_tf_player.h"
  12. #include "c_tf_playerresource.h"
  13. #include <vgui_controls/Label.h>
  14. #include <vgui/ILocalize.h>
  15. #include <vgui/ISurface.h>
  16. #include "c_baseobject.h"
  17. #include "fmtstr.h"
  18. #include "tf_gamerules.h"
  19. #include "tf_hud_statpanel.h"
  20. #include "view.h"
  21. #include "ivieweffects.h"
  22. #include "viewrender.h"
  23. #include "tf_gamerules.h"
  24. #include "tf_hud_training.h"
  25. // memdbgon must be the last include file in a .cpp file!!!
  26. #include "tier0/memdbgon.h"
  27. DECLARE_HUDELEMENT_DEPTH( CTFAnnotationsPanel, 1 );
  28. static const float LIFE_TIME = 1.0f;
  29. //-----------------------------------------------------------------------------
  30. // Purpose: Constructor
  31. //-----------------------------------------------------------------------------
  32. CTFAnnotationsPanel::CTFAnnotationsPanel( const char *pElementName )
  33. : EditablePanel( NULL, "AnnotationsPanel" ), CHudElement( pElementName )
  34. {
  35. vgui::Panel *pParent = g_pClientMode->GetViewport();
  36. SetParent( pParent );
  37. m_bShouldBeVisible = false;
  38. SetScheme( "ClientScheme" );
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose:
  42. //-----------------------------------------------------------------------------
  43. CTFAnnotationsPanel::~CTFAnnotationsPanel()
  44. {
  45. Reset();
  46. }
  47. //-----------------------------------------------------------------------------
  48. // Purpose:
  49. //-----------------------------------------------------------------------------
  50. void CTFAnnotationsPanel::Reset()
  51. {
  52. RemoveAll();
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Purpose:
  56. //-----------------------------------------------------------------------------
  57. void CTFAnnotationsPanel::Init()
  58. {
  59. // listen for events
  60. ListenForGameEvent( "show_annotation" );
  61. ListenForGameEvent( "hide_annotation" );
  62. RemoveAll();
  63. CHudElement::Init();
  64. }
  65. //-----------------------------------------------------------------------------
  66. // Purpose: Applies scheme settings
  67. //-----------------------------------------------------------------------------
  68. void CTFAnnotationsPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
  69. {
  70. BaseClass::ApplySchemeSettings( pScheme );
  71. }
  72. //-----------------------------------------------------------------------------
  73. // Purpose:
  74. //-----------------------------------------------------------------------------
  75. void CTFAnnotationsPanel::FireGameEvent( IGameEvent * event )
  76. {
  77. const char *pEventName = event->GetName();
  78. if ( Q_strcmp( "hide_annotation", pEventName ) == 0 )
  79. {
  80. HideAnnotation( event->GetInt("id") );
  81. }
  82. else if ( Q_strcmp( "show_annotation", pEventName ) == 0 )
  83. {
  84. AddAnnotation( event );
  85. }
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Purpose:
  89. //-----------------------------------------------------------------------------
  90. CTFAnnotationsPanelCallout *CTFAnnotationsPanel::TestAndAddCallout( int id, Vector &origin, const char *text )
  91. {
  92. int insertSlot = -1;
  93. // Find an available slot and also see if this call out already exists in the list.
  94. for (int i=0; i<m_pCalloutPanels.Count(); ++i)
  95. {
  96. if (NULL == m_pCalloutPanels[i])
  97. {
  98. insertSlot = i;
  99. continue;
  100. }
  101. // If we already have this annotation, return and don't add it again.
  102. if (m_pCalloutPanels[i]->GetAnnotationID() == id)
  103. {
  104. m_pCalloutPanels[i]->SetText( text );
  105. m_pCalloutPanels[i]->SetLocation( origin );
  106. m_pCalloutPanels[i]->SetFollowEntity( NULL );
  107. m_pCalloutPanels[i]->InvalidateLayout();
  108. return m_pCalloutPanels[i];
  109. }
  110. // if one is available, use it
  111. if ( m_pCalloutPanels[i]->IsVisible() == false )
  112. {
  113. insertSlot = i;
  114. continue;
  115. }
  116. }
  117. CTFAnnotationsPanelCallout *pCallout = new CTFAnnotationsPanelCallout( g_pClientMode->GetViewport(), "AnnotationsPanelCallout", id, origin, text );
  118. if (-1 == insertSlot)
  119. {
  120. m_pCalloutPanels.AddToTail( vgui::SETUP_PANEL(pCallout) );
  121. }
  122. else
  123. {
  124. if ( m_pCalloutPanels[insertSlot] != NULL )
  125. {
  126. m_pCalloutPanels[insertSlot]->MarkForDeletion();
  127. }
  128. m_pCalloutPanels[insertSlot] = vgui::SETUP_PANEL(pCallout);
  129. }
  130. return pCallout;
  131. }
  132. void CTFAnnotationsPanel::UpdateAnnotations( void )
  133. {
  134. //Find an available slot and also see if this call out already exists in the list.
  135. for ( int i = m_pCalloutPanels.Count()-1; i >= 0; i-- )
  136. {
  137. if ( !m_pCalloutPanels[i] )
  138. {
  139. m_pCalloutPanels.Remove(i);
  140. continue;
  141. }
  142. // Update the callout. If it says it's finished, remove it.
  143. if ( m_pCalloutPanels[i]->UpdateCallout() )
  144. {
  145. m_pCalloutPanels[i]->MarkForDeletion();
  146. m_pCalloutPanels.Remove(i);
  147. }
  148. }
  149. // If we have no active callouts, hide
  150. if ( !m_pCalloutPanels.Count() )
  151. {
  152. m_bShouldBeVisible = false;
  153. }
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Purpose:
  157. //-----------------------------------------------------------------------------
  158. void CTFAnnotationsPanel::AddAnnotation( IGameEvent * event )
  159. {
  160. const char *text = event->GetString( "text" );
  161. int id = event->GetInt("id");
  162. float x = event->GetFloat("worldPosX");
  163. float y = event->GetFloat("worldPosY");
  164. float z = event->GetFloat("worldPosZ");
  165. int iVisibilityBitfield = event->GetInt("visibilityBitfield");
  166. float flLifetime = event->GetFloat("lifetime");
  167. int iFollowEntIndex = event->GetInt("follow_entindex");
  168. bool bShowDistance = event->GetBool("show_distance");
  169. const char *pSound = event->GetString( "play_sound" );
  170. bool bShowEffect = event->GetBool( "show_effect" );
  171. Vector location;
  172. location.x = x;
  173. location.y = y;
  174. location.z = z;
  175. m_bShouldBeVisible = true;
  176. // Try and add the callout
  177. CTFAnnotationsPanelCallout *pCallout = TestAndAddCallout( id, location, text );
  178. if ( pCallout )
  179. {
  180. C_BaseEntity *pFollowEntity = iFollowEntIndex != 0 ? ClientEntityList().GetEnt( iFollowEntIndex) : NULL;
  181. pCallout->Touch();
  182. pCallout->SetLifetime( flLifetime );
  183. pCallout->SetVisibilityBitfield( iVisibilityBitfield );
  184. pCallout->SetFollowEntity( pFollowEntity );
  185. pCallout->SetShowDistance( bShowDistance );
  186. pCallout->UpdateCallout();
  187. if ( pCallout->IsVisible() )
  188. {
  189. if ( pSound )
  190. {
  191. vgui::surface()->PlaySound( pSound );
  192. }
  193. if ( bShowEffect )
  194. {
  195. if ( pFollowEntity && pFollowEntity->ParticleProp())
  196. {
  197. pFollowEntity->ParticleProp()->Create( "ping_circle", PATTACH_ABSORIGIN_FOLLOW );
  198. }
  199. else
  200. {
  201. Vector vecNormal( event->GetFloat("worldNormalX"), event->GetFloat("worldNormalY"), event->GetFloat("worldNormalZ") );
  202. Vector vecOrigin( x, y, z );
  203. vecOrigin += vecNormal * 20.0f;
  204. QAngle vecAngles;
  205. VectorAngles( vecNormal, vecAngles );
  206. DispatchParticleEffect( "ping_circle", vecOrigin, vecAngles );
  207. }
  208. }
  209. }
  210. }
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Purpose:
  214. //-----------------------------------------------------------------------------
  215. void CTFAnnotationsPanel::HideAnnotation( int id )
  216. {
  217. // Delete all our callout panels
  218. for ( int i = m_pCalloutPanels.Count()-1; i >= 0; i-- )
  219. {
  220. if ( m_pCalloutPanels[i]->GetAnnotationID() == id )
  221. {
  222. m_pCalloutPanels[i]->FadeAndRemove();
  223. break;
  224. }
  225. }
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Purpose:
  229. //-----------------------------------------------------------------------------
  230. void CTFAnnotationsPanel::RemoveAll()
  231. {
  232. m_bShouldBeVisible = false;
  233. // Delete all our callout panels
  234. for ( int i = m_pCalloutPanels.Count()-1; i >= 0; i-- )
  235. {
  236. m_pCalloutPanels[i]->MarkForDeletion();
  237. }
  238. m_pCalloutPanels.RemoveAll();
  239. }
  240. //-----------------------------------------------------------------------------
  241. // Purpose:
  242. //-----------------------------------------------------------------------------
  243. bool CTFAnnotationsPanel::ShouldDraw( void )
  244. {
  245. return m_bShouldBeVisible;
  246. }
  247. //-----------------------------------------------------------------------------
  248. // Purpose:
  249. //-----------------------------------------------------------------------------
  250. void CTFAnnotationsPanel::OnThink( void )
  251. {
  252. BaseClass::OnThink();
  253. if ( IsVisible() )
  254. {
  255. UpdateAnnotations();
  256. }
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Purpose:
  260. //-----------------------------------------------------------------------------
  261. CTFAnnotationsPanelCallout::~CTFAnnotationsPanelCallout()
  262. {
  263. if ( m_pArrowImages )
  264. {
  265. m_pArrowImages->deleteThis();
  266. }
  267. }
  268. //-----------------------------------------------------------------------------
  269. // Purpose:
  270. //-----------------------------------------------------------------------------
  271. CTFAnnotationsPanelCallout::CTFAnnotationsPanelCallout( Panel *parent, const char *name, int id, Vector &location, const char* text ) : EditablePanel( parent, name )
  272. {
  273. m_pAnnotationLabel = NULL;
  274. m_pDistanceLabel = NULL;
  275. m_pArrowImages = NULL;
  276. m_ID = id;
  277. m_Location = location;
  278. m_Text = text;
  279. m_DeathTime = 0.0f;
  280. m_flLerpPercentage = 1.0f;
  281. m_bWasOffscreen = false;
  282. m_bShowDistance = false;
  283. m_flAlpha[0] = m_flAlpha[1] = 0.0f;
  284. SetWorldPositionCurrentFrame( true );
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Purpose: Applies scheme settings
  288. //-----------------------------------------------------------------------------
  289. void CTFAnnotationsPanelCallout::ApplySettings( KeyValues *pInResourceData )
  290. {
  291. BaseClass::ApplySettings( pInResourceData );
  292. if ( !m_pArrowImages )
  293. {
  294. KeyValues *pArrowImagesSubKey = pInResourceData->FindKey( "ArrowIcons" ); AssertMsg( pArrowImagesSubKey, "This must exist!" );
  295. m_pArrowImages = pArrowImagesSubKey->MakeCopy();
  296. }
  297. }
  298. //-----------------------------------------------------------------------------
  299. // Purpose: Applies scheme settings
  300. //-----------------------------------------------------------------------------
  301. void CTFAnnotationsPanelCallout::ApplySchemeSettings( vgui::IScheme *pScheme )
  302. {
  303. BaseClass::ApplySchemeSettings( pScheme );
  304. LoadControlSettings( "resource/UI/AnnotationsPanelCallout.res" );
  305. m_pDistanceLabel = dynamic_cast<Label *>( FindChildByName( "DistanceLabel" ) );
  306. m_pBackground = FindChildByName( "CalloutBG" );
  307. if ( m_pBackground )
  308. {
  309. m_pAnnotationLabel = dynamic_cast<CExLabel *>( FindChildByName( "CalloutLabel" ) );
  310. m_pAnnotationLabel->SetParent( m_pBackground );
  311. m_pDistanceLabel->SetParent( m_pBackground );
  312. }
  313. wchar_t outputText[MAX_TRAINING_MSG_LENGTH];
  314. if ( m_pAnnotationLabel && CTFHudTraining::FormatTrainingText( m_Text, outputText ) )
  315. {
  316. m_pAnnotationLabel->SetText(outputText);
  317. }
  318. m_pArrow = dynamic_cast<ImagePanel *>( FindChildByName( "ArrowIcon" ) );
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Purpose: Applies scheme settings
  322. //-----------------------------------------------------------------------------
  323. void CTFAnnotationsPanelCallout::PerformLayout( void )
  324. {
  325. if ( !m_pAnnotationLabel || !m_pDistanceLabel )
  326. return;
  327. C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer();
  328. if ( pLocalTFPlayer == NULL )
  329. return;
  330. // @todo Tom Bui: not sure why we need to do this again, but if we don't
  331. // we still have the camera lag!
  332. InvalidateLayout();
  333. // Reposition the callout based on our target's position
  334. Vector vecTarget = m_Location;
  335. if ( m_FollowEntity.Get() )
  336. {
  337. vecTarget = m_FollowEntity->GetAbsOrigin();
  338. if ( m_FollowEntity->CollisionProp() )
  339. {
  340. vecTarget.z += m_FollowEntity->CollisionProp()->OBBSize().z;
  341. }
  342. }
  343. Vector vDelta = vecTarget - MainViewOrigin();
  344. float flDistance = vDelta.Length();
  345. VectorNormalize( vDelta ); // Only necessary so we can use it as part of our alpha calculation
  346. // Is the target visible on screen?
  347. int iX, iY;
  348. bool bOnscreen = GetVectorInHudSpace( vecTarget, iX, iY ); // Tested - confirmed NOT GetVectorInScreenSpace
  349. // Calculate the perp dot product
  350. QAngle angPlayerView = MainViewAngles();
  351. Vector vView, vRight, vUp;
  352. AngleVectors( angPlayerView, &vView, &vRight, &vUp );
  353. const float flPerpDot = vDelta.x * vView.y - vDelta.y * vView.x;
  354. // Calculate the alpha - the more the user looks away from the target, the greater the alpha
  355. if ( m_DeathTime > 0.0f && m_DeathTime - LIFE_TIME >= gpGlobals->curtime )
  356. {
  357. m_flAlpha[0] = m_flAlpha[1] = 255 * clamp( ( m_DeathTime - gpGlobals->curtime ) / LIFE_TIME, 0.0f, 1.0f );
  358. }
  359. else
  360. {
  361. m_flAlpha[1] = 255;
  362. // BUGBUG: the following lines don't do anything because of the clamp range
  363. //const float flDot = DotProduct( vDelta, vView ); // As the player looks away the target to the target, this will go from -1 to 1
  364. //m_flAlpha[1] = clamp( -255 * flDot, 255, 255 ); // Set target.
  365. m_flAlpha[0] = Lerp( gpGlobals->frametime, m_flAlpha[0], m_flAlpha[1] ); // Move towards target
  366. }
  367. const int fade_alpha = m_flAlpha[0];
  368. SetAlpha( fade_alpha );
  369. m_pArrow->SetAlpha( fade_alpha );
  370. m_pBackground->SetAlpha( fade_alpha );
  371. const int halfWidth = m_pBackground->GetWide() / 2;
  372. bool bOffscreen = !bOnscreen || iX < halfWidth || iX > ScreenWidth()-halfWidth;
  373. if ( bOffscreen )
  374. {
  375. m_pArrow->SetSize( XRES( 10 ), YRES( 20 ) );
  376. const int nHorizontalBuffer = XRES( 20 );
  377. iX = flPerpDot <= 0.0f ? nHorizontalBuffer : ( ScreenWidth() - nHorizontalBuffer - m_pBackground->GetWide() - m_pArrow->GetWide() );
  378. iY = ( ScreenHeight() - m_pBackground->GetTall() ) / 2;
  379. }
  380. else
  381. {
  382. // On screen
  383. // If our target isn't visible, we draw transparently
  384. trace_t tr;
  385. UTIL_TraceLine( vecTarget, MainViewOrigin(), MASK_OPAQUE, NULL, COLLISION_GROUP_NONE, &tr );
  386. if ( tr.fraction < 1.0f )
  387. {
  388. // Not visible ie obstructed by some objects in the world.
  389. // Do *not* show entities that are not the same team
  390. if ( m_FollowEntity.Get() &&
  391. m_FollowEntity->GetTeamNumber() != TEAM_UNASSIGNED && m_FollowEntity->GetTeamNumber() != TEAM_INVALID &&
  392. m_FollowEntity->GetTeamNumber() != pLocalTFPlayer->GetTeamNumber() &&
  393. pLocalTFPlayer->GetTeamNumber() != TEAM_SPECTATOR )
  394. {
  395. SetAlpha( 0 );
  396. m_pArrow->SetAlpha( 0 );
  397. }
  398. }
  399. iX = iX - m_pBackground->GetWide() / 2;
  400. iY = iY - m_pBackground->GetTall() - m_pArrow->GetTall();
  401. }
  402. if ( m_bWasOffscreen != bOffscreen )
  403. {
  404. m_flLerpPercentage = 0.0f;
  405. m_bWasOffscreen = bOffscreen;
  406. }
  407. // lerp to the new position if applicable
  408. // note that this accelerates, cause it uses the current position as the "last position"
  409. if ( m_flLerpPercentage < 1.0f )
  410. {
  411. const float kInvLerpTime = 1.0f / 2.5f;
  412. m_flLerpPercentage = MIN( m_flLerpPercentage + gpGlobals->frametime * kInvLerpTime, 1.0f );
  413. int currentX, currentY;
  414. GetPos( currentX, currentY );
  415. iX = Lerp( m_flLerpPercentage, currentX, iX );
  416. iY = Lerp( m_flLerpPercentage, currentY, iY );
  417. }
  418. SetPos( iX, iY );
  419. int wide, tall;
  420. m_pAnnotationLabel->GetContentSize( wide, tall );
  421. if ( m_bShowDistance )
  422. {
  423. wchar_t *wzFollowEntityName = NULL;
  424. if ( m_FollowEntity.Get() )
  425. {
  426. C_BaseObject *pBuilding = dynamic_cast< C_BaseObject* >( m_FollowEntity.Get() );
  427. if ( pBuilding && pBuilding->GetType() < OBJ_LAST )
  428. {
  429. // Must match resource/tf_objects.txt!!!
  430. const char *szLocalizedObjectNames[OBJ_LAST] =
  431. {
  432. "#TF_Object_Dispenser",
  433. "#TF_Object_Tele",
  434. "#TF_Object_Sentry",
  435. "#TF_object_Sapper"
  436. };
  437. wzFollowEntityName = g_pVGuiLocalize->Find( szLocalizedObjectNames[pBuilding->GetType()] );
  438. }
  439. }
  440. const float kInchesToMeters = 0.0254f;
  441. int distance = RoundFloatToInt( flDistance * kInchesToMeters );
  442. wchar_t wzValue[32];
  443. _snwprintf( wzValue, ARRAYSIZE( wzValue ), L"%u", distance );
  444. wchar_t wzText[256];
  445. if ( wzFollowEntityName == NULL )
  446. {
  447. g_pVGuiLocalize->ConstructString_safe( wzText, g_pVGuiLocalize->Find( "#TR_DistanceTo" ), 1, wzValue );
  448. }
  449. else
  450. {
  451. g_pVGuiLocalize->ConstructString_safe( wzText, g_pVGuiLocalize->Find( "#TR_DistanceToObject" ), 2, wzFollowEntityName, wzValue );
  452. }
  453. m_pDistanceLabel->SetText( wzText );
  454. int distanceWide, distanceTall;
  455. m_pDistanceLabel->GetContentSize( distanceWide, distanceTall );
  456. wide = MAX( distanceWide, wide );
  457. tall += distanceTall;
  458. }
  459. wide += XRES(24);
  460. tall += YRES(18);
  461. // Set this panel, the label, and the background to contain the text
  462. const int aArrowBuffers[2] = { (int)(XRES( 20 ) * 2), (int)YRES( 20 ) }; // Leave enough room for arrows
  463. SetSize( wide + aArrowBuffers[0], tall + aArrowBuffers[1] );
  464. m_pDistanceLabel->SetSize( wide, m_pDistanceLabel->GetTall() );
  465. if ( m_pBackground )
  466. {
  467. // also adjust the background image
  468. m_pBackground->SetSize( wide, tall );
  469. m_pAnnotationLabel->SetSize( m_pBackground->GetWide(), m_pBackground->GetTall() );
  470. m_pDistanceLabel->SetSize( m_pBackground->GetWide(), m_pDistanceLabel->GetTall() );
  471. }
  472. // position background and arrows
  473. if ( bOffscreen )
  474. {
  475. // Set the arrow to left or right, depending on which side of the screen the panel is on
  476. if ( m_pBackground )
  477. {
  478. if ( iX + m_pBackground->GetWide() / 2 < ScreenWidth() / 2 )
  479. {
  480. m_pArrow->SetImage( m_pArrowImages->GetString( "left" ) );
  481. m_pArrow->SetPos( 0, ( m_pBackground->GetTall() - m_pArrow->GetTall() ) / 2 );
  482. m_pBackground->SetPos( m_pArrow->GetWide() + XRES( 1 ), 0 );
  483. }
  484. else
  485. {
  486. m_pArrow->SetImage( m_pArrowImages->GetString( "right" ) );
  487. m_pArrow->SetPos( m_pBackground->GetWide(), ( m_pBackground->GetTall() - m_pArrow->GetTall() ) / 2 );
  488. m_pBackground->SetPos( 0, 0 );
  489. }
  490. }
  491. }
  492. else
  493. {
  494. if ( m_pBackground )
  495. {
  496. // Set the arrow image to the one that points down
  497. m_pBackground->SetPos( 0, 0 );
  498. m_pArrow->SetImage( m_pArrowImages->GetString( "down" ) );
  499. m_pArrow->SetSize( XRES( 20 ), YRES( 10 ) );
  500. m_pArrow->SetPos( ( m_pBackground->GetWide() - m_pArrow->GetWide() ) / 2, m_pBackground->GetTall() );
  501. }
  502. }
  503. // check that we haven't run off the right side of the screen
  504. int x,y;
  505. GetPos( x, y );
  506. if ( (x + wide) > ScreenWidth() )
  507. {
  508. // push ourselves to the left to fit on the screen
  509. SetPos( ScreenWidth() - wide - XRES(8), y );
  510. }
  511. }
  512. void CTFAnnotationsPanelCallout::Touch()
  513. {
  514. SetVisible( true );
  515. m_DeathTime = gpGlobals->curtime + LIFE_TIME;
  516. m_bWasOffscreen = true;
  517. SetPos( ScreenWidth() * 0.125f, ScreenHeight() * 0.125f );
  518. }
  519. //-----------------------------------------------------------------------------
  520. // Purpose:
  521. //-----------------------------------------------------------------------------
  522. void CTFAnnotationsPanelCallout::SetLifetime( float flLifetime )
  523. {
  524. if ( flLifetime < 0 )
  525. {
  526. m_DeathTime = 0.0f;
  527. }
  528. else if ( flLifetime == 0 )
  529. {
  530. m_DeathTime = gpGlobals->curtime + LIFE_TIME;
  531. }
  532. else
  533. {
  534. m_DeathTime = gpGlobals->curtime + flLifetime;
  535. }
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Purpose:
  539. //-----------------------------------------------------------------------------
  540. void CTFAnnotationsPanelCallout::SetShowDistance( bool bShowDistance )
  541. {
  542. m_bShowDistance = bShowDistance;
  543. if ( m_pDistanceLabel && m_pDistanceLabel->IsVisible() != m_bShowDistance )
  544. {
  545. m_pDistanceLabel->SetVisible( bShowDistance );
  546. }
  547. }
  548. //-----------------------------------------------------------------------------
  549. // Purpose:
  550. //-----------------------------------------------------------------------------
  551. void CTFAnnotationsPanelCallout::SetText( const char *text )
  552. {
  553. m_Text = text;
  554. wchar_t outputText[MAX_TRAINING_MSG_LENGTH];
  555. if ( m_pAnnotationLabel && CTFHudTraining::FormatTrainingText( m_Text, outputText ) )
  556. {
  557. m_pAnnotationLabel->SetText(outputText);
  558. }
  559. }
  560. //-----------------------------------------------------------------------------
  561. // Purpose:
  562. //-----------------------------------------------------------------------------
  563. void CTFAnnotationsPanelCallout::FadeAndRemove()
  564. {
  565. m_DeathTime = gpGlobals->curtime + 0.25f;
  566. }
  567. //-----------------------------------------------------------------------------
  568. // Purpose:
  569. //-----------------------------------------------------------------------------
  570. bool CTFAnnotationsPanelCallout::UpdateCallout()
  571. {
  572. if ( m_DeathTime > 0.0f )
  573. {
  574. float pct_life = clamp( (m_DeathTime - gpGlobals->curtime) / LIFE_TIME, 0.0f, 1.0f );
  575. if (pct_life <= 0.0f)
  576. {
  577. SetVisible( false );
  578. return true;
  579. }
  580. }
  581. C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer();
  582. if ( !pLocalTFPlayer )
  583. return true;
  584. if ( m_iVisibilityBitfield != 0 )
  585. {
  586. int bit = 1 << pLocalTFPlayer->entindex();
  587. if ( ( m_iVisibilityBitfield & bit ) == 0 )
  588. {
  589. SetVisible( false );
  590. return true;
  591. }
  592. }
  593. if ( !IsVisible() )
  594. {
  595. SetVisible( true );
  596. }
  597. InvalidateLayout();
  598. return false;
  599. }