|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "charinfo_loadout_subpanel.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
#include "vgui/ILocalize.h"
#include "c_tf_freeaccount.h"
#include "c_tf_player.h"
#include "confirm_dialog.h"
#include "gamestringpool.h"
#include "c_tf_objective_resource.h"
#include "tf_gamerules.h"
#include "tf_item_inventory.h"
#include "trading_start_dialog.h"
#include "gc_clientsystem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
DECLARE_BUILD_FACTORY( CImageButton );
ConVar tf_explanations_charinfopanel( "tf_explanations_charinfopanel", "0", FCVAR_ARCHIVE, "Whether the user has seen explanations for this panel." );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CImageButton::CImageButton( vgui::Panel *parent, const char *panelName ) : BaseClass( parent, panelName, "" ) { m_pszActiveImageName = NULL; m_pszInactiveImageName = NULL;
m_pActiveImage = NULL; m_pInactiveImage = NULL;
m_ActiveDrawColor = Color(255,255,255,255); m_InactiveDrawColor = Color(255,255,255,255); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CImageButton::ApplySettings( KeyValues *inResourceData ) { m_bScaleImage = inResourceData->GetInt( "scaleImage", 0 );
// Active Image
delete [] m_pszActiveImageName; m_pszActiveImageName = NULL;
const char *activeImageName = inResourceData->GetString( "activeimage", "" ); if ( *activeImageName ) { SetActiveImage( activeImageName ); }
// Inactive Image
delete [] m_pszInactiveImageName; m_pszInactiveImageName = NULL;
const char *inactiveImageName = inResourceData->GetString( "inactiveimage", "" ); if ( *inactiveImageName ) { SetInactiveImage( inactiveImageName ); }
const char *pszDrawColor = inResourceData->GetString("activedrawcolor", ""); if (*pszDrawColor) { int r = 0, g = 0, b = 0, a = 255; if (sscanf(pszDrawColor, "%d %d %d %d", &r, &g, &b, &a) >= 3) { m_ActiveDrawColor = Color(r, g, b, a); } else { vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); m_ActiveDrawColor = pScheme->GetColor(pszDrawColor, Color(0, 0, 0, 0)); } }
pszDrawColor = inResourceData->GetString("inactivedrawcolor", ""); if (*pszDrawColor) { int r = 0, g = 0, b = 0, a = 255; if (sscanf(pszDrawColor, "%d %d %d %d", &r, &g, &b, &a) >= 3) { m_InactiveDrawColor = Color(r, g, b, a); } else { vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); m_InactiveDrawColor = pScheme->GetColor(pszDrawColor, Color(0, 0, 0, 0)); } }
BaseClass::ApplySettings( inResourceData ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CImageButton::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme );
if ( m_pszActiveImageName && strlen( m_pszActiveImageName ) > 0 ) { SetActiveImage(vgui::scheme()->GetImage( m_pszActiveImageName, m_bScaleImage ) ); }
if ( m_pszInactiveImageName && strlen( m_pszInactiveImageName ) > 0 ) { SetInactiveImage(vgui::scheme()->GetImage( m_pszInactiveImageName, m_bScaleImage ) ); }
vgui::IBorder *pBorder = pScheme->GetBorder( "NoBorder" ); SetDefaultBorder( pBorder); SetDepressedBorder( pBorder ); SetKeyFocusBorder( pBorder );
Color defaultFgColor = GetSchemeColor( "Button.TextColor", Color(255, 255, 255, 255), pScheme ); Color armedFgColor = GetSchemeColor( "Button.ArmedTextColor", Color(255, 255, 255, 255), pScheme ); Color depressedFgColor = GetSchemeColor( "Button.DepressedTextColor", Color(255, 255, 255, 255), pScheme );
Color blank(0,0,0,0); SetDefaultColor( defaultFgColor, blank ); SetArmedColor( armedFgColor, blank ); SetDepressedColor( depressedFgColor, blank ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CImageButton::SetActiveImage( const char *imagename ) { int len = Q_strlen( imagename ) + 1; m_pszActiveImageName = new char[ len ]; Q_strncpy( m_pszActiveImageName, imagename, len );
SetActiveImage(vgui::scheme()->GetImage( m_pszActiveImageName, m_bScaleImage ) ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CImageButton::SetInactiveImage( const char *imagename ) { int len = Q_strlen( imagename ) + 1; m_pszInactiveImageName = new char[ len ]; Q_strncpy( m_pszInactiveImageName, imagename, len );
SetInactiveImage(vgui::scheme()->GetImage( m_pszInactiveImageName, m_bScaleImage ) ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CImageButton::SetActiveImage( vgui::IImage *image ) { m_pActiveImage = image;
if ( m_pActiveImage ) { int wide, tall; if ( m_bScaleImage ) { // scaling, force the image size to be our size
GetSize( wide, tall ); m_pActiveImage->SetSize( wide, tall ); } else { // not scaling, so set our size to the image size
m_pActiveImage->GetSize( wide, tall ); SetSize( wide, tall ); } }
Repaint(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CImageButton::SetInactiveImage( vgui::IImage *image ) { m_pInactiveImage = image;
if ( m_pInactiveImage ) { int wide, tall; if ( m_bScaleImage) { // scaling, force the image size to be our size
GetSize( wide, tall ); m_pInactiveImage->SetSize( wide, tall ); } else { // not scaling, so set our size to the image size
m_pInactiveImage->GetSize( wide, tall ); SetSize( wide, tall ); } }
Repaint(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CImageButton::OnSizeChanged( int newWide, int newTall ) { if ( m_bScaleImage ) { // scaling, force the image size to be our size
if ( m_pActiveImage ) m_pActiveImage->SetSize( newWide, newTall );
if ( m_pInactiveImage ) m_pInactiveImage->SetSize( newWide, newTall ); } BaseClass::OnSizeChanged( newWide, newTall ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CImageButton::Paint() { if ( IsArmed() || _buttonFlags.IsFlagSet( FORCE_DEPRESSED ) ) { // draw the active image
if ( m_pActiveImage ) { m_pActiveImage->SetColor( m_ActiveDrawColor ); m_pActiveImage->SetPos( 0, 0 ); m_pActiveImage->Paint(); } } else { // draw the inactive image
if ( m_pInactiveImage ) { m_pActiveImage->SetColor( m_InactiveDrawColor ); m_pInactiveImage->SetPos( 0, 0 ); m_pInactiveImage->Paint(); } }
BaseClass::Paint(); }
const char *g_pszSubButtonNames[CHSB_NUM_BUTTONS] = { "ShowBackpackButton", // CHSB_BACKPACK,
"ShowCraftingButton", // CHSB_CRAFTING,
"ShowArmoryButton", // CHSB_ARMORY,
"ShowTradeButton", // CHSB_TRADING,
}; const char *g_pszSubButtonLabelNames[CHSB_NUM_BUTTONS] = { "ShowBackpackLabel", // CHSB_BACKPACK,
"ShowCraftingLabel", // CHSB_CRAFTING,
"ShowArmoryLabel", // CHSB_ARMORY,
"ShowTradeLabel", // CHSB_TRADING,
};
int g_nLoadoutClassOrder[] = { TF_CLASS_SCOUT, TF_CLASS_SOLDIER, TF_CLASS_PYRO, TF_CLASS_DEMOMAN, TF_CLASS_HEAVYWEAPONS, TF_CLASS_ENGINEER, TF_CLASS_MEDIC, TF_CLASS_SNIPER, TF_CLASS_SPY };
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCharInfoLoadoutSubPanel::CCharInfoLoadoutSubPanel(Panel *parent) : vgui::PropertyPage(parent, "CharInfoLoadoutSubPanel") { m_iCurrentClassIndex = TF_CLASS_UNDEFINED; m_iCurrentTeamIndex = TF_TEAM_RED; m_iShowingPanel = CHAP_LOADOUT; m_iPrevShowingPanel = CHAP_LOADOUT;
memset( m_pClassButtons, 0, sizeof( m_pClassButtons ) );
m_pClassButtons[ TF_CLASS_SCOUT ] = new CImageButton( this, "scout" ); m_pClassButtons[ TF_CLASS_SOLDIER ] = new CImageButton( this, "soldier" ); m_pClassButtons[ TF_CLASS_PYRO ] = new CImageButton( this, "pyro" ); m_pClassButtons[ TF_CLASS_DEMOMAN ] = new CImageButton( this, "demoman" ); m_pClassButtons[ TF_CLASS_HEAVYWEAPONS ] = new CImageButton( this, "heavyweapons" ); m_pClassButtons[ TF_CLASS_ENGINEER ] = new CImageButton( this, "engineer" ); m_pClassButtons[ TF_CLASS_MEDIC ] = new CImageButton( this, "medic" ); m_pClassButtons[ TF_CLASS_SNIPER ] = new CImageButton( this, "sniper" ); m_pClassButtons[ TF_CLASS_SPY ] = new CImageButton( this, "spy" );
for( int i = 0; i < Q_ARRAYSIZE( m_pClassButtons ); i++ ) { if( m_pClassButtons[ i ] ) m_pClassButtons[ i ]->SetParentNeedsCursorMoveEvents( true ); }
for ( int i = 0; i < CHSB_NUM_BUTTONS; i++ ) { m_pSubButtons[i] = new CImageButton( this, g_pszSubButtonNames[i] ); m_pButtonLabels[i] = new CExLabel( this, g_pszSubButtonLabelNames[i], "" ); } m_iOverSubButton = -1;
m_pClassLoadoutPanel = new CClassLoadoutPanel( this ); m_pBackpackPanel = new CBackpackPanel( this, "backpack_panel" ); m_pCraftingPanel = new CCraftingPanel( this, "crafting_panel" ); m_pArmoryPanel = new CArmoryPanel( this, "armory_panel" ); m_pArmoryPanel->AllowGotoStore(); m_pSelectLabel = NULL; m_pLoadoutChangesLabel = NULL; m_pNoSteamLabel = NULL; m_pNoGCLabel = NULL; m_pClassLabel = NULL; m_pItemsLabel = NULL; m_bSnapClassLayout = false; m_bClassLayoutDirty = false; m_bRequestingInventoryRefresh = false; m_flStartExplanationsAt = 0;
vgui::ivgui()->AddTickSignal( GetVPanel() );
REGISTER_COLOR_AS_OVERRIDABLE( m_ItemColorNone, "itemcountcolor_noitems" ); REGISTER_COLOR_AS_OVERRIDABLE( m_ItemColor, "itemcountcolor" ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCharInfoLoadoutSubPanel::~CCharInfoLoadoutSubPanel() { }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/CharInfoLoadoutSubPanel.res" );
m_pSelectLabel = dynamic_cast<vgui::Label*>( FindChildByName("SelectLabel") ); m_pLoadoutChangesLabel = dynamic_cast<vgui::Label*>( FindChildByName("LoadoutChangesLabel") ); m_pNoSteamLabel = dynamic_cast<vgui::Label*>( FindChildByName("NoSteamLabel") ); m_pNoGCLabel = dynamic_cast<vgui::Label*>( FindChildByName("NoGCLabel") ); m_pClassLabel = dynamic_cast<vgui::Label*>( FindChildByName("ClassLabel") ); int ignored; if ( m_pClassLabel ) { m_pClassLabel->GetPos( ignored, m_iClassLabelYPos ); } m_pItemsLabel = dynamic_cast<CExLabel*>( FindChildByName("ItemsLabel") ); if ( m_pItemsLabel ) { m_pItemsLabel->GetPos( ignored, m_iItemLabelYPos ); }
// Start classes sized as if the mouse is in the middle of the screen
m_iMouseXPos = -1; m_bSnapClassLayout = true; RecalculateTargetClassLayout(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnPageShow( void ) { SetVisible( true );
BaseClass::OnPageShow();
if( m_iCurrentClassIndex != TF_CLASS_UNDEFINED ) { m_pClassButtons[ m_iCurrentClassIndex ]->GetPos( m_iMouseXPos, m_iMouseYPos ); m_bClassLayoutDirty = true; InvalidateLayout(); }
// If this is the first time we've opened the loadout, start the loadout explanations
if ( !tf_explanations_charinfopanel.GetBool() && ShouldShowExplanations() ) { m_flStartExplanationsAt = engine->Time() + 0.5; }
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnSelectionStarted( void ) { PostActionSignal( new KeyValues("SelectionUpdate", "open", 1 ) ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnSelectionEnded( void ) { PostActionSignal( new KeyValues("SelectionUpdate", "open", 0 ) ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnCancelSelection( void ) { PostMessage( m_pClassLoadoutPanel, new KeyValues("CancelSelection") ); PostMessage( m_pBackpackPanel, new KeyValues("CancelSelection") ); PostMessage( m_pCraftingPanel, new KeyValues("CancelSelection") ); PostMessage( m_pArmoryPanel, new KeyValues("CancelSelection") ); RequestFocus(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnCharInfoClosing( void ) { switch ( m_iShowingPanel ) { case CHAP_CRAFTING: PostMessage( m_pCraftingPanel, new KeyValues("Closing") ); break; case CHAP_BACKPACK: break; case CHAP_ARMORY: PostMessage( m_pArmoryPanel, new KeyValues("Closing") ); break; case CHAP_LOADOUT: PostMessage( m_pClassLoadoutPanel, new KeyValues("Closing") ); break; default: // Class loadout.
break; } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnOpenCrafting( void ) { OpenToCrafting(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnCraftingClosed( void ) { PostMessage( m_pCraftingPanel, new KeyValues("Closing") ); m_iShowingPanel = CHAP_LOADOUT; m_iPrevShowingPanel = CHAP_CRAFTING; m_flStartExplanationsAt = 0; m_iCurrentClassIndex = TF_CLASS_UNDEFINED; UpdateModelPanels(); RequestFocus(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnArmoryClosed( void ) { // Return to whatever we were on before opening the armory
PostMessage( m_pArmoryPanel, new KeyValues("Closing") ); m_iShowingPanel = m_iPrevShowingPanel; m_iPrevShowingPanel = CHAP_ARMORY; m_flStartExplanationsAt = 0; m_iCurrentClassIndex = TF_CLASS_UNDEFINED; UpdateModelPanels(); RequestFocus(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnCommand( const char *command ) { if ( !Q_strnicmp( command, "loadout ", 8 ) ) { // Ignore selection while we don't have a steam connection
if ( !TFInventoryManager()->GetLocalTFInventory()->RetrievedInventoryFromSteam() ) return;
m_flStartExplanationsAt = 0;
const char *pszClass = command+8; if ( pszClass[0] != '\0' ) { int nClassIndex = GetClassIndexFromString( pszClass, NUM_CLASSES_IN_LOADOUT_PANEL ); if ( nClassIndex != TF_CLASS_UNDEFINED && m_iCurrentClassIndex != nClassIndex ) { SetClassIndex( nClassIndex, true ); return; } } } else if ( !Q_strnicmp( command, "backpack", 8 ) ) { OpenToBackpack(); } else if ( !Q_strnicmp( command, "crafting", 8 ) ) { OpenToCrafting(); } else if ( !Q_strnicmp( command, "armory", 6 ) ) { OpenToArmory(); } else if ( !Q_strnicmp( command, "trading", 7 ) ) { OpenTradingStartDialog( this ); } else if ( !Q_stricmp( command, "show_explanations" ) ) { if ( !m_flStartExplanationsAt ) { m_flStartExplanationsAt = engine->Time(); } RequestFocus(); } else { engine->ClientCmd( const_cast<char *>( command ) ); }
BaseClass::OnCommand( command ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::RequestInventoryRefresh() { m_bRequestingInventoryRefresh = false;
// Don't respond to the mouse if we don't have items
if ( !TFInventoryManager()->GetLocalTFInventory()->RetrievedInventoryFromSteam() ) { ShowWaitingDialog( new CGenericWaitingDialog(this), "#NoSteamNoItems_Refresh", true, true, 30.0f ); if ( !m_bRequestingInventoryRefresh ) { // make sure the local inventory is added as a listener
TFInventoryManager()->UpdateLocalInventory(); m_bRequestingInventoryRefresh = true; // ask GC for refresh
GCSDK::CProtoBufMsg< CMsgRequestInventoryRefresh > msg( k_EMsgGCRequestInventoryRefresh ); GCClientSystem()->BSendMessage( msg ); } } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::SetClassIndex( int iClassIndex, bool bOpenClassLoadout ) { Assert(iClassIndex >= TF_CLASS_UNDEFINED && iClassIndex <= NUM_CLASSES_IN_LOADOUT_PANEL); m_iCurrentClassIndex = iClassIndex; m_iShowingPanel = CHAP_LOADOUT; UpdateModelPanels( bOpenClassLoadout );
RequestInventoryRefresh(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::SetTeamIndex( int iTeam ) { Assert( IsValidTFTeam( iTeam ) ); m_iCurrentTeamIndex = iTeam; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OpenSubPanel( charinfo_activepanels_t iPanel ) { m_flStartExplanationsAt = 0; m_iCurrentClassIndex = TF_CLASS_UNDEFINED; m_iPrevShowingPanel = m_iShowingPanel; m_iShowingPanel = iPanel;
UpdateModelPanels();
RequestInventoryRefresh(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::UpdateModelPanels( bool bOpenClassLoadout ) { int iLabelClassToSet = -1; int iClassIndexToSet = 0;
if ( m_iShowingPanel == CHAP_CRAFTING ) { m_pClassLoadoutPanel->SetVisible( false ); m_pBackpackPanel->SetVisible( false ); m_pArmoryPanel->SetVisible( false ); m_pCraftingPanel->ShowPanel( m_iCurrentClassIndex, true, (m_iPrevShowingPanel == CHAP_ARMORY) ); } else if ( m_iShowingPanel == CHAP_BACKPACK ) { m_pClassLoadoutPanel->SetVisible( false ); m_pCraftingPanel->SetVisible( false ); m_pArmoryPanel->SetVisible( false ); m_pBackpackPanel->ShowPanel( m_iCurrentClassIndex, true, (m_iPrevShowingPanel == CHAP_ARMORY) ); } else if ( m_iShowingPanel == CHAP_ARMORY ) { m_pClassLoadoutPanel->SetVisible( false ); m_pCraftingPanel->SetVisible( false ); m_pBackpackPanel->SetVisible( false ); m_pArmoryPanel->ShowPanel( m_iArmoryItemDef ); } else { iClassIndexToSet = bOpenClassLoadout ? m_iCurrentClassIndex : TF_CLASS_UNDEFINED; m_pArmoryPanel->SetVisible( false ); m_pBackpackPanel->SetVisible( false ); m_pCraftingPanel->SetVisible( false ); m_pClassLoadoutPanel->SetTeam( m_iCurrentTeamIndex ); m_pClassLoadoutPanel->SetClass( iClassIndexToSet ); m_pClassLoadoutPanel->ShowPanel( iClassIndexToSet, false, (m_iPrevShowingPanel == CHAP_ARMORY) );
iLabelClassToSet = m_iCurrentClassIndex; }
m_iCurrentClassIndex = iClassIndexToSet;
if( bOpenClassLoadout ) { PostActionSignal( new KeyValues("ClassSelected", "class", m_iCurrentClassIndex ) ); } else { m_iLabelSetToClass = iLabelClassToSet; m_bClassLayoutDirty = true; InvalidateLayout(); } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::PerformLayout( void ) { BaseClass::PerformLayout();
// Show our changes label if we're alive, and hence won't get the changes immediately
bool bChangesLabel = false; if ( engine->IsInGame() ) { C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( pLocalPlayer && pLocalPlayer->IsAlive() && pLocalPlayer->GetObserverMode() == OBS_MODE_NONE ) { bChangesLabel = true; } }
if ( !TFInventoryManager()->GetLocalTFInventory()->RetrievedInventoryFromSteam() ) { bool bLoggedIntoSteam = steamapicontext && steamapicontext->SteamUser() && steamapicontext->SteamUser()->BLoggedOn(); if ( m_pItemsLabel ) m_pNoGCLabel->SetVisible( bLoggedIntoSteam ); if ( m_pNoSteamLabel ) m_pNoSteamLabel->SetVisible( !bLoggedIntoSteam ); if ( m_pSelectLabel ) m_pSelectLabel->SetVisible( false ); if ( m_pLoadoutChangesLabel) m_pLoadoutChangesLabel->SetVisible( false );
for ( int i = 0; i < CHSB_NUM_BUTTONS; i++ ) { m_pSubButtons[i]->SetVisible( false ); m_pButtonLabels[i]->SetVisible( false ); } } else { if ( m_pNoSteamLabel ) m_pNoSteamLabel->SetVisible( false ); if ( m_pNoGCLabel ) m_pNoGCLabel->SetVisible( false ); if ( m_pSelectLabel ) m_pSelectLabel->SetVisible( true );
for ( int i = 0; i < CHSB_NUM_BUTTONS; i++ ) { m_pSubButtons[i]->SetVisible( true ); m_pButtonLabels[i]->SetVisible( true ); } if ( !bChangesLabel ) { if ( m_pSelectLabel ) m_pSelectLabel->SetPos( 0, m_iSelectLabelY ); if ( m_pLoadoutChangesLabel ) m_pLoadoutChangesLabel->SetVisible( false ); } else { if ( m_pSelectLabel ) m_pSelectLabel->SetPos( 0, m_iSelectLabelOnChangesY ); if ( m_pLoadoutChangesLabel ) m_pLoadoutChangesLabel->SetVisible( true ); } }
m_iOverSubButton = -1; if ( m_pSelectLabel ) m_pClassLabel->SetVisible( false ); if ( m_pItemsLabel ) m_pItemsLabel->SetVisible( false );
m_bClassLayoutDirty = false;
// Now Layout the class images.
for ( int iPanel = 0; iPanel < ARRAYSIZE( g_nLoadoutClassOrder ); iPanel++ ) { int i = g_nLoadoutClassOrder[iPanel];
int iX = m_iClassLayout[i][0]; int iY = m_iClassLayout[i][1]; int iWide = m_iClassLayout[i][2]; int iTall = m_iClassLayout[i][3];
if ( m_bSnapClassLayout ) { m_pClassButtons[i]->SetBounds( iX, iY, iWide, iTall ); } else { // Lerp towards the target
int iCurX, iCurY, iCurWide, iCurTall; m_pClassButtons[i]->GetBounds( iCurX, iCurY, iCurWide, iCurTall ); int iNewX = Lerp( 0.2, iCurX, iX ); int iNewY = Lerp( 0.2, iCurY, iY ); int iNewWide = Lerp( 0.2, iCurWide, iWide ); int iNewTall = Lerp( 0.2, iCurTall, iTall ); m_pClassButtons[i]->SetBounds( iNewX, iNewY, iNewWide, iNewTall ); if ( abs(iNewX-iX) > 5 || abs(iNewY-iY) > 5 || abs(iNewWide-iWide) > 5 || abs(iNewTall-iTall) > 5 ) { m_bClassLayoutDirty = true; } } }
// We need to do our own management of cursor arming in the buttons, because the curserentered/exited code can't
// deal with the way we resize the buttons without the cursor moving.
int iBestButton = -1; int iBestZ = 0; int x = m_iMouseXPos, y = m_iMouseYPos;
// only get the actual cursor pos if we don't have a cached cursor pos. THe
// cached pos might have come from the keyboard.
if( x < 0 ) vgui::input()->GetCursorPos(x, y); for ( int iPanel = 0; iPanel < ARRAYSIZE( g_nLoadoutClassOrder ); iPanel++ ) { int i = g_nLoadoutClassOrder[iPanel]; m_pClassButtons[i]->SetArmed( false );
m_pClassButtons[i]->SetEnabled( TFInventoryManager()->GetLocalTFInventory()->RetrievedInventoryFromSteam() );
if ( m_pClassButtons[i]->IsWithin( x,y ) && iBestZ < m_pClassButtons[i]->GetZPos() ) { iBestButton = i; iBestZ = m_pClassButtons[i]->GetZPos(); } }
if ( iBestButton >= 0 && iBestButton < ARRAYSIZE( m_pClassButtons ) ) { m_pClassButtons[iBestButton]->SetArmed( true );
if ( m_iLabelSetToClass != iBestButton ) { m_iLabelSetToClass = iBestButton; }
UpdateLabelFromClass( m_iLabelSetToClass ); }
m_bSnapClassLayout = false; }
void CCharInfoLoadoutSubPanel::UpdateLabelFromClass( int nClass ) { if ( nClass < 0 ) return;
const wchar_t *wszClassName = g_pVGuiLocalize->Find( g_aPlayerClassNames[nClass] ); if ( m_pClassLabel ) { m_pClassLabel->SetText( wszClassName ); m_pClassLabel->SetVisible( true ); }
if ( m_pItemsLabel ) { m_pItemsLabel->SetVisible( true ); }
CUtlVector<CEconItemView*> pList; int iNumItems = TFInventoryManager()->GetAllUsableItemsForSlot( nClass, -1, &pList );
if ( !iNumItems ) { const wchar_t *wszItemsName = g_pVGuiLocalize->Find( "#NoItemsFoundShort" ); m_pItemsLabel->SetText( wszItemsName ); m_pItemsLabel->SetColorStr( m_ItemColorNone ); } else if ( iNumItems == 1 ) { const wchar_t *wszItemsName = g_pVGuiLocalize->Find( "#ItemsFoundShortOne" ); m_pItemsLabel->SetText( wszItemsName ); m_pItemsLabel->SetColorStr( m_ItemColor ); } else { wchar_t wzCount[10]; _snwprintf( wzCount, ARRAYSIZE( wzCount ), L"%d", iNumItems ); wchar_t wTemp[32]; g_pVGuiLocalize->ConstructString_safe( wTemp, g_pVGuiLocalize->Find("ItemsFoundShort"), 1, wzCount ); m_pItemsLabel->SetText( wTemp ); m_pItemsLabel->SetColorStr( m_ItemColor ); }
int iPos = 0; for ( int i = TF_FIRST_NORMAL_CLASS; i <= NUM_CLASSES_IN_LOADOUT_PANEL; i++ ) { if ( iRemapIndexToClass[i] == nClass ) { iPos = i; break; } } Assert(iPos != 0 ); int iXLeft = (GetWide() - ((m_iClassWideMin * NUM_CLASSES_IN_LOADOUT_PANEL) + (m_iClassXDelta * (NUM_CLASSES_IN_LOADOUT_PANEL-1)))) * 0.5; int iBaseX = iXLeft + ((m_iClassWideMin + m_iClassXDelta) * (iPos-1)); int iCenterX = iBaseX + (m_iClassWideMin * 0.5);
m_pClassLabel->SetVisible( true ); m_pClassLabel->SetPos( iCenterX - (m_pClassLabel->GetWide() * 0.5), m_iClassLabelYPos ); m_pItemsLabel->SetVisible( true ); m_pItemsLabel->SetPos( iCenterX - (m_pItemsLabel->GetWide() * 0.5), m_iItemLabelYPos ); }
void CCharInfoLoadoutSubPanel::UpdateLabelFromSubButton( int nButton ) { if( nButton < 0 ) nButton = CHSB_NUM_BUTTONS - 1; else if( nButton >= CHSB_NUM_BUTTONS ) nButton = 0;
if ( m_iOverSubButton == nButton ) return;
m_iOverSubButton = nButton;
switch ( nButton ) { default: case CHSB_BACKPACK: { int iNumItems = TFInventoryManager()->GetLocalTFInventory()->GetItemCount(); if ( iNumItems == 1 ) { const wchar_t *wszItemsName = g_pVGuiLocalize->Find( "#Loadout_OpenBackpackDesc1" ); m_pItemsLabel->SetText( wszItemsName ); } else { wchar_t wzCount[10]; _snwprintf( wzCount, ARRAYSIZE( wzCount ), L"%d", iNumItems ); wchar_t wTemp[32]; g_pVGuiLocalize->ConstructString_safe( wTemp, g_pVGuiLocalize->Find("Loadout_OpenBackpackDesc"), 1, wzCount ); m_pItemsLabel->SetText( wTemp ); } } break; case CHSB_CRAFTING: m_pItemsLabel->SetText( g_pVGuiLocalize->Find( "Loadout_OpenCraftingDesc" ) ); break; case CHSB_ARMORY: m_pItemsLabel->SetText( g_pVGuiLocalize->Find( "Loadout_OpenArmoryDesc" ) ); break; case CHSB_TRADING: m_pItemsLabel->SetText( g_pVGuiLocalize->Find( "Loadout_OpenTradingDesc" ) ); break; }
int iX, iY; m_pSubButtons[nButton]->GetPos( iX, iY ); iX += (m_pSubButtons[nButton]->GetWide() * 0.5); iY += m_pSubButtons[nButton]->GetTall() + YRES(5);
m_pItemsLabel->SetVisible( true ); m_pItemsLabel->SetPos( iX - (m_pItemsLabel->GetWide() * 0.5), iY + (m_iItemLabelYPos - m_iClassLabelYPos) ); m_pItemsLabel->SetColorStr( m_ItemColor );
for ( int i = 0; i < CHSB_NUM_BUTTONS; i++ ) { m_pSubButtons[i]->SetArmed( false ); }
m_pSubButtons[nButton]->SetArmed( true ); m_pSubButtons[nButton]->RequestFocus(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnTick( void ) { if ( m_iCurrentClassIndex != TF_CLASS_UNDEFINED ) return; if ( !IsVisible() ) return;
if ( m_bRequestingInventoryRefresh && TFInventoryManager()->GetLocalTFInventory()->RetrievedInventoryFromSteam() ) { m_bRequestingInventoryRefresh = false; CloseWaitingDialog(); return; }
// if the class layout is dirty, invalidate our layout so that
// we'll animate the class buttons.
if ( m_bClassLayoutDirty ) { InvalidateLayout(); }
if ( !HasFocus() ) return;
// Don't respond to the mouse if we don't have items
if ( !TFInventoryManager()->GetLocalTFInventory()->RetrievedInventoryFromSteam() ) return;
if ( m_flStartExplanationsAt && m_flStartExplanationsAt < engine->Time() ) { m_flStartExplanationsAt = 0;
if ( ShouldShowExplanations() ) { tf_explanations_charinfopanel.SetValue( 1 );
CExplanationPopup *pPopup = dynamic_cast<CExplanationPopup*>( FindChildByName("StartExplanation") ); if ( pPopup ) { pPopup->Popup(); } } }
}
//-----------------------------------------------------------------------------
// Purpose: Handles mousing over classes
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::OnCursorMoved( int x, int y ) { RecalculateTargetClassLayoutAtPos( x, y ); }
//-----------------------------------------------------------------------------
// Purpose: Handles setting the highlighted class for both mouse and keyboard
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::RecalculateTargetClassLayoutAtPos( int x, int y ) { // Ignore mouse movement outside the buttons
bool bWithin = false; for ( int i = TF_FIRST_NORMAL_CLASS; i <= NUM_CLASSES_IN_LOADOUT_PANEL; i++ ) { if ( m_pClassButtons[i]->IsWithin(x,y) ) { bWithin = true; break; } }
if ( bWithin ) { m_iMouseXPos = x; m_iMouseYPos = y; RecalculateTargetClassLayout(); m_bClassLayoutDirty = true; } else { // See if we're over a sub button
bool bOverSubButton = false; for ( int i = 0; i < CHSB_NUM_BUTTONS; i++ ) { if ( m_pSubButtons[i]->IsWithin(x,y) ) { bOverSubButton = true; UpdateLabelFromSubButton( i ); } }
if ( !bOverSubButton && m_pClassLabel->IsVisible() ) { // Hide the class label
if ( m_iMouseXPos != -1 ) { m_iMouseXPos = -1; RecalculateTargetClassLayout(); m_bClassLayoutDirty = true; }
m_iOverSubButton = -1; m_iLabelSetToClass = -1; m_pClassLabel->SetVisible( false ); m_pItemsLabel->SetVisible( false ); } } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharInfoLoadoutSubPanel::RecalculateTargetClassLayout( void ) { // Now Layout the class images.
for ( int i = TF_FIRST_NORMAL_CLASS; i <= NUM_CLASSES_IN_LOADOUT_PANEL; i++ ) { int iIndex = GetRemappedMenuIndexForClass(i);
// Figure out where we'd be unscaled
int iXLeft = (GetWide() - ((m_iClassWideMin * NUM_CLASSES_IN_LOADOUT_PANEL) + (m_iClassXDelta * (NUM_CLASSES_IN_LOADOUT_PANEL-1)))) * 0.5; int iBaseX = iXLeft + ((m_iClassWideMin + m_iClassXDelta) * (iIndex-1));
// Scale based on distance from the mouse cursor.
int iCenterX = iBaseX + (m_iClassWideMin * 0.5);
float flScale = 0.0; if ( m_iMouseXPos >= 0 ) { flScale = RemapValClamped( abs(m_iMouseXPos - iCenterX), m_iClassDistanceMin, m_iClassDistanceMax, 1.0, 0.0 ); }
float iWide = RemapValClamped( flScale, 0.0, 1.0, m_iClassWideMin, m_iClassWideMax ); float iTall = RemapValClamped( flScale, 0.0, 1.0, m_iClassTallMin, m_iClassTallMax );
int iY = m_iClassYPos - ((iTall - m_iClassTallMin) * 0.5); int iX = iBaseX - ((iWide - m_iClassWideMin) * 0.5);
m_pClassButtons[i]->SetZPos( flScale * 100 );
// Cache off the target bounds for this class button
m_iClassLayout[i][0] = iX; m_iClassLayout[i][1] = iY; m_iClassLayout[i][2] = iWide; m_iClassLayout[i][3] = iTall; } }
void CCharInfoLoadoutSubPanel::MoveCharacterSelection( int nDirection ) { int nCurrent = 0;
if ( m_iLabelSetToClass != -1 ) { for ( int i = 0; i < ARRAYSIZE( g_nLoadoutClassOrder ); i++ ) { if ( m_iLabelSetToClass == g_nLoadoutClassOrder[ i ] ) { nCurrent = i; break; } }
nCurrent += nDirection;
if ( nCurrent < 0 ) { nCurrent = ARRAYSIZE( g_nLoadoutClassOrder ) - 1; } else if ( nCurrent >= ARRAYSIZE( g_nLoadoutClassOrder ) ) { nCurrent = 0; } }
for ( int i = 0; i < ARRAYSIZE( g_nLoadoutClassOrder ); i++ ) { m_pClassButtons[ g_nLoadoutClassOrder[ i ] ]->SetArmed( false ); }
// animate the class buttons
CImageButton *pButton = m_pClassButtons[ g_nLoadoutClassOrder[ nCurrent ] ]; int x, y, wide, tall; pButton->GetBounds( x, y, wide, tall ); RecalculateTargetClassLayoutAtPos( x + wide/2, y + tall/2 );
pButton->RequestFocus(); }
void CCharInfoLoadoutSubPanel::OnKeyCodeTyped(vgui::KeyCode code) { // turn off key handling in this panel when we're showing a loadout
// for one class
if ( m_iCurrentClassIndex != TF_CLASS_UNDEFINED ) { // let escape and B (aka "go back") through so we
// can actually get out of the loadout screen
if ( code == KEY_ESCAPE ) { BaseClass::OnKeyCodePressed( code ); } return; }
BaseClass::OnKeyCodeTyped( code ); }
void CCharInfoLoadoutSubPanel::OnKeyCodePressed(vgui::KeyCode code) { ButtonCode_t nButtonCode = GetBaseButtonCode( code );
// turn off key handling in this panel when we're showing a loadout
// for one class
if( m_iCurrentClassIndex != TF_CLASS_UNDEFINED ) { // let escape and B (aka "go back") through so we
// can actually get out of the loadout screen
if ( nButtonCode == KEY_XBUTTON_B ) { BaseClass::OnKeyCodePressed( code ); } return; }
if ( nButtonCode == KEY_XBUTTON_LEFT || nButtonCode == KEY_XSTICK1_LEFT || nButtonCode == KEY_XSTICK2_LEFT || nButtonCode == STEAMCONTROLLER_DPAD_LEFT || code == KEY_LEFT ) { if ( m_iLabelSetToClass != -1 ) { MoveCharacterSelection( -1 ); } else { UpdateLabelFromSubButton( m_iOverSubButton - 1 ); } return; } else if ( nButtonCode == KEY_XBUTTON_RIGHT || nButtonCode == KEY_XSTICK1_RIGHT || nButtonCode == KEY_XSTICK2_RIGHT || nButtonCode == STEAMCONTROLLER_DPAD_RIGHT || code == KEY_RIGHT ) { if ( m_iLabelSetToClass != -1 ) { MoveCharacterSelection( 1 ); } else { UpdateLabelFromSubButton( m_iOverSubButton + 1 ); } return; } else if ( nButtonCode == KEY_XBUTTON_UP || nButtonCode == KEY_XSTICK1_UP || nButtonCode == KEY_XSTICK2_UP || nButtonCode == STEAMCONTROLLER_DPAD_UP || code == KEY_UP ) { if ( m_iLabelSetToClass == -1 ) { m_iLabelSetToClass = g_nLoadoutClassOrder[ 0 ]; CImageButton *pButton = m_pClassButtons[ m_iLabelSetToClass ]; UpdateLabelFromClass( m_iLabelSetToClass );
int x, y, wide, tall; pButton->GetBounds( x, y, wide, tall ); RecalculateTargetClassLayoutAtPos( x + wide/2, y + tall/2 ); pButton->RequestFocus();
} return; } else if ( nButtonCode == KEY_XBUTTON_DOWN || nButtonCode == KEY_XSTICK1_DOWN || nButtonCode == KEY_XSTICK2_DOWN || nButtonCode == STEAMCONTROLLER_DPAD_DOWN || code == KEY_DOWN ) { if ( m_iLabelSetToClass != -1 ) { m_iLabelSetToClass = -1; m_pClassLabel->SetVisible( false ); m_pItemsLabel->SetVisible( false );
for ( int iPanel = 0; iPanel < ARRAYSIZE( g_nLoadoutClassOrder ); iPanel++ ) { int i = g_nLoadoutClassOrder[iPanel]; m_pClassButtons[i]->SetArmed( false ); }
UpdateLabelFromSubButton( 0 ); } return; }
BaseClass::OnKeyCodePressed( code ); }
|