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
681 lines
20 KiB
//========= 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; |
|
}
|
|
|