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.
691 lines
16 KiB
691 lines
16 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "cbase.h" |
|
#include "c_tf_basehint.h" |
|
#include "tf_hints.h" |
|
#include "itfhintitem.h" |
|
#include <vgui_controls/Controls.h> |
|
#include <vgui/IVGui.h> |
|
#include <vgui/Cursor.h> |
|
#include <vgui_controls/Label.h> |
|
#include <vgui/ISurface.h> |
|
#include <vgui/IScheme.h> |
|
#include "vgui_int.h" |
|
#include "hintitembase.h" |
|
#include <KeyValues.h> |
|
|
|
HINTCOMPLETIONFUNCTION LookupCompletionFunction( const char *name ); |
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : id - |
|
// priority - |
|
// player - |
|
// entity - |
|
//----------------------------------------------------------------------------- |
|
C_TFBaseHint::C_TFBaseHint( int id, int priority, int entity, HINTCOMPLETIONFUNCTION pfn /*=NULL*/ ) |
|
: vgui::Panel( NULL, "TFBaseHint" ), m_CursorNone( vgui::dc_none ) |
|
{ |
|
m_pObject = NULL; |
|
m_pClearLabel = NULL; |
|
m_pCaption = NULL; |
|
m_pfnCompletion = pfn; |
|
|
|
// Child of main panel |
|
SetParent( VGui_GetClientDLLRootPanel() ); |
|
|
|
// Put at top of z-order (happens in Think, too) |
|
// MoveToFront(); |
|
|
|
// No cursor |
|
SetCursor( m_CursorNone ); |
|
// Set to default size |
|
SetSize( TFBASEHINT_DEFAULT_WIDTH, TFBASEHINT_DEFAULT_HEIGHT ); |
|
// We'll expressly delete it |
|
SetAutoDelete( false ); |
|
|
|
// Set up default values |
|
SetID( id ); |
|
SetPriority( priority ); |
|
SetEntity( entity ); |
|
SetCompleted( false ); |
|
// Target panel |
|
m_hTarget = NULL; |
|
|
|
m_bMoving = false; |
|
m_flMoveRemaining = 0.0f; |
|
m_flMoveTotal = 0.0f; |
|
|
|
for ( int pt = 0; pt < 2; pt++ ) |
|
{ |
|
m_nMoveStart[ pt ] = 0; |
|
m_nMoveEnd[ pt ] = 0; |
|
} |
|
|
|
vgui::ivgui()->AddTickSignal( GetVPanel() ); |
|
|
|
// Create clear label |
|
m_pClearLabel = new vgui::Label( this, "CLEAR", "[Enter] to remove, [Enter] twice quickly to remove all..." ); |
|
m_pClearLabel->SetContentAlignment( vgui::Label::a_west ); |
|
m_pClearLabel->SetTextInset( 3, 2 ); |
|
|
|
// Create window caption |
|
m_pCaption = new vgui::Label( this, "CAPTION", "" ); |
|
m_pCaption->SetContentAlignment( vgui::Label::a_west ); |
|
m_pCaption->SetTextInset( 3, 0 ); |
|
|
|
// See if the hint started out complete! |
|
CheckForCompletion(); |
|
|
|
// Always start out hidden |
|
SetVisible( false ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
C_TFBaseHint::~C_TFBaseHint( void ) |
|
{ |
|
RemoveAllHintItems( true ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Applying scheme settings |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::ApplySchemeSettings(vgui::IScheme *pScheme) |
|
{ |
|
BaseClass::ApplySchemeSettings(pScheme); |
|
|
|
vgui::HFont hSmallFont = pScheme->GetFont( "DefaultVerySmall" ); |
|
vgui::HFont hCaptionFont = pScheme->GetFont( "DefaultSmall" ); |
|
m_pClearLabel->SetFont( hSmallFont ); |
|
m_pCaption->SetFont( hCaptionFont ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pkv - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::ParseFromData( KeyValues *pkv ) |
|
{ |
|
int priority = pkv->GetInt( "priority", 100 ); |
|
SetPriority( priority ); |
|
int width = pkv->GetInt( "width", TFBASEHINT_DEFAULT_WIDTH ); |
|
if ( !width && !stricmp( pkv->GetString( "width" ), "default" ) ) |
|
{ |
|
width = TFBASEHINT_DEFAULT_WIDTH; |
|
} |
|
SetSize( width, TFBASEHINT_DEFAULT_HEIGHT ); |
|
const char *title = pkv->GetString( "title" ); |
|
if ( title ) |
|
{ |
|
SetTitle( title ); |
|
} |
|
|
|
const char *completionfunction = pkv->GetString( "completionfunction" ); |
|
if ( completionfunction && strlen( completionfunction ) > 0 ) |
|
{ |
|
SetCompletionFunction( LookupCompletionFunction( completionfunction ) ); |
|
} |
|
|
|
KeyValues *items = pkv->FindKey( "items" ); |
|
if ( items ) |
|
{ |
|
KeyValues *pkvItem = items->GetFirstSubKey(); |
|
for( ; pkvItem ; pkvItem = pkvItem->GetNextKey() ) |
|
{ |
|
CHintItemBase *item = CreateHintItem( this, pkvItem->GetName() ); |
|
if ( item ) |
|
{ |
|
item->ParseItem( pkvItem ); |
|
item->ComputeTitle(); |
|
|
|
item->SetSize( GetWide(), 20 ); |
|
|
|
AddHintItem( item ); |
|
} |
|
else |
|
{ |
|
Msg( "C_TFBaseHint::ParseFromData: Failed to create hint item %s\n", pkvItem->GetName() ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : int&x - |
|
// y - |
|
// w - |
|
// &h - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::GetClientArea( int&x, int& y, int& w, int &h ) |
|
{ |
|
GetSize( w, h ); |
|
|
|
x = BORDER; |
|
y = BORDER + CAPTION; |
|
|
|
w -= 2 * BORDER; |
|
h -= 2 * BORDER; |
|
|
|
h -= CAPTION; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *title - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::SetTitle( const char *title ) |
|
{ |
|
if ( m_pCaption ) |
|
{ |
|
m_pCaption->SetText( title ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::PaintBackground() |
|
{ |
|
SetBgColor( Color( 240, 240, 220, 255 ) ); |
|
if ( m_pCaption ) |
|
{ |
|
m_pCaption->SetBgColor( Color( 163, 180, 200, 255 ) ); |
|
|
|
m_pCaption->SetFgColor( Color( 0, 0, 0, 255 ) ); |
|
} |
|
if ( m_pClearLabel ) |
|
{ |
|
m_pClearLabel->SetBgColor( Color( 230, 230, 210, 255 ) ); |
|
m_pClearLabel->SetFgColor( Color( 100, 127, 160, 255 ) ); |
|
} |
|
|
|
BaseClass::PaintBackground(); |
|
|
|
int w, h; |
|
GetSize( w, h ); |
|
|
|
vgui::surface()->DrawSetColor( 0, 0, 0, 255 ); |
|
vgui::surface()->DrawOutlinedRect( 0, 0, w, h ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
int x, y, w, h; |
|
GetClientArea( x, y, w, h ); |
|
|
|
int itemh; |
|
|
|
int needY = 4; |
|
|
|
for ( int i = 0; i < GetNumHintItems(); i++ ) |
|
{ |
|
ITFHintItem *item = GetHintItem( i ); |
|
if ( item ) |
|
{ |
|
itemh = item->GetHeight(); |
|
|
|
item->SetPosition( x, y + 2 ); |
|
item->SetItemNumber( i + 1 ); |
|
|
|
if ( i == 0 ) |
|
{ |
|
item->SetVisible( true ); |
|
needY += itemh + 2; |
|
} |
|
else |
|
{ |
|
item->SetVisible( false ); |
|
} |
|
} |
|
} |
|
|
|
needY += 8; |
|
|
|
if ( m_pClearLabel ) |
|
{ |
|
m_pClearLabel->SetBounds( x, y + needY + 2, w, 14 ); |
|
} |
|
|
|
if ( m_pCaption ) |
|
{ |
|
m_pCaption->SetBounds( x, BORDER, w, CAPTION ); |
|
} |
|
|
|
needY += 14 + BORDER; |
|
|
|
int needPixels = needY - h; |
|
|
|
int trueW, trueH; |
|
GetSize( trueW, trueH ); |
|
|
|
SetSize( trueW, trueH + needPixels ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Install completion function |
|
// Input : pfn - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::SetCompletionFunction( HINTCOMPLETIONFUNCTION pfn ) |
|
{ |
|
m_pfnCompletion = pfn; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::CheckForCompletion( void ) |
|
{ |
|
if ( m_pfnCompletion ) |
|
{ |
|
bool complete = (*m_pfnCompletion)( this ); |
|
if ( complete ) |
|
{ |
|
SetCompleted( true ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::OnTick() |
|
{ |
|
if ( !IsVisible() ) |
|
return; |
|
|
|
// MoveToFront(); |
|
|
|
// Check for completion of entire hint |
|
CheckForCompletion(); |
|
|
|
bool setactive = false; |
|
int numactive = 0; |
|
// Remove obsolete items |
|
int i; |
|
for ( i = m_Hints.Size() - 1; i >= 0; i-- ) |
|
{ |
|
ITFHintItem *item = m_Hints[ i ]; |
|
if ( !item ) |
|
continue; |
|
|
|
if ( item->GetCompleted() ) |
|
{ |
|
RemoveHintItem( i ); |
|
} |
|
else |
|
{ |
|
numactive++; |
|
} |
|
} |
|
|
|
// Mark first one as active |
|
// Perform think |
|
for ( i = 0; i < m_Hints.Size(); i++ ) |
|
{ |
|
ITFHintItem *item = m_Hints[ i ]; |
|
if ( !item ) |
|
continue; |
|
|
|
if ( !setactive ) |
|
{ |
|
item->SetActive( true ); |
|
setactive = true; |
|
} |
|
else |
|
{ |
|
item->SetActive( false ); |
|
} |
|
|
|
// Think, too |
|
if ( item->GetActive() ) |
|
{ |
|
item->Think(); |
|
} |
|
} |
|
|
|
// No more active items |
|
if ( !numactive ) |
|
{ |
|
SetCompleted( true ); |
|
} |
|
|
|
// Keep moving window to correct position |
|
AnimatePosition(); |
|
|
|
/* |
|
static float nextchange = 0.0f; |
|
|
|
if ( gpGlobals->curtime < nextchange ) |
|
return; |
|
|
|
nextchange = gpGlobals->curtime + 1.0f; |
|
|
|
int w, h; |
|
GetSize( w, h ); |
|
|
|
int x = random->RandomInt( 0, ScreenWidth() - w ); |
|
int y = random->RandomInt( 0, ScreenHeight() - h ); |
|
|
|
SetDesiredPosition( x, y, 0.9f ); |
|
*/ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int C_TFBaseHint::GetID( void ) |
|
{ |
|
return m_nID; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : id - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::SetID( int id ) |
|
{ |
|
m_nID = id; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int C_TFBaseHint::GetPriority( void ) |
|
{ |
|
return m_nPriority; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : priority - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::SetPriority( int priority ) |
|
{ |
|
m_nPriority = priority; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int C_TFBaseHint::GetEntity( void ) |
|
{ |
|
return m_nEntity; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : C_BaseEntity |
|
//----------------------------------------------------------------------------- |
|
C_BaseEntity *C_TFBaseHint::GetBaseEntity( void ) |
|
{ |
|
return m_nEntity != -1 ? cl_entitylist->GetEnt( m_nEntity ) : NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : entity - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::SetEntity( int entity ) |
|
{ |
|
m_nEntity = entity; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *entity - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::SetBaseEntity( C_BaseEntity *entity ) |
|
{ |
|
m_nEntity = entity ? entity->index : -1; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool C_TFBaseHint::GetCompleted( void ) |
|
{ |
|
return m_bCompleted; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : completed - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::SetCompleted( bool completed ) |
|
{ |
|
m_bCompleted = completed; |
|
// Hide the window right away if it's finished |
|
SetVisible( !completed ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *item - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::AddHintItem( ITFHintItem *item ) |
|
{ |
|
m_Hints.AddToTail( item ); |
|
InvalidateLayout(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : index - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::RemoveHintItem( int index ) |
|
{ |
|
ITFHintItem *item = GetHintItem( index ); |
|
if ( item ) |
|
{ |
|
m_Hints.Remove( index ); |
|
item->DeleteThis(); |
|
InvalidateLayout(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int C_TFBaseHint::GetNumHintItems( void ) |
|
{ |
|
return m_Hints.Size(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : deleteitems - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::RemoveAllHintItems( bool deleteitems ) |
|
{ |
|
while ( m_Hints.Size() > 0 ) |
|
{ |
|
ITFHintItem *item = m_Hints[ 0 ]; |
|
m_Hints.Remove( 0 ); |
|
if ( deleteitems ) |
|
{ |
|
item->DeleteThis(); |
|
} |
|
} |
|
|
|
InvalidateLayout(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : index - |
|
//----------------------------------------------------------------------------- |
|
ITFHintItem *C_TFBaseHint::GetHintItem( int index ) |
|
{ |
|
if ( index < 0 || index >= m_Hints.Size() ) |
|
{ |
|
return NULL; |
|
} |
|
|
|
return m_Hints[ index ]; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : x - |
|
// y - |
|
// movementtime - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::SetDesiredPosition( int x, int y, float movementtime /*=0.3f*/ ) |
|
{ |
|
m_bMoving = true; |
|
|
|
m_flMoveRemaining = movementtime; |
|
m_flMoveTotal = movementtime; |
|
|
|
int ox, oy; |
|
GetPos( ox, oy ); |
|
|
|
m_nMoveStart[ 0 ] = ox; |
|
m_nMoveStart[ 1 ] = oy; |
|
|
|
m_nMoveEnd[ 0 ] = x; |
|
m_nMoveEnd[ 1 ] = y; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : float |
|
//----------------------------------------------------------------------------- |
|
float C_TFBaseHint::GetMovementFraction( void ) |
|
{ |
|
float frac = 0.0f; |
|
|
|
if ( m_flMoveTotal > 0.0f ) |
|
{ |
|
frac = 1.0f - ( m_flMoveRemaining / m_flMoveTotal ); |
|
} |
|
|
|
float squared = frac * frac; |
|
|
|
frac = 3 * squared - 2 * frac * squared; |
|
|
|
// Simple spline |
|
frac = clamp( frac, 0.0f, 1.0f ); |
|
|
|
return frac; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::AnimatePosition( void ) |
|
{ |
|
if ( !m_bMoving ) |
|
return; |
|
|
|
m_flMoveRemaining -= gpGlobals->frametime; |
|
if ( m_flMoveRemaining <= 0.0f ) |
|
{ |
|
m_bMoving = false; |
|
SetPos( m_nMoveEnd[ 0 ], m_nMoveEnd[ 1 ] ); |
|
return; |
|
} |
|
|
|
float frac = GetMovementFraction(); |
|
|
|
int dx = m_nMoveEnd[ 0 ] - m_nMoveStart[ 0 ]; |
|
int dy = m_nMoveEnd[ 1 ] - m_nMoveStart[ 1 ]; |
|
|
|
int x, y; |
|
|
|
x = m_nMoveStart[ 0 ] + ( int )( frac * dx ); |
|
y = m_nMoveStart[ 1 ] + ( int )( frac * dy ); |
|
|
|
SetPos( x, y ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Helper to center a panel |
|
// Input : *panel - |
|
// Output : static void |
|
//----------------------------------------------------------------------------- |
|
static void PositionHintNoTarget( C_TFBaseHint *panel ) |
|
{ |
|
int w, h; |
|
panel->GetSize( w, h ); |
|
int y = ( ScreenHeight() - h ) / 2; |
|
|
|
panel->SetDesiredPosition( ScreenWidth() - w - 10, y ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *panel - |
|
//----------------------------------------------------------------------------- |
|
void C_TFBaseHint::SetHintTarget( vgui::Panel *panel ) |
|
{ |
|
m_hTarget = panel; |
|
|
|
if ( panel ) |
|
{ |
|
int hintW, hintH; |
|
|
|
GetSize( hintW, hintH ); |
|
|
|
int x, y, w, h; |
|
panel->GetBounds( x, y, w, h ); |
|
|
|
// Try and position ourselves up and to left of target item? |
|
x = x - ( hintW - w ); |
|
y = y - ( hintH ) - 40; |
|
|
|
// Don't let it hang off screen |
|
if ( x < 3 ) |
|
{ |
|
x = 3; |
|
} |
|
else if ( x + hintW + 3 >= ScreenWidth() ) |
|
{ |
|
int over = ( x + hintW + 3 - ScreenWidth() ); |
|
|
|
x -= over; |
|
} |
|
|
|
if ( y < 3 ) |
|
{ |
|
y = 3; |
|
} |
|
else if ( y + hintH >= ScreenHeight() ) |
|
{ |
|
int over = ( y + hintH + 3 - ScreenHeight() ); |
|
|
|
y -= over; |
|
} |
|
|
|
SetDesiredPosition( x, y ); |
|
} |
|
else |
|
{ |
|
PositionHintNoTarget( this ); |
|
} |
|
|
|
// Tell hint items that there is a new target |
|
for ( int i = 0 ; i < GetNumHintItems(); i++ ) |
|
{ |
|
ITFHintItem *item = GetHintItem( i ); |
|
item->SetHintTarget( panel ); |
|
} |
|
}
|
|
|