summaryrefslogtreecommitdiff
path: root/game/client/tf/tf_hud_annotationspanel.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/tf_hud_annotationspanel.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/client/tf/tf_hud_annotationspanel.cpp')
-rw-r--r--game/client/tf/tf_hud_annotationspanel.cpp681
1 files changed, 681 insertions, 0 deletions
diff --git a/game/client/tf/tf_hud_annotationspanel.cpp b/game/client/tf/tf_hud_annotationspanel.cpp
new file mode 100644
index 0000000..deee35d
--- /dev/null
+++ b/game/client/tf/tf_hud_annotationspanel.cpp
@@ -0,0 +1,681 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "tf_hud_annotationspanel.h"
+#include "vgui_controls/AnimationController.h"
+#include "iclientmode.h"
+#include "c_tf_player.h"
+#include "c_tf_playerresource.h"
+#include <vgui_controls/Label.h>
+#include <vgui/ILocalize.h>
+#include <vgui/ISurface.h>
+#include "c_baseobject.h"
+#include "fmtstr.h"
+#include "tf_gamerules.h"
+#include "tf_hud_statpanel.h"
+#include "view.h"
+#include "ivieweffects.h"
+#include "viewrender.h"
+#include "tf_gamerules.h"
+#include "tf_hud_training.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+DECLARE_HUDELEMENT_DEPTH( CTFAnnotationsPanel, 1 );
+
+static const float LIFE_TIME = 1.0f;
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CTFAnnotationsPanel::CTFAnnotationsPanel( const char *pElementName )
+ : EditablePanel( NULL, "AnnotationsPanel" ), CHudElement( pElementName )
+{
+ vgui::Panel *pParent = g_pClientMode->GetViewport();
+ SetParent( pParent );
+ m_bShouldBeVisible = false;
+ SetScheme( "ClientScheme" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CTFAnnotationsPanel::~CTFAnnotationsPanel()
+{
+ Reset();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanel::Reset()
+{
+ RemoveAll();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanel::Init()
+{
+ // listen for events
+ ListenForGameEvent( "show_annotation" );
+ ListenForGameEvent( "hide_annotation" );
+
+ RemoveAll();
+
+ CHudElement::Init();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Applies scheme settings
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanel::FireGameEvent( IGameEvent * event )
+{
+ const char *pEventName = event->GetName();
+
+ if ( Q_strcmp( "hide_annotation", pEventName ) == 0 )
+ {
+ HideAnnotation( event->GetInt("id") );
+ }
+ else if ( Q_strcmp( "show_annotation", pEventName ) == 0 )
+ {
+ AddAnnotation( event );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CTFAnnotationsPanelCallout *CTFAnnotationsPanel::TestAndAddCallout( int id, Vector &origin, const char *text )
+{
+ int insertSlot = -1;
+
+ // Find an available slot and also see if this call out already exists in the list.
+ for (int i=0; i<m_pCalloutPanels.Count(); ++i)
+ {
+ if (NULL == m_pCalloutPanels[i])
+ {
+ insertSlot = i;
+ continue;
+ }
+ // If we already have this annotation, return and don't add it again.
+ if (m_pCalloutPanels[i]->GetAnnotationID() == id)
+ {
+ m_pCalloutPanels[i]->SetText( text );
+ m_pCalloutPanels[i]->SetLocation( origin );
+ m_pCalloutPanels[i]->SetFollowEntity( NULL );
+ m_pCalloutPanels[i]->InvalidateLayout();
+ return m_pCalloutPanels[i];
+ }
+ // if one is available, use it
+ if ( m_pCalloutPanels[i]->IsVisible() == false )
+ {
+ insertSlot = i;
+ continue;
+ }
+ }
+
+ CTFAnnotationsPanelCallout *pCallout = new CTFAnnotationsPanelCallout( g_pClientMode->GetViewport(), "AnnotationsPanelCallout", id, origin, text );
+
+ if (-1 == insertSlot)
+ {
+ m_pCalloutPanels.AddToTail( vgui::SETUP_PANEL(pCallout) );
+ }
+ else
+ {
+ if ( m_pCalloutPanels[insertSlot] != NULL )
+ {
+ m_pCalloutPanels[insertSlot]->MarkForDeletion();
+ }
+ m_pCalloutPanels[insertSlot] = vgui::SETUP_PANEL(pCallout);
+ }
+
+ return pCallout;
+}
+
+
+void CTFAnnotationsPanel::UpdateAnnotations( void )
+{
+
+ //Find an available slot and also see if this call out already exists in the list.
+ for ( int i = m_pCalloutPanels.Count()-1; i >= 0; i-- )
+ {
+ if ( !m_pCalloutPanels[i] )
+ {
+ m_pCalloutPanels.Remove(i);
+ continue;
+ }
+
+ // Update the callout. If it says it's finished, remove it.
+ if ( m_pCalloutPanels[i]->UpdateCallout() )
+ {
+ m_pCalloutPanels[i]->MarkForDeletion();
+ m_pCalloutPanels.Remove(i);
+ }
+ }
+
+ // If we have no active callouts, hide
+ if ( !m_pCalloutPanels.Count() )
+ {
+ m_bShouldBeVisible = false;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanel::AddAnnotation( IGameEvent * event )
+{
+ const char *text = event->GetString( "text" );
+ int id = event->GetInt("id");
+ float x = event->GetFloat("worldPosX");
+ float y = event->GetFloat("worldPosY");
+ float z = event->GetFloat("worldPosZ");
+ int iVisibilityBitfield = event->GetInt("visibilityBitfield");
+ float flLifetime = event->GetFloat("lifetime");
+ int iFollowEntIndex = event->GetInt("follow_entindex");
+ bool bShowDistance = event->GetBool("show_distance");
+ const char *pSound = event->GetString( "play_sound" );
+ bool bShowEffect = event->GetBool( "show_effect" );
+
+ Vector location;
+
+ location.x = x;
+ location.y = y;
+ location.z = z;
+
+ m_bShouldBeVisible = true;
+
+ // Try and add the callout
+ CTFAnnotationsPanelCallout *pCallout = TestAndAddCallout( id, location, text );
+
+ if ( pCallout )
+ {
+ C_BaseEntity *pFollowEntity = iFollowEntIndex != 0 ? ClientEntityList().GetEnt( iFollowEntIndex) : NULL;
+ pCallout->Touch();
+ pCallout->SetLifetime( flLifetime );
+ pCallout->SetVisibilityBitfield( iVisibilityBitfield );
+ pCallout->SetFollowEntity( pFollowEntity );
+ pCallout->SetShowDistance( bShowDistance );
+ pCallout->UpdateCallout();
+
+ if ( pCallout->IsVisible() )
+ {
+ if ( pSound )
+ {
+ vgui::surface()->PlaySound( pSound );
+ }
+
+ if ( bShowEffect )
+ {
+ if ( pFollowEntity && pFollowEntity->ParticleProp())
+ {
+ pFollowEntity->ParticleProp()->Create( "ping_circle", PATTACH_ABSORIGIN_FOLLOW );
+ }
+ else
+ {
+ Vector vecNormal( event->GetFloat("worldNormalX"), event->GetFloat("worldNormalY"), event->GetFloat("worldNormalZ") );
+ Vector vecOrigin( x, y, z );
+ vecOrigin += vecNormal * 20.0f;
+
+ QAngle vecAngles;
+ VectorAngles( vecNormal, vecAngles );
+ DispatchParticleEffect( "ping_circle", vecOrigin, vecAngles );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanel::HideAnnotation( int id )
+{
+ // Delete all our callout panels
+ for ( int i = m_pCalloutPanels.Count()-1; i >= 0; i-- )
+ {
+ if ( m_pCalloutPanels[i]->GetAnnotationID() == id )
+ {
+ m_pCalloutPanels[i]->FadeAndRemove();
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanel::RemoveAll()
+{
+ m_bShouldBeVisible = false;
+
+ // Delete all our callout panels
+ for ( int i = m_pCalloutPanels.Count()-1; i >= 0; i-- )
+ {
+ m_pCalloutPanels[i]->MarkForDeletion();
+ }
+ m_pCalloutPanels.RemoveAll();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTFAnnotationsPanel::ShouldDraw( void )
+{
+ return m_bShouldBeVisible;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanel::OnThink( void )
+{
+ BaseClass::OnThink();
+
+ if ( IsVisible() )
+ {
+ UpdateAnnotations();
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CTFAnnotationsPanelCallout::~CTFAnnotationsPanelCallout()
+{
+ if ( m_pArrowImages )
+ {
+ m_pArrowImages->deleteThis();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CTFAnnotationsPanelCallout::CTFAnnotationsPanelCallout( Panel *parent, const char *name, int id, Vector &location, const char* text ) : EditablePanel( parent, name )
+{
+ m_pAnnotationLabel = NULL;
+ m_pDistanceLabel = NULL;
+ m_pArrowImages = NULL;
+ m_ID = id;
+ m_Location = location;
+ m_Text = text;
+ m_DeathTime = 0.0f;
+ m_flLerpPercentage = 1.0f;
+ m_bWasOffscreen = false;
+ m_bShowDistance = false;
+ m_flAlpha[0] = m_flAlpha[1] = 0.0f;
+ SetWorldPositionCurrentFrame( true );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Applies scheme settings
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanelCallout::ApplySettings( KeyValues *pInResourceData )
+{
+ BaseClass::ApplySettings( pInResourceData );
+
+ if ( !m_pArrowImages )
+ {
+ KeyValues *pArrowImagesSubKey = pInResourceData->FindKey( "ArrowIcons" ); AssertMsg( pArrowImagesSubKey, "This must exist!" );
+ m_pArrowImages = pArrowImagesSubKey->MakeCopy();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Applies scheme settings
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanelCallout::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ LoadControlSettings( "resource/UI/AnnotationsPanelCallout.res" );
+
+ m_pDistanceLabel = dynamic_cast<Label *>( FindChildByName( "DistanceLabel" ) );
+
+ m_pBackground = FindChildByName( "CalloutBG" );
+ if ( m_pBackground )
+ {
+ m_pAnnotationLabel = dynamic_cast<CExLabel *>( FindChildByName( "CalloutLabel" ) );
+ m_pAnnotationLabel->SetParent( m_pBackground );
+ m_pDistanceLabel->SetParent( m_pBackground );
+ }
+
+ wchar_t outputText[MAX_TRAINING_MSG_LENGTH];
+ if ( m_pAnnotationLabel && CTFHudTraining::FormatTrainingText( m_Text, outputText ) )
+ {
+ m_pAnnotationLabel->SetText(outputText);
+ }
+
+ m_pArrow = dynamic_cast<ImagePanel *>( FindChildByName( "ArrowIcon" ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Applies scheme settings
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanelCallout::PerformLayout( void )
+{
+ if ( !m_pAnnotationLabel || !m_pDistanceLabel )
+ return;
+
+ C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( pLocalTFPlayer == NULL )
+ return;
+
+ // @todo Tom Bui: not sure why we need to do this again, but if we don't
+ // we still have the camera lag!
+ InvalidateLayout();
+
+ // Reposition the callout based on our target's position
+ Vector vecTarget = m_Location;
+ if ( m_FollowEntity.Get() )
+ {
+ vecTarget = m_FollowEntity->GetAbsOrigin();
+ if ( m_FollowEntity->CollisionProp() )
+ {
+ vecTarget.z += m_FollowEntity->CollisionProp()->OBBSize().z;
+ }
+ }
+ Vector vDelta = vecTarget - MainViewOrigin();
+ float flDistance = vDelta.Length();
+ VectorNormalize( vDelta ); // Only necessary so we can use it as part of our alpha calculation
+
+ // Is the target visible on screen?
+ int iX, iY;
+ bool bOnscreen = GetVectorInHudSpace( vecTarget, iX, iY ); // Tested - confirmed NOT GetVectorInScreenSpace
+
+ // Calculate the perp dot product
+ QAngle angPlayerView = MainViewAngles();
+ Vector vView, vRight, vUp;
+ AngleVectors( angPlayerView, &vView, &vRight, &vUp );
+ const float flPerpDot = vDelta.x * vView.y - vDelta.y * vView.x;
+
+ // Calculate the alpha - the more the user looks away from the target, the greater the alpha
+ if ( m_DeathTime > 0.0f && m_DeathTime - LIFE_TIME >= gpGlobals->curtime )
+ {
+ m_flAlpha[0] = m_flAlpha[1] = 255 * clamp( ( m_DeathTime - gpGlobals->curtime ) / LIFE_TIME, 0.0f, 1.0f );
+ }
+ else
+ {
+ m_flAlpha[1] = 255;
+ // BUGBUG: the following lines don't do anything because of the clamp range
+ //const float flDot = DotProduct( vDelta, vView ); // As the player looks away the target to the target, this will go from -1 to 1
+ //m_flAlpha[1] = clamp( -255 * flDot, 255, 255 ); // Set target.
+ m_flAlpha[0] = Lerp( gpGlobals->frametime, m_flAlpha[0], m_flAlpha[1] ); // Move towards target
+ }
+
+ const int fade_alpha = m_flAlpha[0];
+
+ SetAlpha( fade_alpha );
+ m_pArrow->SetAlpha( fade_alpha );
+ m_pBackground->SetAlpha( fade_alpha );
+
+ const int halfWidth = m_pBackground->GetWide() / 2;
+ bool bOffscreen = !bOnscreen || iX < halfWidth || iX > ScreenWidth()-halfWidth;
+ if ( bOffscreen )
+ {
+ m_pArrow->SetSize( XRES( 10 ), YRES( 20 ) );
+
+ const int nHorizontalBuffer = XRES( 20 );
+ iX = flPerpDot <= 0.0f ? nHorizontalBuffer : ( ScreenWidth() - nHorizontalBuffer - m_pBackground->GetWide() - m_pArrow->GetWide() );
+ iY = ( ScreenHeight() - m_pBackground->GetTall() ) / 2;
+ }
+ else
+ {
+ // On screen
+ // If our target isn't visible, we draw transparently
+ trace_t tr;
+ UTIL_TraceLine( vecTarget, MainViewOrigin(), MASK_OPAQUE, NULL, COLLISION_GROUP_NONE, &tr );
+
+ if ( tr.fraction < 1.0f )
+ {
+ // Not visible ie obstructed by some objects in the world.
+ // Do *not* show entities that are not the same team
+ if ( m_FollowEntity.Get() &&
+ m_FollowEntity->GetTeamNumber() != TEAM_UNASSIGNED && m_FollowEntity->GetTeamNumber() != TEAM_INVALID &&
+ m_FollowEntity->GetTeamNumber() != pLocalTFPlayer->GetTeamNumber() &&
+ pLocalTFPlayer->GetTeamNumber() != TEAM_SPECTATOR )
+ {
+ SetAlpha( 0 );
+ m_pArrow->SetAlpha( 0 );
+ }
+ }
+
+ iX = iX - m_pBackground->GetWide() / 2;
+ iY = iY - m_pBackground->GetTall() - m_pArrow->GetTall();
+ }
+
+ if ( m_bWasOffscreen != bOffscreen )
+ {
+ m_flLerpPercentage = 0.0f;
+ m_bWasOffscreen = bOffscreen;
+ }
+ // lerp to the new position if applicable
+ // note that this accelerates, cause it uses the current position as the "last position"
+ if ( m_flLerpPercentage < 1.0f )
+ {
+ const float kInvLerpTime = 1.0f / 2.5f;
+ m_flLerpPercentage = MIN( m_flLerpPercentage + gpGlobals->frametime * kInvLerpTime, 1.0f );
+ int currentX, currentY;
+ GetPos( currentX, currentY );
+ iX = Lerp( m_flLerpPercentage, currentX, iX );
+ iY = Lerp( m_flLerpPercentage, currentY, iY );
+ }
+ SetPos( iX, iY );
+
+ int wide, tall;
+ m_pAnnotationLabel->GetContentSize( wide, tall );
+
+ if ( m_bShowDistance )
+ {
+ wchar_t *wzFollowEntityName = NULL;
+ if ( m_FollowEntity.Get() )
+ {
+ C_BaseObject *pBuilding = dynamic_cast< C_BaseObject* >( m_FollowEntity.Get() );
+ if ( pBuilding && pBuilding->GetType() < OBJ_LAST )
+ {
+ // Must match resource/tf_objects.txt!!!
+ const char *szLocalizedObjectNames[OBJ_LAST] =
+ {
+ "#TF_Object_Dispenser",
+ "#TF_Object_Tele",
+ "#TF_Object_Sentry",
+ "#TF_object_Sapper"
+ };
+ wzFollowEntityName = g_pVGuiLocalize->Find( szLocalizedObjectNames[pBuilding->GetType()] );
+ }
+ }
+ const float kInchesToMeters = 0.0254f;
+ int distance = RoundFloatToInt( flDistance * kInchesToMeters );
+ wchar_t wzValue[32];
+ _snwprintf( wzValue, ARRAYSIZE( wzValue ), L"%u", distance );
+
+ wchar_t wzText[256];
+ if ( wzFollowEntityName == NULL )
+ {
+ g_pVGuiLocalize->ConstructString_safe( wzText, g_pVGuiLocalize->Find( "#TR_DistanceTo" ), 1, wzValue );
+ }
+ else
+ {
+ g_pVGuiLocalize->ConstructString_safe( wzText, g_pVGuiLocalize->Find( "#TR_DistanceToObject" ), 2, wzFollowEntityName, wzValue );
+ }
+
+ m_pDistanceLabel->SetText( wzText );
+ int distanceWide, distanceTall;
+ m_pDistanceLabel->GetContentSize( distanceWide, distanceTall );
+ wide = MAX( distanceWide, wide );
+ tall += distanceTall;
+ }
+
+ wide += XRES(24);
+ tall += YRES(18);
+
+ // Set this panel, the label, and the background to contain the text
+ const int aArrowBuffers[2] = { (int)(XRES( 20 ) * 2), (int)YRES( 20 ) }; // Leave enough room for arrows
+ SetSize( wide + aArrowBuffers[0], tall + aArrowBuffers[1] );
+ m_pDistanceLabel->SetSize( wide, m_pDistanceLabel->GetTall() );
+ if ( m_pBackground )
+ {
+ // also adjust the background image
+ m_pBackground->SetSize( wide, tall );
+ m_pAnnotationLabel->SetSize( m_pBackground->GetWide(), m_pBackground->GetTall() );
+ m_pDistanceLabel->SetSize( m_pBackground->GetWide(), m_pDistanceLabel->GetTall() );
+ }
+
+ // position background and arrows
+ if ( bOffscreen )
+ {
+ // Set the arrow to left or right, depending on which side of the screen the panel is on
+ if ( m_pBackground )
+ {
+ if ( iX + m_pBackground->GetWide() / 2 < ScreenWidth() / 2 )
+ {
+ m_pArrow->SetImage( m_pArrowImages->GetString( "left" ) );
+ m_pArrow->SetPos( 0, ( m_pBackground->GetTall() - m_pArrow->GetTall() ) / 2 );
+ m_pBackground->SetPos( m_pArrow->GetWide() + XRES( 1 ), 0 );
+ }
+ else
+ {
+ m_pArrow->SetImage( m_pArrowImages->GetString( "right" ) );
+ m_pArrow->SetPos( m_pBackground->GetWide(), ( m_pBackground->GetTall() - m_pArrow->GetTall() ) / 2 );
+ m_pBackground->SetPos( 0, 0 );
+ }
+ }
+ }
+ else
+ {
+ if ( m_pBackground )
+ {
+ // Set the arrow image to the one that points down
+ m_pBackground->SetPos( 0, 0 );
+ m_pArrow->SetImage( m_pArrowImages->GetString( "down" ) );
+ m_pArrow->SetSize( XRES( 20 ), YRES( 10 ) );
+ m_pArrow->SetPos( ( m_pBackground->GetWide() - m_pArrow->GetWide() ) / 2, m_pBackground->GetTall() );
+ }
+ }
+
+ // check that we haven't run off the right side of the screen
+ int x,y;
+ GetPos( x, y );
+ if ( (x + wide) > ScreenWidth() )
+ {
+ // push ourselves to the left to fit on the screen
+ SetPos( ScreenWidth() - wide - XRES(8), y );
+ }
+}
+
+void CTFAnnotationsPanelCallout::Touch()
+{
+ SetVisible( true );
+ m_DeathTime = gpGlobals->curtime + LIFE_TIME;
+ m_bWasOffscreen = true;
+ SetPos( ScreenWidth() * 0.125f, ScreenHeight() * 0.125f );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanelCallout::SetLifetime( float flLifetime )
+{
+ if ( flLifetime < 0 )
+ {
+ m_DeathTime = 0.0f;
+ }
+ else if ( flLifetime == 0 )
+ {
+ m_DeathTime = gpGlobals->curtime + LIFE_TIME;
+ }
+ else
+ {
+ m_DeathTime = gpGlobals->curtime + flLifetime;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanelCallout::SetShowDistance( bool bShowDistance )
+{
+ m_bShowDistance = bShowDistance;
+ if ( m_pDistanceLabel && m_pDistanceLabel->IsVisible() != m_bShowDistance )
+ {
+ m_pDistanceLabel->SetVisible( bShowDistance );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanelCallout::SetText( const char *text )
+{
+ m_Text = text;
+ wchar_t outputText[MAX_TRAINING_MSG_LENGTH];
+ if ( m_pAnnotationLabel && CTFHudTraining::FormatTrainingText( m_Text, outputText ) )
+ {
+ m_pAnnotationLabel->SetText(outputText);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFAnnotationsPanelCallout::FadeAndRemove()
+{
+ m_DeathTime = gpGlobals->curtime + 0.25f;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTFAnnotationsPanelCallout::UpdateCallout()
+{
+ if ( m_DeathTime > 0.0f )
+ {
+ float pct_life = clamp( (m_DeathTime - gpGlobals->curtime) / LIFE_TIME, 0.0f, 1.0f );
+ if (pct_life <= 0.0f)
+ {
+ SetVisible( false );
+ return true;
+ }
+ }
+
+ C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( !pLocalTFPlayer )
+ return true;
+
+ if ( m_iVisibilityBitfield != 0 )
+ {
+ int bit = 1 << pLocalTFPlayer->entindex();
+ if ( ( m_iVisibilityBitfield & bit ) == 0 )
+ {
+ SetVisible( false );
+ return true;
+ }
+ }
+
+ if ( !IsVisible() )
+ {
+ SetVisible( true );
+ }
+
+ InvalidateLayout();
+
+ return false;
+}