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.
2233 lines
67 KiB
2233 lines
67 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
|
|
#include "cbase.h" |
|
#include "store/store_page.h" |
|
#include "vgui/ISurface.h" |
|
#include "vgui/IInput.h" |
|
#include "vgui/ILocalize.h" |
|
#include "gamestringpool.h" |
|
#include "econ_item_inventory.h" |
|
#include "econ_item_system.h" |
|
#include "item_model_panel.h" |
|
#include "store/store_panel.h" |
|
#include "store/store_preview_item.h" |
|
#include "store/store_viewcart.h" |
|
#include "rtime.h" |
|
#include "econ_ui.h" |
|
#include "store/store_page_new.h" |
|
#include "gc_clientsystem.h" |
|
#include "confirm_dialog.h" |
|
|
|
#ifdef TF_CLIENT_DLL |
|
#include "c_tf_gamestats.h" |
|
#include "c_tf_freeaccount.h" |
|
#endif // TF_CLIENT_DLL |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
#ifdef TF_CLIENT_DLL |
|
void AddSubKeyNamed( KeyValues *pKeys, const char *pszName ); |
|
#endif |
|
|
|
DECLARE_BUILD_FACTORY( CStorePreviewItemIcon ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CStoreItemControlsPanel::CStoreItemControlsPanel( vgui::Panel *pParent, const char *pPanelName, CItemModelPanel *pItemModelPanel ) |
|
: vgui::EditablePanel( pParent, pPanelName ), |
|
m_pItemModelPanel( pItemModelPanel ), |
|
m_pEntry( NULL ), |
|
m_bItemPanelEntered( false ), |
|
m_bButtonsVisible( false ) |
|
{ |
|
} |
|
|
|
void CStoreItemControlsPanel::SetMouseHoverHandler( Panel *pHandler ) |
|
{ |
|
m_pMouseHoverHandler = pHandler; |
|
} |
|
|
|
void CStoreItemControlsPanel::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
LoadControlSettings( |
|
ShouldUseNewStore() ? |
|
"Resource/UI/econ/store/v2/StoreItemControls.res" : |
|
"Resource/UI/econ/store/v1/StoreItemControls.res" |
|
); |
|
} |
|
|
|
const econ_store_entry_t *CStoreItemControlsPanel::GetItem() const |
|
{ |
|
return m_pEntry; |
|
} |
|
|
|
void CStoreItemControlsPanel::SetItem( const econ_store_entry_t *pEntry ) |
|
{ |
|
m_pEntry = pEntry; |
|
} |
|
|
|
void CStoreItemControlsPanel::SetButtonsVisible( bool bVisible ) |
|
{ |
|
m_bButtonsVisible = bVisible; |
|
|
|
for ( int i = 0; i < GetChildCount(); ++i ) |
|
{ |
|
CExButton *pButton = dynamic_cast< CExButton* >( GetChild( i ) ); |
|
if ( pButton ) |
|
{ |
|
pButton->SetVisible( bVisible ); |
|
pButton->SetArmed( false ); |
|
} |
|
} |
|
} |
|
|
|
void CStoreItemControlsPanel::OnCursorEntered() |
|
{ |
|
BaseClass::OnCursorEntered(); |
|
|
|
if ( m_pItemModelPanel && m_pItemModelPanel->HasItem() ) |
|
{ |
|
SetButtonsVisible( true ); |
|
} |
|
} |
|
|
|
void CStoreItemControlsPanel::OnCursorExited() |
|
{ |
|
BaseClass::OnCursorExited(); |
|
} |
|
|
|
void CStoreItemControlsPanel::OnItemPanelEntered() |
|
{ |
|
m_bItemPanelEntered = true; |
|
SetButtonsVisible( true ); |
|
} |
|
|
|
void CStoreItemControlsPanel::OnItemPanelExited() |
|
{ |
|
m_bItemPanelEntered = false; |
|
} |
|
|
|
void CStoreItemControlsPanel::OnThink() |
|
{ |
|
if ( !m_bItemPanelEntered ) |
|
{ |
|
if ( !IsCursorOver() ) |
|
{ |
|
SetButtonsVisible( false ); |
|
} |
|
} |
|
|
|
if ( m_pMouseHoverHandler.Get() ) |
|
{ |
|
KeyValues *pMsg = new KeyValues( "StoreItemControlsPanelHover", "entered", m_bButtonsVisible ); |
|
pMsg->SetPtr( "entry", (void *)m_pEntry ); |
|
PostMessage( m_pMouseHoverHandler.Get(), pMsg ); |
|
} |
|
} |
|
|
|
void CStoreItemControlsPanel::OnCommand( const char *command ) |
|
{ |
|
if ( !Q_strnicmp( command, "addtocart", 9 ) ) |
|
{ |
|
PostActionSignal( new KeyValues( "ItemAddToCart" ) ); |
|
} |
|
else if ( !Q_strnicmp( command, "preview_item", 12 ) ) |
|
{ |
|
PostActionSignal( new KeyValues( "ItemPreview" ) ); |
|
} |
|
else if ( !Q_strnicmp( command, "details", 7 ) ) |
|
{ |
|
PostActionSignal( new KeyValues( "ItemDetails" ) ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePreviewItemIcon::OnItemPanelMouseReleased( vgui::Panel *panel ) |
|
{ |
|
PostActionSignal(new KeyValues("ItemIconSelected", "icon", m_iIconIndex)); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CStorePricePanel::CStorePricePanel( vgui::Panel *pParent, const char *pPanelName ) |
|
: vgui::EditablePanel( pParent, pPanelName ) |
|
{ |
|
m_bOldDiscountVisibility = false; |
|
m_pPrice = NULL; |
|
m_pDiscount = NULL; |
|
m_pNew = NULL; |
|
m_pSale = NULL; |
|
m_pSaleBorder = NULL; |
|
m_pOGPrice = NULL; |
|
m_pCrossout = NULL; |
|
m_pLimited = NULL; |
|
m_pHighlighted = NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CStorePricePanel::~CStorePricePanel() |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char* CStorePricePanel::GetPanelResFile() |
|
{ |
|
return "Resource/UI/econ/store/v1/StorePrice.res"; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePricePanel::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
LoadControlSettings( GetPanelResFile() ); |
|
|
|
m_pPrice = dynamic_cast< CExLabel* >( FindChildByName( "Price" ) ); |
|
m_pDiscount = dynamic_cast< CExLabel* >( FindChildByName( "Discount" ) ); |
|
m_pHighlighted = dynamic_cast< CExLabel* >( FindChildByName( "Highlighted" ) ); |
|
m_pNew = dynamic_cast< CExLabel* >( FindChildByName( "NewLarge" ) ); |
|
if ( !m_pNew ) |
|
{ |
|
m_pNew = dynamic_cast< CExLabel* >( FindChildByName( "New" ) ); |
|
} |
|
m_pSale = dynamic_cast< CExLabel* >( FindChildByName( "Sale" ) ); |
|
m_pSaleBorder = dynamic_cast< vgui::EditablePanel* >( FindChildByName( "StorePriceBorder" ) ); |
|
m_pOGPrice = dynamic_cast< CExLabel* >( FindChildByName( "OG_Price" ) ); |
|
m_pCrossout = FindChildByName( "OG_Price_CrossOut" ); |
|
|
|
// Only support one "limited" |
|
m_pLimited = FindChildByName( "LimitedLarge" ); |
|
if ( !m_pLimited ) |
|
{ |
|
m_pLimited = FindChildByName( "Limited" ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePricePanel::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
if ( m_pPrice ) |
|
{ |
|
int contentWidth, contentHeight; |
|
m_pPrice->GetContentSize( contentWidth, contentHeight ); |
|
int iTextInsetX, iTextInsetY; |
|
m_pPrice->GetTextInset( &iTextInsetX, &iTextInsetY ); |
|
m_pPrice->SetWide( contentWidth + iTextInsetX ); |
|
m_pPrice->SetPos( GetWide() - m_pPrice->GetWide(), GetTall() - m_pPrice->GetTall() ); |
|
} |
|
|
|
if ( m_pPrice && m_pDiscount && m_pOGPrice ) |
|
{ |
|
int contentWidth, contentHeight; |
|
m_pDiscount->GetContentSize( contentWidth, contentHeight ); |
|
int iTextInsetX, iTextInsetY; |
|
m_pDiscount->GetTextInset( &iTextInsetX, &iTextInsetY ); |
|
m_pDiscount->SetWide( contentWidth + iTextInsetX ); |
|
m_pDiscount->SetPos( 0, GetTall() - m_pDiscount->GetTall() ); |
|
|
|
// Place original price in bottom-right corner, above the price label |
|
int aPricePos[2]; |
|
m_pPrice->GetPos( aPricePos[0], aPricePos[1] ); |
|
m_pOGPrice->SetWide( GetWide() ); |
|
m_pOGPrice->GetContentSize( contentWidth, contentHeight ); |
|
int aOGPricePos[2] = { 0, aPricePos[1] - contentHeight }; |
|
m_pOGPrice->SetPos( aOGPricePos[0], aOGPricePos[1] ); |
|
|
|
// Place crossout over original price, halfway down from its vertical starting position |
|
m_pCrossout->SetBounds( |
|
aOGPricePos[0] + m_pOGPrice->GetWide() - contentWidth, |
|
aOGPricePos[1] + contentHeight/2, contentWidth, m_pCrossout->GetTall() |
|
); |
|
} |
|
|
|
if ( m_pNew ) |
|
{ |
|
int contentWidth, contentHeight; |
|
m_pNew->GetContentSize( contentWidth, contentHeight ); |
|
int iTextInsetX, iTextInsetY; |
|
m_pNew->GetTextInset( &iTextInsetX, &iTextInsetY ); |
|
m_pNew->SetWide( contentWidth + iTextInsetX ); |
|
int iPosX, iPosY; |
|
m_pNew->GetPos( iPosX, iPosY ); |
|
m_pNew->SetPos( GetWide() - m_pNew->GetWide(), iPosY ); |
|
} |
|
|
|
if ( m_pHighlighted ) |
|
{ |
|
int contentWidth, contentHeight; |
|
m_pHighlighted->GetContentSize( contentWidth, contentHeight ); |
|
int iTextInsetX, iTextInsetY; |
|
m_pHighlighted->GetTextInset( &iTextInsetX, &iTextInsetY ); |
|
m_pHighlighted->SetWide( contentWidth + iTextInsetX ); |
|
int iPosX, iPosY; |
|
m_pHighlighted->GetPos( iPosX, iPosY ); |
|
m_pHighlighted->SetPos( GetWide() - m_pHighlighted->GetWide(), iPosY ); |
|
} |
|
|
|
if ( m_pSale ) |
|
{ |
|
int contentWidth, contentHeight; |
|
m_pSale->GetContentSize( contentWidth, contentHeight ); |
|
int iTextInsetX, iTextInsetY; |
|
m_pSale->GetTextInset( &iTextInsetX, &iTextInsetY ); |
|
m_pSale->SetWide( contentWidth + iTextInsetX ); |
|
int iPosX, iPosY; |
|
m_pSale->GetPos( iPosX, iPosY ); |
|
m_pSale->SetPos( GetWide() - m_pSale->GetWide(), iPosY ); |
|
} |
|
|
|
if ( m_pLimited ) |
|
{ |
|
int iPosX, iPosY; |
|
Panel *pRefPanel = ( m_pSale && m_pSale->IsVisible() ) ? m_pSale : ( m_pNew && m_pNew->IsVisible() ) ? m_pNew : NULL; |
|
if ( pRefPanel && pRefPanel->IsVisible() ) |
|
{ |
|
pRefPanel->GetPos( iPosX, iPosY ); |
|
m_pLimited->SetPos( GetWide() - m_pLimited->GetWide() - XRES( 3 ), iPosY + pRefPanel->GetTall() + YRES( 3 ) ); |
|
} |
|
else |
|
{ |
|
m_pLimited->GetPos( iPosX, iPosY ); |
|
m_pLimited->SetPos( GetWide() - m_pLimited->GetWide() - XRES( 3 ), iPosY ); |
|
} |
|
} |
|
|
|
if ( m_pSaleBorder ) |
|
{ |
|
m_pSaleBorder->SetSize( GetWide(), GetTall() ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePricePanel::SetPriceText( int iPrice, const char *pVariable, const econ_store_entry_t *pEntry ) |
|
{ |
|
if ( iPrice == 0 ) |
|
{ |
|
if ( pEntry->m_bIsMarketItem ) |
|
{ |
|
SetDialogVariable( pVariable, g_pVGuiLocalize->Find( "#Store_Market" ) ); |
|
} |
|
else |
|
{ |
|
SetDialogVariable( pVariable, "" ); |
|
} |
|
return; |
|
} |
|
|
|
wchar_t wzLocalizedPrice[ kLocalizedPriceSizeInChararacters ]; |
|
MakeMoneyString( wzLocalizedPrice, ARRAYSIZE( wzLocalizedPrice ), iPrice, EconUI()->GetStorePanel()->GetCurrency() ); |
|
|
|
if ( pEntry->m_bIsMarketItem ) |
|
{ |
|
wchar_t wzMarketString[96]; |
|
g_pVGuiLocalize->ConstructString_safe( |
|
wzMarketString, |
|
LOCCHAR( "%s1 %s2" ), |
|
2, |
|
g_pVGuiLocalize->Find( "#Store_Market" ), |
|
wzLocalizedPrice ); |
|
|
|
SetDialogVariable( pVariable, wzMarketString ); |
|
} |
|
else |
|
{ |
|
SetDialogVariable( pVariable, wzLocalizedPrice ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
static bool IsItemPreviewed( const econ_store_entry_t *pEntry, ECurrency eCurrency ) |
|
{ |
|
return (pEntry->GetItemDefinitionIndex() == InventoryManager()->GetLocalInventory()->GetPreviewItemDef()) |
|
&& !pEntry->IsOnSale( eCurrency ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void AddItemToCartHelper( const char *pszContext, const econ_store_entry_t *pEntry, ECartItemType eSelectedCartItemType ) |
|
{ |
|
Assert( pEntry ); |
|
|
|
CStoreCart *pCart = EconUI()->GetStorePanel()->GetCart(); |
|
const ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); |
|
|
|
// If this is the item we've previewing *and* it's the first one we've added |
|
// to the cart then we note that it's a preview item purchase and so we may |
|
// get a discount. |
|
ECartItemType eCartItemType = eSelectedCartItemType == kCartItem_Purchase && IsItemPreviewed( pEntry, eCurrency ) && !pCart->ContainsItemDefinition( pEntry->GetItemDefinitionIndex() ) |
|
? kCartItem_TryOutUpgrade |
|
: eSelectedCartItemType; |
|
|
|
pCart->AddToCart( pEntry, pszContext, eCartItemType ); |
|
EconUI()->GetStorePanel()->OnAddToCart(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void AddItemToCartHelper( const char *pszContext, item_definition_index_t unItemDef, ECartItemType eSelectedCartItemType ) |
|
{ |
|
const econ_store_entry_t *pEntry = EconUI()->GetStorePanel()->GetPriceSheet()->GetEntry( unItemDef ); |
|
if ( pEntry ) |
|
{ |
|
AddItemToCartHelper( pszContext, pEntry, eSelectedCartItemType ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePricePanel::SetItem( const econ_store_entry_t *pEntry ) |
|
{ |
|
const ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); |
|
|
|
item_price_t unPrice = pEntry->GetCurrentPrice( eCurrency ); |
|
SetPriceText( unPrice, "price", pEntry ); |
|
|
|
const bool bIsItemPreviewed = IsItemPreviewed( pEntry, eCurrency ); |
|
|
|
if ( bIsItemPreviewed ) |
|
{ |
|
// Make sure we're doing the math we think we're doing -- the item isn't on sale and so |
|
// we'll be setting a new price based on the base price. |
|
Assert( pEntry->GetCurrentPrice( eCurrency ) == pEntry->GetBasePrice( eCurrency ) ); |
|
Assert( unPrice == pEntry->GetBasePrice( eCurrency ) ); |
|
|
|
// Apply the preview period discount. |
|
unPrice *= EconUI()->GetStorePanel()->GetPriceSheet()->GetPreviewPeriodDiscount(); |
|
} |
|
|
|
item_price_t unBasePrice; |
|
const bool bIsDiscounted = pEntry->HasDiscount( eCurrency, &unBasePrice ); |
|
|
|
if ( m_pDiscount && m_pOGPrice ) |
|
{ |
|
// and discount |
|
if ( bIsDiscounted == false ) |
|
{ |
|
m_pDiscount->SetVisible( false ); |
|
m_pOGPrice->SetVisible( false ); |
|
} |
|
else |
|
{ |
|
SetPriceText( unBasePrice, "og_price", pEntry ); |
|
|
|
// set the discount and size |
|
float flDiscountPercentage = 1.0f - ( float(unPrice) / float(unBasePrice) ); |
|
wchar_t wszDiscount[16]; |
|
_snwprintf( wszDiscount, ARRAYSIZE( wszDiscount ), L"-%.0f%%", flDiscountPercentage * 100.0f ); |
|
m_pDiscount->SetText( wszDiscount ); |
|
|
|
m_pDiscount->SetVisible( true ); |
|
m_pOGPrice->SetVisible( true ); |
|
} |
|
} |
|
|
|
if ( m_pCrossout && m_pOGPrice ) |
|
{ |
|
m_pCrossout->SetVisible( bIsDiscounted ); |
|
} |
|
|
|
if ( m_pNew ) |
|
{ |
|
m_pNew->SetVisible( pEntry->m_bNew ); |
|
} |
|
|
|
if ( m_pHighlighted ) |
|
{ |
|
m_pHighlighted->SetVisible( pEntry->m_bHighlighted ); |
|
|
|
|
|
} |
|
|
|
if ( m_pSale ) |
|
{ |
|
bool bSaleVisible = false; |
|
|
|
// We don't check explicitly for "is on sale" here because other things like item previews can |
|
// adjust the price we're going to display to the user without adjusting the actual store entry. |
|
if ( unPrice != pEntry->GetBasePrice( eCurrency ) && ( m_pNew == NULL || !m_pNew->IsVisible() ) ) |
|
{ |
|
if ( bIsItemPreviewed ) |
|
{ |
|
m_pSale->SetText( "#TF_PreviewDiscount" ); |
|
} |
|
|
|
m_pSale->SetVisible( true ); |
|
bSaleVisible = true; |
|
} |
|
else |
|
{ |
|
m_pSale->SetVisible( false ); |
|
} |
|
|
|
if ( m_pSaleBorder ) |
|
{ |
|
m_pSaleBorder->SetVisible( !ShouldUseNewStore() && bSaleVisible ); |
|
} |
|
} |
|
|
|
if ( m_pLimited ) |
|
{ |
|
if ( pEntry->m_bLimited ) |
|
{ |
|
m_pLimited->SetVisible( true ); |
|
} |
|
else |
|
{ |
|
m_pLimited->SetVisible( false ); |
|
} |
|
} |
|
|
|
InvalidateLayout(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePricePanel::OnStoreItemControlsPanelHover( KeyValues *data ) |
|
{ |
|
// We don't care if there's no discount label to deal with |
|
if ( !m_pDiscount ) |
|
return; |
|
|
|
// Should the discount label be visible? |
|
const econ_store_entry_t *pEntry = (const econ_store_entry_t *)data->GetPtr( "entry" ); |
|
if ( !pEntry ) |
|
return; |
|
|
|
ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); |
|
if ( !pEntry->HasDiscount( eCurrency, NULL ) ) |
|
return; |
|
|
|
bool bEntered = data->GetInt( "entered" ) == 1; |
|
m_pDiscount->SetVisible( !bEntered ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CStorePage::CStorePage(Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData, const char *pPreviewItemResFile ) : vgui::PropertyPage(parent, "StorePage") |
|
{ |
|
m_pPageData = pPageData; |
|
|
|
m_pItemModelPanelKVs = NULL; |
|
m_pModelPanelLabelsKVs = NULL; |
|
m_pCartModelPanelKVs = NULL; |
|
m_pCartQuantityLabelKVs = NULL; |
|
|
|
m_pFeaturedItemPanel = NULL; |
|
|
|
m_pItemBackdropPanel = new EditablePanel( this, "ItemBackdrop" ); |
|
m_pMouseOverItemPanel = new CItemModelPanel( this, "mouseoveritempanel" ); |
|
m_pMouseOverTooltip = new CItemModelPanelToolTip( this ); |
|
m_pMouseOverTooltip->SetupPanels( this, m_pMouseOverItemPanel ); |
|
m_pMouseOverTooltip->SetPositioningStrategy( IPTTP_BOTTOM_SIDE ); |
|
|
|
if ( IsHomePage() ) |
|
{ |
|
if ( !ShouldUseNewStore() ) |
|
{ |
|
m_pFeaturedItemPanel = new CItemModelPanel( this, "featured_item_panel" ); |
|
m_pFeaturedItemPanel->SetActAsButton( true, true ); |
|
m_pFeaturedItemPanel->SetTooltip( m_pMouseOverTooltip, "" ); |
|
} |
|
|
|
m_pFilterComboBox = NULL; |
|
} |
|
else |
|
{ |
|
m_pFilterComboBox = new vgui::ComboBox( this, "ClassFilterComboBox", 11, false ); |
|
m_pFilterComboBox->SetVisible( false ); |
|
m_pFilterComboBox->AddActionSignalTarget( this ); |
|
} |
|
|
|
m_pPreviewItemResFile = pPreviewItemResFile; |
|
m_pPreviewPanel = NULL; |
|
m_pSelectedPanel = NULL; |
|
m_pNextPageButton = NULL; |
|
m_pPrevPageButton = NULL; |
|
m_pCheckoutButton = NULL; |
|
m_pPreviewItemButton = NULL; |
|
m_pAddToCartButtonPanel = NULL; |
|
m_iCurrentFilter = 0; |
|
m_pCartButton = NULL; |
|
m_pBackpackLabel = NULL; |
|
m_iSelectedItemDef = 0; |
|
m_iSelectDefOnPageShow = 0; |
|
m_iSelectPageOnPageShow = 0; |
|
m_iOldSelectedItemDef = 0; |
|
m_bShouldDeletePreviewPanel = false; |
|
m_bFilterDirty = true; |
|
|
|
ListenForGameEvent( "cart_updated" ); |
|
|
|
REGISTER_COLOR_AS_OVERRIDABLE( m_colItemPanelBG, "item_panel_bgcolor" ); |
|
REGISTER_COLOR_AS_OVERRIDABLE( m_colItemPanelBGMouseover, "item_panel_bgcolor_mouseover" ); |
|
REGISTER_COLOR_AS_OVERRIDABLE( m_colItemPanelBGSelected, "item_panel_bgcolor_selected" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CStorePage::~CStorePage() |
|
{ |
|
if ( m_pItemModelPanelKVs ) |
|
{ |
|
m_pItemModelPanelKVs->deleteThis(); |
|
m_pItemModelPanelKVs = NULL; |
|
} |
|
if ( m_pCartModelPanelKVs ) |
|
{ |
|
m_pCartModelPanelKVs->deleteThis(); |
|
m_pCartModelPanelKVs = NULL; |
|
} |
|
if ( m_pCartQuantityLabelKVs ) |
|
{ |
|
m_pCartQuantityLabelKVs->deleteThis(); |
|
m_pCartQuantityLabelKVs = NULL; |
|
} |
|
if ( m_pModelPanelLabelsKVs ) |
|
{ |
|
m_pModelPanelLabelsKVs->deleteThis(); |
|
m_pModelPanelLabelsKVs = NULL; |
|
} |
|
if ( m_bShouldDeletePreviewPanel && m_pPreviewPanel ) |
|
{ |
|
delete m_pPreviewPanel; |
|
m_pPreviewPanel = NULL; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnPostCreate() |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char *CStorePage::GetPageResFile( void ) |
|
{ |
|
return m_pPageData->m_pchPageRes; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CStorePreviewItemPanel *CStorePage::CreatePreviewPanel( void ) |
|
{ |
|
return new CStorePreviewItemPanel( this, m_pPreviewItemResFile, "storepreviewitem", this ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
// First time through, create our preview panel |
|
if ( ( ShouldUseNewStore() || !IsHomePage() ) && !m_pPreviewPanel ) |
|
{ |
|
m_pPreviewPanel = CreatePreviewPanel(); |
|
|
|
// Force it to load it's scheme now, because it needs to be done before we set it's visibility below |
|
m_pPreviewPanel->InvalidateLayout( false, true ); |
|
m_pPreviewPanel->SetVisible( false ); |
|
} |
|
|
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
KeyValues *pConditions = NULL; |
|
#ifdef TF_CLIENT_DLL |
|
const char *pszHoliday = UTIL_GetActiveHolidayString(); |
|
if ( pszHoliday && pszHoliday[0] ) |
|
{ |
|
pConditions = new KeyValues( "conditions" ); |
|
|
|
char szCondition[64]; |
|
Q_snprintf( szCondition, sizeof( szCondition ), "if_%s", pszHoliday ); |
|
AddSubKeyNamed( pConditions, szCondition ); |
|
} |
|
#endif |
|
|
|
LoadControlSettings( GetPageResFile(), NULL, NULL, pConditions ); |
|
|
|
if ( pConditions ) |
|
{ |
|
pConditions->deleteThis(); |
|
} |
|
|
|
m_bReapplyItemKVs = true; |
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
SetBorderForItem( m_vecItemPanels[i].m_pItemModelPanel, false ); |
|
} |
|
|
|
m_pMouseOverItemPanel->SetBorder( pScheme->GetBorder("LoadoutItemPopupBorder") ); |
|
|
|
m_pNextPageButton = dynamic_cast<CExButton*>( FindChildByName("NextPageButton") ); |
|
m_pPrevPageButton = dynamic_cast<CExButton*>( FindChildByName("PrevPageButton") ); |
|
m_pCheckoutButton = dynamic_cast<CExButton*>( FindChildByName("CheckoutButton") ); |
|
m_pPreviewItemButton = dynamic_cast<CExButton*>( FindChildByName("PreviewItemButton") ); |
|
m_pAddToCartButtonPanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName("AddToCartButton") ); |
|
if ( m_pAddToCartButtonPanel ) |
|
{ |
|
CExButton *pButton = dynamic_cast<CExButton*>( m_pAddToCartButtonPanel->FindChildByName("SubButton") ); |
|
if ( pButton ) |
|
{ |
|
pButton->AddActionSignalTarget( GetVPanel() ); |
|
} |
|
} |
|
m_pCurPageLabel = dynamic_cast<vgui::Label*>( FindChildByName("CurPageLabel") ); |
|
m_pCartButton = dynamic_cast<CExButton*>( FindChildByName("CartButton") ); |
|
m_pBackpackLabel = dynamic_cast<vgui::Label*>( FindChildByName("BackpackSpaceLabel") ); |
|
if ( m_pBackpackLabel ) |
|
{ |
|
m_colBackpackOrg = m_pBackpackLabel->GetFgColor(); |
|
} |
|
|
|
m_pItemDetailsButtonPanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName("ItemDetailsButton") ); |
|
if ( m_pItemDetailsButtonPanel ) |
|
{ |
|
CExButton *pButton = dynamic_cast<CExButton*>( m_pItemDetailsButtonPanel->FindChildByName("SubButton") ); |
|
if ( pButton ) |
|
{ |
|
pButton->AddActionSignalTarget( GetVPanel() ); |
|
} |
|
} |
|
m_pItemPreviewButtonPanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName("ItemPreviewButton") ); |
|
if ( m_pItemPreviewButtonPanel ) |
|
{ |
|
CExButton *pButton = dynamic_cast<CExButton*>( m_pItemPreviewButtonPanel->FindChildByName("SubButton") ); |
|
if ( pButton ) |
|
{ |
|
pButton->AddActionSignalTarget( GetVPanel() ); |
|
} |
|
} |
|
|
|
m_pCartFeaturedItemImage = dynamic_cast<vgui::ImagePanel*>( FindChildByName("CartFeaturedItemSymbol") ); |
|
if ( m_pCartFeaturedItemImage ) |
|
{ |
|
m_pCartFeaturedItemImage->SetMouseInputEnabled( false ); |
|
m_pCartFeaturedItemImage->SetKeyBoardInputEnabled( false ); |
|
} |
|
|
|
vgui::Panel *pPanel = FindChildByName("CartImage"); |
|
if ( pPanel ) |
|
{ |
|
pPanel->SetMouseInputEnabled( false ); |
|
pPanel->SetKeyBoardInputEnabled( false ); |
|
} |
|
pPanel = FindChildByName("FeaturedItemSymbol"); |
|
if ( pPanel ) |
|
{ |
|
pPanel->SetMouseInputEnabled( false ); |
|
pPanel->SetKeyBoardInputEnabled( false ); |
|
} |
|
pPanel = FindChildByName("FeaturedItemLabel"); |
|
if ( pPanel ) |
|
{ |
|
pPanel->SetMouseInputEnabled( false ); |
|
pPanel->SetKeyBoardInputEnabled( false ); |
|
} |
|
pPanel = FindChildByName("FeaturedItemPrice"); |
|
if ( pPanel ) |
|
{ |
|
pPanel->SetMouseInputEnabled( false ); |
|
pPanel->SetKeyBoardInputEnabled( false ); |
|
} |
|
|
|
if ( m_pFilterComboBox ) |
|
{ |
|
vgui::HFont hFont = pScheme->GetFont( "HudFontSmallestBold", true ); |
|
m_pFilterComboBox->SetFont( hFont ); |
|
UpdateFilteredItems(); |
|
UpdateFilterComboBox(); |
|
|
|
// Move to "All items" selected |
|
m_pFilterComboBox->SilentActivateItemByRow( 0 ); |
|
} |
|
|
|
if ( m_pItemBackdropPanel ) |
|
{ |
|
m_pItemBackdropPanel->SetBgColor( m_colItemBackdropPanel ); |
|
} |
|
|
|
SetDetailsVisible( true ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::ApplySettings( KeyValues *inResourceData ) |
|
{ |
|
BaseClass::ApplySettings( inResourceData ); |
|
|
|
m_colItemBackdropPanel = inResourceData->GetColor( "item_backdrop_color" ); |
|
|
|
KeyValues *pItemKV = inResourceData->FindKey( "modelpanels_kv" ); |
|
if ( pItemKV ) |
|
{ |
|
if ( m_pItemModelPanelKVs ) |
|
{ |
|
m_pItemModelPanelKVs->deleteThis(); |
|
} |
|
m_pItemModelPanelKVs = new KeyValues("modelpanels_kv"); |
|
pItemKV->CopySubkeys( m_pItemModelPanelKVs ); |
|
} |
|
|
|
pItemKV = inResourceData->FindKey( "modelpanel_labels_kv" ); |
|
if ( pItemKV ) |
|
{ |
|
if ( m_pModelPanelLabelsKVs ) |
|
{ |
|
m_pModelPanelLabelsKVs->deleteThis(); |
|
} |
|
m_pModelPanelLabelsKVs = new KeyValues("modelpanel_labels_kv"); |
|
pItemKV->CopySubkeys( m_pModelPanelLabelsKVs ); |
|
} |
|
|
|
pItemKV = inResourceData->FindKey( "cart_modelpanels_kv" ); |
|
if ( pItemKV ) |
|
{ |
|
if ( m_pCartModelPanelKVs ) |
|
{ |
|
m_pCartModelPanelKVs->deleteThis(); |
|
} |
|
m_pCartModelPanelKVs = new KeyValues("cart_modelpanels_kv"); |
|
pItemKV->CopySubkeys( m_pCartModelPanelKVs ); |
|
} |
|
|
|
pItemKV = inResourceData->FindKey( "cart_labels_kv" ); |
|
if ( pItemKV ) |
|
{ |
|
if ( m_pCartQuantityLabelKVs ) |
|
{ |
|
m_pCartQuantityLabelKVs->deleteThis(); |
|
} |
|
m_pCartQuantityLabelKVs = new KeyValues("cart_labels_kv"); |
|
pItemKV->CopySubkeys( m_pCartQuantityLabelKVs ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::PerformLayout( void ) |
|
{ |
|
if ( m_bReapplyItemKVs ) |
|
{ |
|
m_bReapplyItemKVs = false; |
|
|
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
if ( m_pItemModelPanelKVs ) |
|
{ |
|
m_vecItemPanels[i].m_pItemModelPanel->ApplySettings( m_pItemModelPanelKVs ); |
|
SetBorderForItem( m_vecItemPanels[i].m_pItemModelPanel, false ); |
|
m_vecItemPanels[i].m_pItemModelPanel->InvalidateLayout(); |
|
} |
|
m_vecItemPanels[i].m_pStorePricePanel->InvalidateLayout(); |
|
} |
|
|
|
if ( m_pCartModelPanelKVs ) |
|
{ |
|
FOR_EACH_VEC( m_pCartModelPanels, i ) |
|
{ |
|
m_pCartModelPanels[i]->ApplySettings( m_pCartModelPanelKVs ); |
|
SetBorderForItem( m_pCartModelPanels[i], false ); |
|
m_pCartModelPanels[i]->InvalidateLayout(); |
|
} |
|
} |
|
|
|
if ( m_pCartQuantityLabelKVs ) |
|
{ |
|
FOR_EACH_VEC( m_pCartQuantityLabels, i ) |
|
{ |
|
m_pCartQuantityLabels[i]->ApplySettings( m_pCartQuantityLabelKVs ); |
|
m_pCartQuantityLabels[i]->InvalidateLayout(); |
|
} |
|
} |
|
|
|
if ( m_pModelPanelLabelsKVs ) |
|
{ |
|
FOR_EACH_VEC( m_pCartQuantityLabels, i ) |
|
{ |
|
m_pCartQuantityLabels[i]->ApplySettings( m_pModelPanelLabelsKVs ); |
|
m_pCartQuantityLabels[i]->InvalidateLayout(); |
|
} |
|
} |
|
} |
|
|
|
BaseClass::PerformLayout(); |
|
|
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
CItemModelPanel *pItemModelPanel = m_vecItemPanels[i].m_pItemModelPanel; |
|
CStorePricePanel *pItemPricePanel = m_vecItemPanels[i].m_pStorePricePanel; |
|
CStoreItemControlsPanel *pItemControlsPanel = m_vecItemPanels[i].m_pItemControlsPanel; |
|
pItemModelPanel->SetVisible( true ); |
|
pItemModelPanel->SetNoItemText( "#SelectNoItemSlot" ); |
|
|
|
PositionItemPanel(pItemModelPanel, i ); |
|
|
|
int iX,iY,iW,iH; |
|
pItemModelPanel->GetBounds( iX, iY, iW, iH ); |
|
// Position our price label and controls |
|
pItemPricePanel->SetVisible( pItemModelPanel->HasItem() ); |
|
pItemPricePanel->SetBounds( iX, iY, iW, iH ); |
|
|
|
pItemPricePanel->InvalidateLayout( true ); |
|
|
|
pItemControlsPanel->SetPos( iX + m_iItemControlsXOffset, iY + iH - pItemControlsPanel->GetTall() - m_iItemControlsYOffset ); |
|
} |
|
|
|
if ( m_pItemBackdropPanel && m_vecItemPanels.Count() >= 2 ) |
|
{ |
|
CItemModelPanel *pTopLeftPanel = m_vecItemPanels.Head().m_pItemModelPanel; |
|
CItemModelPanel *pBottomRightPanel = m_vecItemPanels.Tail().m_pItemModelPanel; |
|
|
|
int aItemBackdropBounds[4]; |
|
if ( pTopLeftPanel && pBottomRightPanel ) |
|
{ |
|
int nX, nY; |
|
pTopLeftPanel->GetPos( nX, nY ); |
|
|
|
aItemBackdropBounds[0] = nX - m_iItemBackdropLeftMargin; |
|
aItemBackdropBounds[1] = nY - m_iItemBackdropTopMargin; |
|
|
|
pBottomRightPanel->GetPos( nX, nY ); |
|
aItemBackdropBounds[2] = nX + pBottomRightPanel->GetWide() + m_iItemBackdropRightMargin - aItemBackdropBounds[0]; |
|
aItemBackdropBounds[3] = nY + pBottomRightPanel->GetTall() + m_iItemBackdropBottomMargin - aItemBackdropBounds[1]; |
|
|
|
m_pItemBackdropPanel->SetBounds( aItemBackdropBounds[0], aItemBackdropBounds[1], aItemBackdropBounds[2], aItemBackdropBounds[3] ); |
|
|
|
m_pItemBackdropPanel->SetPaintBackgroundType( m_iItemBackdropPaintBackgroundType ); |
|
m_pItemBackdropPanel->SetZPos( m_iItemBackdropZPos ); |
|
} |
|
} |
|
|
|
if ( m_pCartModelPanels.Count() > 0 ) |
|
{ |
|
bool bFeaturedImagePanelVisible = false; |
|
CStoreCart *pCart = EconUI()->GetStorePanel()->GetCart(); |
|
|
|
int iCartX, iCartY; |
|
m_pCartButton->GetPos( iCartX, iCartY ); |
|
int iCartModelWide = m_pCartModelPanels[0]->GetWide(); |
|
FOR_EACH_VEC( m_pCartModelPanels, i ) |
|
{ |
|
if ( m_pCartModelPanels[i]->HasItem() ) |
|
{ |
|
m_pCartModelPanels[i]->SetVisible( true ); |
|
m_pCartQuantityLabels[i]->SetVisible( true ); |
|
|
|
int iX = iCartX + m_pCartButton->GetWide() + (XRES(4) * (i+1)) + (iCartModelWide * i); |
|
m_pCartModelPanels[i]->SetPos( iX, iCartY ); |
|
int iY = iCartY + m_pCartModelPanels[i]->GetTall() - m_pCartQuantityLabels[i]->GetTall(); |
|
m_pCartQuantityLabels[i]->SetPos( iX + iCartModelWide - m_pCartQuantityLabels[i]->GetWide(), iY ); |
|
|
|
// If we're the featured item, show it |
|
cart_item_t *pCartItem = pCart->GetItem(i); |
|
if ( pCartItem && ( pCartItem->pEntry == EconUI()->GetStorePanel()->GetFeaturedEntry() ) ) |
|
{ |
|
bFeaturedImagePanelVisible = true; |
|
|
|
if ( m_pCartFeaturedItemImage ) |
|
{ |
|
m_pCartFeaturedItemImage->SetPos( iX - XRES(4), iY - YRES(10) ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
if ( m_pCartFeaturedItemImage && m_pCartFeaturedItemImage->IsVisible() != bFeaturedImagePanelVisible ) |
|
{ |
|
m_pCartFeaturedItemImage->SetVisible( bFeaturedImagePanelVisible ); |
|
} |
|
} |
|
|
|
if ( m_pCurPageLabel ) |
|
{ |
|
bool bMultiplePages = (GetNumPages() > 1); |
|
m_pCurPageLabel->SetVisible( bMultiplePages ); |
|
m_pNextPageButton->SetVisible( bMultiplePages ); |
|
m_pPrevPageButton->SetVisible( bMultiplePages ); |
|
if ( bMultiplePages ) |
|
{ |
|
m_pNextPageButton->SetEnabled( m_iCurrentPage < (GetNumPages()-1) ); |
|
m_pPrevPageButton->SetEnabled( m_iCurrentPage > 0 ); |
|
} |
|
} |
|
|
|
if ( IsHomePage() ) |
|
{ |
|
const store_promotion_spend_for_free_item_t *pPromotion = EconUI()->GetStorePanel()->GetPriceSheet()->GetStorePromotion_SpendForFreeItem(); |
|
wchar_t wszText[1024]; |
|
wchar_t wszPriceThreshold[ kLocalizedPriceSizeInChararacters ]; |
|
ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); |
|
AssertMsg( eCurrency >= k_ECurrencyUSD && eCurrency < k_ECurrencyMax, "Invalid currency!" ); |
|
|
|
int iPriceThreshold = pPromotion->m_rgusPriceThreshold[ eCurrency ]; |
|
MakeMoneyString( wszPriceThreshold, ARRAYSIZE( wszPriceThreshold ), iPriceThreshold, EconUI()->GetStorePanel()->GetCurrency() ); |
|
bool bIsFreeTrial = false; |
|
#ifdef TF_CLIENT_DLL |
|
bIsFreeTrial = IsFreeTrialAccount(); |
|
#endif |
|
const char *pszLocString = bIsFreeTrial ? "#Store_FreeTrial_BonusText" : "#Store_Promotion_SpendForGift"; |
|
const char *pszElementName = bIsFreeTrial ? "BonusTextLabel" : "PromotionLabel_BonusItem"; |
|
|
|
g_pVGuiLocalize->ConstructString_safe( wszText, g_pVGuiLocalize->Find( pszLocString ), 1, wszPriceThreshold ); |
|
CExLabel *pPromotionText = dynamic_cast< CExLabel* >( FindChildByName( pszElementName, true ) ); |
|
if ( pPromotionText ) |
|
{ |
|
pPromotionText->SetText( wszText ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::PositionItemPanel( CItemModelPanel *pPanel, int iIndex ) |
|
{ |
|
CItemModelPanel *pRealPanel = m_vecItemPanels[iIndex].m_pItemModelPanel; |
|
|
|
int iOffsetIndex = iIndex; |
|
int iYPosOffset = 0; |
|
int iCenter = GetWide() * 0.5; |
|
int iButtonX = (iOffsetIndex % GetNumColumns()); |
|
int iButtonY = (iOffsetIndex / GetNumColumns()); |
|
int iXPos = m_iItemXPos + (iCenter + m_iItemOffcenterX) + (iButtonX * pRealPanel->GetWide()) + (m_iItemXDelta * iButtonX); |
|
int iYPos = m_iItemYPos + (iButtonY * pRealPanel->GetTall() ) + (m_iItemYDelta * iButtonY) + iYPosOffset; |
|
|
|
pRealPanel->SetPos( iXPos, iYPos ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnPageShow( void ) |
|
{ |
|
m_iCurrentPage = m_iSelectPageOnPageShow; |
|
m_iSelectPageOnPageShow = 0; |
|
|
|
// !KLUDGE! |
|
SetDetailsVisible( !ShouldUseNewStore() ); |
|
|
|
m_bReapplyItemKVs = true; |
|
BaseClass::OnPageShow(); |
|
|
|
if ( !IsHomePage() ) |
|
{ |
|
EconUI()->Gamestats_Store( IE_STORE_TAB_CHANGED, NULL, GetPageName() ); |
|
} |
|
|
|
m_pMouseOverItemPanel->SetVisible( false ); |
|
|
|
CreateItemPanels(); |
|
|
|
if ( m_pFilterComboBox ) |
|
{ |
|
SetFilter( 0 ); |
|
m_pFilterComboBox->SilentActivateItemByRow( 0 ); |
|
// m_pFilterComboBox->SetVisible( !IsHomePage() ); |
|
} |
|
|
|
// Setup sort by newest |
|
if ( m_pPageData && !ShouldUseNewStore() ) |
|
{ |
|
eEconStoreSortType iSortType = kEconStoreSortType_DateNewest; |
|
CEconStorePriceSheet *pPriceSheet = EconUI()->GetStorePanel()->GetPriceSheetForEdit(); |
|
pPriceSheet->SetEconStoreSortType( iSortType ); |
|
|
|
CEconStoreCategoryManager::StoreCategory_t *pPageData = const_cast< CEconStoreCategoryManager::StoreCategory_t * >( m_pPageData ); |
|
pPageData->m_vecEntries.SetLessContext( pPriceSheet ); |
|
pPageData->m_vecEntries.RedoSort( true ); |
|
|
|
UpdateFilteredItems(); |
|
} |
|
|
|
UpdateModelPanels(); |
|
|
|
if ( m_pCheckoutButton ) |
|
{ |
|
m_pCheckoutButton->RequestFocus(); |
|
} |
|
|
|
if ( m_iSelectDefOnPageShow ) |
|
{ |
|
m_iSelectDefOnPageShow = 0; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CStorePricePanel* CStorePage::CreatePricePanel( int iIndex ) |
|
{ |
|
if ( m_pPageData && !Q_strcmp( m_pPageData->m_pchPageClass, "CStorePage_Popular" ) ) |
|
return vgui::SETUP_PANEL( new CStorePricePanel_Popular( this, "StorePrice", iIndex + 1 ) ); |
|
|
|
if ( m_pPageData && !Q_strcmp( m_pPageData->m_pchPageClass, "CStorePage_New" ) ) |
|
return vgui::SETUP_PANEL( new CStorePricePanel_New( this, "StorePrice" ) ); |
|
|
|
if ( m_pPageData && !Q_strcmp( m_pPageData->m_pchPageClass, "CStorePage_Bundles" ) ) |
|
return vgui::SETUP_PANEL( new CStorePricePanel_Bundles( this, "StorePrice" ) ); |
|
|
|
return vgui::SETUP_PANEL( new CStorePricePanel( this, "StorePrice" ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OrderItemsForDisplay( CUtlVector<const econ_store_entry_t *>& vecItems ) const |
|
{ |
|
/* |
|
// See how I tread upon all the holy concepts of OOP. |
|
if ( m_pPageData && |
|
!Q_strcmp( m_pPageData->m_pchPageClass, "CStorePage_Bundles" ) && |
|
!ShouldUseNewStore() ) |
|
{ |
|
vecItems.Sort( &ItemDisplayOrderSort_UseSortOverride ); |
|
} |
|
*/ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::CreateItemPanels( void ) |
|
{ |
|
int iNumPanels = GetNumItemPanels(); |
|
if ( m_pPageData && m_vecItemPanels.Count() < iNumPanels ) |
|
{ |
|
for ( int i = m_vecItemPanels.Count(); i < iNumPanels; i++ ) |
|
{ |
|
int idx = m_vecItemPanels.AddToTail(); |
|
item_panel &itempanel = m_vecItemPanels[idx]; |
|
CItemModelPanel *pPanel = vgui::SETUP_PANEL( new CItemModelPanel( this, VarArgs("modelpanel%d", i) ) ); |
|
pPanel->SetShowQuantity( true ); |
|
pPanel->SetActAsButton( true, true ); |
|
itempanel.m_pItemModelPanel = pPanel; |
|
|
|
pPanel->SetTooltip( m_pMouseOverTooltip, "" ); |
|
|
|
// Create our price panel too |
|
CStorePricePanel *pPricePanel = CreatePricePanel( i ); |
|
pPricePanel->SetMouseInputEnabled( false ); |
|
pPricePanel->SetKeyBoardInputEnabled( false ); |
|
itempanel.m_pStorePricePanel = pPricePanel; |
|
|
|
// and controls |
|
CStoreItemControlsPanel *pControlsPanel = vgui::SETUP_PANEL( new CStoreItemControlsPanel( this, "StoreItemControls", pPanel ) ); |
|
//pControlsPanel->AddActionSignalTarget( this ); |
|
if ( ShouldUseNewStore() ) |
|
{ |
|
pControlsPanel->SetMouseHoverHandler( pPricePanel ); |
|
} |
|
itempanel.m_pItemControlsPanel = pControlsPanel; |
|
} |
|
|
|
m_EntryIndices.SetCountNonDestructively( m_vecItemPanels.Count() ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnCommand( const char *command ) |
|
{ |
|
if ( !Q_strnicmp( command, "nextpage", 8 ) ) |
|
{ |
|
if ( m_iCurrentPage < (GetNumPages()-1) ) |
|
{ |
|
m_iCurrentPage++; |
|
UpdateModelPanels(); |
|
} |
|
return; |
|
} |
|
else if ( !Q_strnicmp( command, "prevpage", 8 ) ) |
|
{ |
|
if ( m_iCurrentPage > 0 ) |
|
{ |
|
m_iCurrentPage--; |
|
UpdateModelPanels(); |
|
} |
|
return; |
|
} |
|
else if ( !Q_strnicmp( command, "preview_item", 12 ) ) |
|
{ |
|
PreviewSelectionItem(); |
|
return; |
|
} |
|
else if ( !Q_strnicmp( command, "addtocart", 9 ) ) |
|
{ |
|
AddSelectionToCart(); |
|
return; |
|
} |
|
else if ( !Q_strnicmp( command, "viewcart", 8 ) ) |
|
{ |
|
OpenStoreViewCartPanel(); |
|
return; |
|
} |
|
else if ( !Q_strnicmp( command, "startshopping", 8 ) ) |
|
{ |
|
PostMessage( EconUI()->GetStorePanel(), new KeyValues("StartShopping") ); |
|
return; |
|
} |
|
else if ( !Q_strnicmp( command, "checkout", 8 ) ) |
|
{ |
|
EconUI()->GetStorePanel()->InitiateCheckout( false ); |
|
return; |
|
} |
|
else if ( !Q_stricmp( command, "show_details" ) ) |
|
{ |
|
if ( m_pSelectedPanel ) |
|
{ |
|
CEconItemView *pItem = m_pSelectedPanel->GetItem(); |
|
if ( pItem ) |
|
{ |
|
SetDetailsVisible( true ); |
|
} |
|
} |
|
return; |
|
} |
|
else if ( !Q_stricmp( command, "show_preview" ) ) |
|
{ |
|
SetDetailsVisible( false ); |
|
return; |
|
} |
|
else if ( !Q_strnicmp( command, "marketplace", 8 ) ) |
|
{ |
|
if ( steamapicontext && steamapicontext->SteamFriends() ) |
|
{ |
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( "http://steamcommunity.com/market/search?appid=440" ); |
|
} |
|
return; |
|
} |
|
else if ( !Q_stricmp( command, "reloadscheme" ) ) |
|
{ |
|
InvalidateLayout( false, true ); |
|
SetVisible( true ); |
|
UpdateSelectionInfoPanel(); |
|
return; |
|
} |
|
else |
|
{ |
|
engine->ClientCmd( const_cast<char *>( command ) ); |
|
} |
|
|
|
BaseClass::OnCommand( command ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::FireGameEvent( IGameEvent *event ) |
|
{ |
|
const char * type = event->GetName(); |
|
|
|
if ( Q_strcmp(type, "cart_updated") == 0 ) |
|
{ |
|
UpdateCart(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnMouseWheeled( int delta ) |
|
{ |
|
if ( m_vecItemPanels.Count() == 0 ) |
|
{ |
|
// on home page, likely |
|
return; |
|
} |
|
|
|
int oldSelectionIndex = -1; |
|
int currentSelectionIndex = -1; |
|
|
|
// deselect everything |
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
if ( m_vecItemPanels[i].m_pItemModelPanel->IsSelected() ) |
|
{ |
|
oldSelectionIndex = i; |
|
m_vecItemPanels[i].m_pItemModelPanel->SetSelected( false ); |
|
SetBorderForItem( m_vecItemPanels[i].m_pItemModelPanel, false ); |
|
} |
|
} |
|
|
|
// step selection ahead |
|
if ( delta < 0 ) |
|
{ |
|
currentSelectionIndex = oldSelectionIndex+1; |
|
|
|
if ( currentSelectionIndex >= m_vecItemPanels.Count() ) |
|
{ |
|
if ( m_iCurrentPage < (GetNumPages()-1) ) |
|
{ |
|
currentSelectionIndex = 0; |
|
m_iCurrentPage++; |
|
UpdateModelPanels(); |
|
} |
|
else |
|
{ |
|
currentSelectionIndex = m_vecItemPanels.Count(); |
|
} |
|
} |
|
else if ( !m_vecItemPanels[ currentSelectionIndex ].m_pItemModelPanel->HasItem() ) |
|
{ |
|
// don't move into empty slots |
|
currentSelectionIndex = oldSelectionIndex; |
|
} |
|
} |
|
else if ( delta > 0 ) |
|
{ |
|
currentSelectionIndex = oldSelectionIndex-1; |
|
|
|
if ( currentSelectionIndex < 0 ) |
|
{ |
|
if ( m_iCurrentPage > 0 ) |
|
{ |
|
currentSelectionIndex = m_vecItemPanels.Count()-1; |
|
m_iCurrentPage--; |
|
UpdateModelPanels(); |
|
} |
|
else |
|
{ |
|
currentSelectionIndex = 0; |
|
} |
|
} |
|
else if ( !m_vecItemPanels[ currentSelectionIndex ].m_pItemModelPanel->HasItem() ) |
|
{ |
|
// don't move into empty slots |
|
currentSelectionIndex = oldSelectionIndex; |
|
} |
|
} |
|
else |
|
{ |
|
// no actual wheel movement |
|
return; |
|
} |
|
|
|
// sanity check |
|
currentSelectionIndex = clamp( currentSelectionIndex, 0, m_vecItemPanels.Count()-1 ); |
|
|
|
m_pSelectedPanel = m_vecItemPanels[ currentSelectionIndex ].m_pItemModelPanel; |
|
m_pSelectedPanel->SetSelected( ShouldUseNewStore() ); |
|
SetBorderForItem( m_pSelectedPanel, false ); |
|
UpdateSelectionInfoPanel(); |
|
|
|
if ( currentSelectionIndex != oldSelectionIndex ) |
|
{ |
|
vgui::surface()->PlaySound( "ui/buttonclick.wav" ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CStorePage::AssignItemToPanel( CItemModelPanel *pPanel, int iIndex ) |
|
{ |
|
iIndex += (m_iCurrentPage * GetNumItemPanels()); |
|
if ( iIndex >= 0 && iIndex < m_FilteredEntries.Count() ) |
|
{ |
|
CEconItemView ItemData; |
|
ItemData.Init( m_FilteredEntries[iIndex]->GetItemDefinitionIndex(), AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); |
|
ItemData.SetItemQuantity( m_FilteredEntries[iIndex]->GetQuantity() ); |
|
ItemData.SetClientItemFlags( kEconItemFlagClient_Preview | kEconItemFlagClient_StoreItem ); |
|
pPanel->SetItem( &ItemData ); |
|
|
|
return iIndex; |
|
} |
|
|
|
pPanel->SetItem( NULL ); |
|
return -1; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CStorePage::GetNumPages( void ) |
|
{ |
|
return ceil( (float)m_FilteredEntries.Count() / (float)GetNumItemPanels() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
/* static */ int CStorePage::ItemDisplayOrderSort_UseSortOverride( const econ_store_entry_t *const *ppA, const econ_store_entry_t *const *ppB ) |
|
{ |
|
static CSchemaAttributeDefHandle pAttribDef_StoreSortOverride( "store sort override" ); |
|
|
|
const GameItemDefinition_t *pDefA = ItemSystem()->GetStaticDataForItemByDefIndex( (*ppA)->GetItemDefinitionIndex() ), |
|
*pDefB = ItemSystem()->GetStaticDataForItemByDefIndex( (*ppB)->GetItemDefinitionIndex() ); |
|
|
|
// We expect only items with valid definition indices to make it into the list to |
|
// be sorted. |
|
Assert( pDefA ); |
|
Assert( pDefB ); |
|
|
|
// Sort based on: our sort key if we have one; otherwise our definition index. |
|
float flValue; |
|
int unSortKeyA = ( pAttribDef_StoreSortOverride && FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pDefA, pAttribDef_StoreSortOverride, &flValue ) ) |
|
? (int)flValue |
|
: pDefA->GetDefinitionIndex(), |
|
unSortKeyB = ( pAttribDef_StoreSortOverride && FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pDefB, pAttribDef_StoreSortOverride, &flValue ) ) |
|
? (int)flValue |
|
: pDefB->GetDefinitionIndex(); |
|
|
|
return unSortKeyA - unSortKeyB; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Update our internal list of entries based on our filters, and count items in each filter |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::UpdateFilteredItems( void ) |
|
{ |
|
if ( !m_bFilterDirty ) |
|
return; |
|
|
|
m_FilteredEntries.Purge(); |
|
m_vecFilterCounts.SetCount( GetNumPrimaryFilters() ); |
|
if ( !m_vecFilterCounts.Count() ) |
|
return; |
|
|
|
FOR_EACH_VEC( m_vecFilterCounts, i ) |
|
{ |
|
m_vecFilterCounts[i] = 0; |
|
} |
|
|
|
for ( int i = 0; i < m_pPageData->m_vecEntries.Count(); i++ ) |
|
{ |
|
const econ_store_entry_t *pEntry = EconUI()->GetStorePanel()->GetPriceSheet()->GetEntry( m_pPageData->m_vecEntries[i] ); |
|
GameItemDefinition_t *pDef = ItemSystem()->GetStaticDataForItemByDefIndex( pEntry->GetItemDefinitionIndex() ); |
|
if ( pDef ) |
|
{ |
|
// Get a list of applicable filters for the current item definition |
|
CUtlVector<int> filterList; |
|
GetFiltersForDef( pDef, &filterList ); |
|
|
|
bool bPassesClassFilter = false; |
|
|
|
FOR_EACH_VEC( filterList, iFL ) |
|
{ |
|
int iFilter = filterList[iFL]; |
|
|
|
m_vecFilterCounts[iFilter]++; |
|
|
|
if ( m_iCurrentFilter == iFilter ) |
|
{ |
|
bPassesClassFilter = true; |
|
} |
|
} |
|
|
|
// If the item passes both filters, add it. |
|
// NOTE: DoesEntryFilterPassSecondaryFilter() returns true by default. |
|
if ( bPassesClassFilter && DoesEntryFilterPassSecondaryFilter( pEntry ) ) |
|
{ |
|
m_FilteredEntries.AddToTail( pEntry ); |
|
} |
|
} |
|
} |
|
|
|
// Sort our full list of entries however this store page wants it. |
|
OrderItemsForDisplay( m_FilteredEntries ); |
|
|
|
m_bFilterDirty = false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::UpdateModelPanels( void ) |
|
{ |
|
DeSelectAllItemPanels(); |
|
UpdateSelectionInfoPanel(); |
|
UpdateCart(); |
|
|
|
if ( m_pPageData != NULL ) |
|
{ |
|
UpdateFilteredItems(); |
|
UpdateFilterComboBox(); |
|
|
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
CItemModelPanel *pItemModelPanel = m_vecItemPanels[i].m_pItemModelPanel; |
|
pItemModelPanel->SetShowEquipped( true ); |
|
m_EntryIndices[i] = AssignItemToPanel( pItemModelPanel, i ); |
|
SetBorderForItem( pItemModelPanel, false ); |
|
|
|
int iEntry = m_EntryIndices[i]; |
|
if ( iEntry >= 0 && iEntry < m_FilteredEntries.Count() ) |
|
{ |
|
// Set the price label |
|
m_vecItemPanels[i].m_pStorePricePanel->SetItem( m_FilteredEntries[ iEntry ] ); |
|
m_vecItemPanels[i].m_pItemControlsPanel->SetItem( m_FilteredEntries[ iEntry ] ); |
|
} |
|
} |
|
} |
|
|
|
char szTmp[16]; |
|
Q_snprintf(szTmp, 16, "%d/%d", m_iCurrentPage+1, GetNumPages() ); |
|
SetDialogVariable( "backpackpage", szTmp ); |
|
|
|
UpdateBackpackLabel(); |
|
|
|
// Now layout again to position our item buttons |
|
InvalidateLayout(); |
|
|
|
if ( m_pFilterComboBox ) |
|
{ |
|
m_pFilterComboBox->GetComboButton()->SetFgColor( Color( 117,107,94,255 ) ); |
|
m_pFilterComboBox->GetComboButton()->SetDefaultColor( Color( 117,107,94,255), Color( 0,0,0,0) ); |
|
m_pFilterComboBox->GetComboButton()->SetArmedColor( Color( 117,107,94,255), Color( 0,0,0,0) ); |
|
m_pFilterComboBox->GetComboButton()->SetDepressedColor( Color( 117,107,94,255), Color( 0,0,0,0) ); |
|
} |
|
|
|
// If we're not the home page, start with the first item selected already |
|
if ( m_vecItemPanels.Count() ) |
|
{ |
|
ToggleSelectItemPanel( m_vecItemPanels[m_iSelectDefOnPageShow].m_pItemModelPanel ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnItemPanelMouseReleased( vgui::Panel *panel ) |
|
{ |
|
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); |
|
|
|
if ( pItemPanel && IsVisible() && pItemPanel->HasItem() ) |
|
{ |
|
if ( IsHomePage() ) |
|
{ |
|
// On the homepage, they've clicked the featured item. Find it in a store tab and move to it. |
|
PostMessage( EconUI()->GetStorePanel(), new KeyValues("FindAndSelectFeaturedItem") ); |
|
} |
|
else if ( !pItemPanel->IsSelected() ) |
|
{ |
|
ToggleSelectItemPanel( pItemPanel ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnItemPanelMouseDoublePressed( vgui::Panel *panel ) |
|
{ |
|
if ( IsHomePage() ) |
|
{ |
|
// On the homepage, they've clicked the featured item. Find it in a store tab and move to it. |
|
PostMessage( EconUI()->GetStorePanel(), new KeyValues("FindAndSelectFeaturedItem") ); |
|
return; |
|
} |
|
|
|
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); |
|
|
|
if ( pItemPanel && IsVisible() && pItemPanel->HasItem() ) |
|
{ |
|
// Make sure this panel is selected |
|
if ( !pItemPanel->IsSelected() ) |
|
{ |
|
ToggleSelectItemPanel( pItemPanel ); |
|
} |
|
|
|
// Double clicking on an item in the cart takes you to the view cart page |
|
FOR_EACH_VEC( m_pCartModelPanels, i ) |
|
{ |
|
if ( m_pCartModelPanels[i] == pItemPanel ) |
|
{ |
|
OpenStoreViewCartPanel(); |
|
return; |
|
} |
|
} |
|
|
|
// Not a cart panel, so add to cart. |
|
OnCommand("addtocart"); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::DeSelectAllItemPanels( void ) |
|
{ |
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
if ( m_vecItemPanels[i].m_pItemModelPanel->IsSelected() ) |
|
{ |
|
m_vecItemPanels[i].m_pItemModelPanel->SetSelected( false ); |
|
SetBorderForItem( m_vecItemPanels[i].m_pItemModelPanel, false ); |
|
} |
|
} |
|
FOR_EACH_VEC( m_pCartModelPanels, i ) |
|
{ |
|
if ( m_pCartModelPanels[i]->IsSelected() ) |
|
{ |
|
m_pCartModelPanels[i]->SetSelected( false ); |
|
SetBorderForItem( m_pCartModelPanels[i], false ); |
|
} |
|
} |
|
|
|
m_pSelectedPanel = NULL; |
|
if ( m_pFeaturedItemPanel && m_pFeaturedItemPanel->IsSelected() ) |
|
{ |
|
m_pFeaturedItemPanel->SetSelected( false ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::ToggleSelectItemPanel( CItemModelPanel *pPanel ) |
|
{ |
|
if ( ShouldUseNewStore() ) |
|
return; |
|
|
|
if ( pPanel->IsSelected() || !pPanel->HasItem() ) |
|
{ |
|
pPanel->SetSelected( false ); |
|
m_pSelectedPanel = NULL; |
|
} |
|
else |
|
{ |
|
DeSelectAllItemPanels(); |
|
pPanel->SetSelected( true ); |
|
m_pSelectedPanel = pPanel; |
|
} |
|
SetBorderForItem( pPanel, false ); |
|
UpdateSelectionInfoPanel(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::SelectItemPanel( CItemModelPanel *pPanel ) |
|
{ |
|
DeSelectAllItemPanels(); |
|
pPanel->SetSelected( true ); |
|
m_pSelectedPanel = pPanel; |
|
SetBorderForItem( pPanel, false ); |
|
UpdateSelectionInfoPanel(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnItemPanelEntered( vgui::Panel *panel ) |
|
{ |
|
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); |
|
|
|
if ( pItemPanel && IsVisible() ) |
|
{ |
|
CEconItemView *pItem = pItemPanel->GetItem(); |
|
if ( !pItemPanel->IsSelected() ) |
|
{ |
|
SetBorderForItem( pItemPanel, pItem != NULL ); |
|
} |
|
if ( pItemPanel->HasItem() ) |
|
{ |
|
// make related controls visible |
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
item_panel &itempanel = m_vecItemPanels[i]; |
|
if ( itempanel.m_pItemModelPanel == pItemPanel ) |
|
{ |
|
itempanel.m_pItemControlsPanel->OnItemPanelEntered(); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnItemPanelExited( vgui::Panel *panel ) |
|
{ |
|
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); |
|
|
|
if ( pItemPanel && IsVisible() ) |
|
{ |
|
if ( !pItemPanel->IsSelected() ) |
|
{ |
|
SetBorderForItem( pItemPanel, false ); |
|
} |
|
if ( pItemPanel->HasItem() ) |
|
{ |
|
// make related controls visible |
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
item_panel &itempanel = m_vecItemPanels[i]; |
|
if ( itempanel.m_pItemModelPanel == pItemPanel ) |
|
{ |
|
itempanel.m_pItemControlsPanel->OnItemPanelExited(); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnItemAddToCart( vgui::Panel *panel ) |
|
{ |
|
CStoreItemControlsPanel *pControlsPanel = dynamic_cast< CStoreItemControlsPanel * >( panel ); |
|
if ( pControlsPanel ) |
|
{ |
|
const econ_store_entry_t *pEntry = pControlsPanel->GetItem(); |
|
if ( pEntry ) |
|
{ |
|
if ( !ShouldUseNewStore() ) |
|
{ |
|
SelectItemPanel( pControlsPanel->GetItemModelPanel() ); |
|
} |
|
else |
|
{ |
|
#if defined( TF_CLIENT_DLL ) |
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_add_to_cart", "minibutton" ); |
|
#endif |
|
} |
|
AddItemToCartHelper( GetPageName(), pEntry, kCartItem_Purchase ); |
|
UpdateCart(); |
|
} |
|
|
|
// Turn the free slots indicator red if we can't fit everything. |
|
UpdateBackpackLabel(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::SetBorderForItem( CItemModelPanel *pItemPanel, bool bMouseOver ) |
|
{ |
|
if ( !pItemPanel || pItemPanel == m_pFeaturedItemPanel ) |
|
return; |
|
|
|
// Store panels use backgrounds instead of borders |
|
pItemPanel->SetBorder( NULL ); |
|
pItemPanel->SetPaintBackgroundEnabled( true ); |
|
|
|
if ( pItemPanel->IsSelected() ) |
|
{ |
|
pItemPanel->SetBgColor( m_colItemPanelBGSelected ); |
|
} |
|
else if ( bMouseOver ) |
|
{ |
|
pItemPanel->SetBgColor( m_colItemPanelBGMouseover ); |
|
} |
|
else |
|
{ |
|
pItemPanel->SetBgColor( m_colItemPanelBG ); |
|
} |
|
|
|
const CEconStorePriceSheet *pPriceSheet = EconUI()->GetStorePanel()->GetPriceSheet(); |
|
|
|
if ( pItemPanel->GetItem() && pPriceSheet ) |
|
{ |
|
const econ_store_entry_t *pEntry = pPriceSheet->GetEntry( pItemPanel->GetItem()->GetItemDefIndex() ); |
|
|
|
if (pEntry && pEntry->m_bHighlighted && !bMouseOver ) |
|
{ |
|
pItemPanel->SetBorder( vgui::scheme()->GetIScheme( GetScheme() )->GetBorder( "StoreHighlightedBackgroundBorder" ) ); |
|
pItemPanel->SetPaintBorderEnabled( true ); |
|
pItemPanel->SetPaintBackgroundEnabled( false ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::CalculateItemButtonPos( CItemModelPanel *pItemPanel, int x, int y, int *iXPos, int *iYPos ) |
|
{ |
|
*iXPos = x; |
|
*iYPos = (y + pItemPanel->GetTall() + YRES(4)); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::UpdateSelectionInfoPanel( void ) |
|
{ |
|
// Home page doesn't support item selections |
|
if ( IsHomePage() ) |
|
return; |
|
|
|
if ( m_pPreviewItemButton ) |
|
{ |
|
m_pPreviewItemButton->SetVisible( false ); |
|
} |
|
|
|
if ( m_pSelectedPanel ) |
|
{ |
|
const econ_store_entry_t *pEntry = GetSelectedEntry(); |
|
CEconItemView *pItem = m_pSelectedPanel->GetItem(); |
|
if ( pItem && pEntry ) |
|
{ |
|
if ( m_pPreviewItemButton ) |
|
{ |
|
m_pPreviewItemButton->SetVisible( pEntry->CanPreview() ); |
|
} |
|
|
|
m_iOldSelectedItemDef = m_iSelectedItemDef; |
|
m_iSelectedItemDef = pItem->GetItemDefIndex(); |
|
|
|
if ( m_iSelectedItemDef != m_iOldSelectedItemDef ) |
|
{ |
|
EconUI()->Gamestats_Store( IE_STORE_ITEM_SELECTED, pItem, GetPageName() ); |
|
} |
|
|
|
CEconItemDefinition *pItemData = pItem->GetStaticData(); |
|
if ( pItemData ) |
|
{ |
|
ShowPreview( 0, pEntry ); |
|
InvalidateLayout(); |
|
|
|
wchar_t wzLocalizedPrice[ kLocalizedPriceSizeInChararacters ]; |
|
int iPrice = pEntry->GetCurrentPrice( EconUI()->GetStorePanel()->GetCurrency() ); |
|
MakeMoneyString( wzLocalizedPrice, ARRAYSIZE( wzLocalizedPrice ), iPrice, EconUI()->GetStorePanel()->GetCurrency() ); |
|
SetDialogVariable("selectionprice", wzLocalizedPrice ); |
|
|
|
if ( m_pAddToCartButtonPanel ) |
|
{ |
|
m_pAddToCartButtonPanel->SetVisible( true ); |
|
} |
|
|
|
return; |
|
} |
|
} |
|
} |
|
|
|
SetDialogVariable("selectionprice", "" ); |
|
|
|
if ( m_pAddToCartButtonPanel ) |
|
{ |
|
m_pAddToCartButtonPanel->SetVisible( false ); |
|
} |
|
m_iSelectedItemDef = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Called when text changes in combo box |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnTextChanged( KeyValues *data ) |
|
{ |
|
Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") ); |
|
vgui::ComboBox *pComboBox = dynamic_cast<vgui::ComboBox *>( pPanel ); |
|
|
|
m_bFilterDirty = true; |
|
|
|
if ( pComboBox == m_pFilterComboBox ) |
|
{ |
|
// the class selection combo box changed, update class details |
|
KeyValues *pUserData = m_pFilterComboBox->GetActiveItemUserData(); |
|
if ( !pUserData ) |
|
return; |
|
|
|
int iFilter = pUserData->GetInt( "filter", 0 ); |
|
|
|
// If there are no items for that class, refuse to switch |
|
if ( iFilter && m_vecFilterCounts[iFilter] <= 0 ) |
|
{ |
|
m_pFilterComboBox->ActivateItemByRow( m_iCurrentFilter ? m_iCurrentFilter+1 : 0 ); |
|
return; |
|
} |
|
|
|
SetFilter( iFilter ); |
|
m_iCurrentPage = 0; |
|
UpdateModelPanels(); |
|
|
|
m_pCheckoutButton->RequestFocus(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::SetFilter( int iFilter ) |
|
{ |
|
if ( iFilter != m_iCurrentFilter ) |
|
m_bFilterDirty = true; |
|
|
|
m_iCurrentFilter = iFilter; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::ShowPreview( int iClass, const econ_store_entry_t* pEntry ) |
|
{ |
|
if ( !m_pPreviewPanel ) |
|
return; |
|
|
|
CEconItemView itemData; |
|
itemData.Init( m_iSelectedItemDef, AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); |
|
itemData.SetClientItemFlags( kEconItemFlagClient_Preview ); |
|
|
|
m_pPreviewPanel->PreviewItem( iClass, &itemData, pEntry ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::SetDetailsVisible( bool bVisible ) |
|
{ |
|
if ( m_pPreviewPanel ) |
|
{ |
|
m_pPreviewPanel->SetState( bVisible ? PS_DETAILS : PS_ITEM ); |
|
} |
|
|
|
if ( m_pItemPreviewButtonPanel && m_pItemDetailsButtonPanel ) |
|
{ |
|
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); |
|
if ( bVisible ) |
|
{ |
|
m_pItemPreviewButtonPanel->SetBorder( pScheme->GetBorder("StorePreviewTabUnselected") ); |
|
m_pItemDetailsButtonPanel->SetBorder( pScheme->GetBorder("StorePreviewTabSelected") ); |
|
} |
|
else |
|
{ |
|
m_pItemPreviewButtonPanel->SetBorder( pScheme->GetBorder("StorePreviewTabSelected") ); |
|
m_pItemDetailsButtonPanel->SetBorder( pScheme->GetBorder("StorePreviewTabUnselected") ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CStorePage::FindAndSelectEntry( const econ_store_entry_t *pEntry ) |
|
{ |
|
// We can't search if we haven't created our item panels & filtered. |
|
CreateItemPanels(); |
|
SetFilter( FILTER_ALL_ITEMS ); |
|
UpdateFilteredItems(); |
|
|
|
FOR_EACH_VEC( m_FilteredEntries, i ) |
|
{ |
|
if ( m_FilteredEntries[i]->GetItemDefinitionIndex() == pEntry->GetItemDefinitionIndex() ) |
|
{ |
|
// Figure out what page it'll be on |
|
int iPage = floor( (float)i / (float)GetNumItemPanels() ); |
|
|
|
// Switch to that page |
|
m_iCurrentPage = iPage; |
|
UpdateModelPanels(); |
|
m_iSelectPageOnPageShow = iPage; |
|
|
|
// Then select the item model panel for this item |
|
FOR_EACH_VEC( m_vecItemPanels, p ) |
|
{ |
|
CEconItemView *pItem = m_vecItemPanels[p].m_pItemModelPanel->GetItem(); |
|
if ( pItem && pItem->GetItemDefIndex() == pEntry->GetItemDefinitionIndex() ) |
|
{ |
|
// We can't select here, because the pageshow will stomp it. |
|
// Remember that this is the panel we'd like to have selected. |
|
m_iSelectDefOnPageShow = p; |
|
break; |
|
} |
|
} |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const econ_store_entry_t *CStorePage::GetSelectedEntry( void ) |
|
{ |
|
// Get the entry for the panel. |
|
int iEntry = -1; |
|
|
|
if ( m_pFeaturedItemPanel == m_pSelectedPanel ) |
|
return EconUI()->GetStorePanel()->GetFeaturedEntry(); |
|
|
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
if ( m_vecItemPanels[i].m_pItemModelPanel == m_pSelectedPanel ) |
|
{ |
|
iEntry = m_EntryIndices[i]; |
|
if ( iEntry >= 0 && iEntry < m_FilteredEntries.Count() ) |
|
return m_FilteredEntries[iEntry]; |
|
} |
|
} |
|
|
|
// It's probably something already in our cart. |
|
FOR_EACH_VEC( m_pCartModelPanels, i ) |
|
{ |
|
if ( m_pCartModelPanels[i] == m_pSelectedPanel ) |
|
{ |
|
CStoreCart *pCart = EconUI()->GetStorePanel()->GetCart(); |
|
if ( i < pCart->GetNumEntries() ) |
|
{ |
|
cart_item_t *pCartItem = pCart->GetItem(i); |
|
return pCartItem->pEntry; |
|
} |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::AddSelectionToCart( void ) |
|
{ |
|
if ( !m_pSelectedPanel ) |
|
return; |
|
|
|
// Get the entry for the panel. |
|
const econ_store_entry_t *pEntry = GetSelectedEntry(); |
|
if ( pEntry ) |
|
{ |
|
AddItemToCartHelper( GetPageName(), pEntry, kCartItem_Purchase ); |
|
UpdateCart(); |
|
} |
|
|
|
// Turn the free slots indicator red if we can't fit everything. |
|
UpdateBackpackLabel(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::UpdateCart( void ) |
|
{ |
|
if ( !IsVisible() || ( !ShouldUseNewStore() && IsHomePage() ) ) |
|
return; |
|
|
|
CStoreCart *pCart = EconUI()->GetStorePanel()->GetCart(); |
|
int iNumEntriesInCart = pCart->GetNumEntries(); |
|
|
|
// Now update the item icons next to the cart. |
|
if ( m_pCartModelPanels.Count() < iNumEntriesInCart ) |
|
{ |
|
// Support a max of 10 items in the cart quickview right now |
|
for ( int i = m_pCartModelPanels.Count(); (i < iNumEntriesInCart) && (i < m_iMaxCartModelPanels); i++ ) |
|
{ |
|
CItemModelPanel *pPanel = vgui::SETUP_PANEL( new CItemModelPanel( this, VarArgs("cartmodelpanel%d", i) ) ); |
|
pPanel->SetActAsButton( true, true ); |
|
pPanel->ApplySettings( m_pCartModelPanelKVs ); |
|
SetBorderForItem( pPanel, false ); |
|
m_pCartModelPanels.AddToTail( pPanel ); |
|
|
|
pPanel->SetTooltip( m_pMouseOverTooltip, "" ); |
|
|
|
CExLabel *pLabel = vgui::SETUP_PANEL( new CExLabel( this, VarArgs("cartquantitylabel%d", i), "X" ) ); |
|
pLabel->ApplySettings( m_pCartQuantityLabelKVs ); |
|
pLabel->SetMouseInputEnabled( false ); |
|
pLabel->SetKeyBoardInputEnabled( false ); |
|
m_pCartQuantityLabels.AddToTail( pLabel ); |
|
} |
|
} |
|
|
|
UpdateBackpackLabel(); |
|
|
|
InvalidateLayout(); |
|
|
|
CEconItemView *pItemData = new CEconItemView(); |
|
|
|
// Assign the items in the cart to the panels |
|
FOR_EACH_VEC( m_pCartModelPanels, i ) |
|
{ |
|
if ( i >= iNumEntriesInCart ) |
|
{ |
|
m_pCartModelPanels[i]->SetItem( NULL ); |
|
m_pCartModelPanels[i]->SetVisible( false ); |
|
m_pCartQuantityLabels[i]->SetVisible( false ); |
|
continue; |
|
} |
|
|
|
cart_item_t *pCartItem = pCart->GetItem(i); |
|
pItemData->Init( pCartItem->pEntry->GetItemDefinitionIndex(), AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); |
|
pItemData->SetClientItemFlags( kEconItemFlagClient_Preview | kEconItemFlagClient_StoreItem ); |
|
m_pCartModelPanels[i]->SetItem( pItemData ); |
|
m_pCartModelPanels[i]->SetVisible( true ); |
|
|
|
m_pCartQuantityLabels[i]->SetVisible( true ); |
|
m_pCartQuantityLabels[i]->SetText( VarArgs("%d",pCartItem->iQuantity) ); |
|
} |
|
|
|
delete pItemData; |
|
|
|
// Update the item count |
|
wchar_t wszCount[16]; |
|
wchar_t wzLocalized[512]; |
|
_snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", pCart->GetTotalItems() ); |
|
g_pVGuiLocalize->ConstructString_safe( wzLocalized, g_pVGuiLocalize->Find( "#Store_Cart" ), 1, wszCount ); |
|
SetDialogVariable("storecart", wzLocalized ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
ConVar econ_never_show_items_in_cart_count( "econ_never_show_items_in_cart_count", "1", FCVAR_DEVELOPMENTONLY ); |
|
|
|
void CStorePage::UpdateBackpackLabel( void ) |
|
{ |
|
wchar_t wszBackpackSlotCount[16]; |
|
wchar_t wszLocalized[512]; |
|
|
|
// How many slots do we have free in our current backpack? This won't take into |
|
// consideration expanders, account upgrades, etc. |
|
const int iMaxItemCount = InventoryManager()->GetLocalInventory()->GetMaxItemCount(), |
|
iCurItemCount = InventoryManager()->GetLocalInventory()->GetItemCount(); |
|
AssertMsg( iMaxItemCount - iCurItemCount >= 0, "You have a negative number of backpack slots available - fix me!" ); |
|
const int iBaseFreeSlots = MAX( 0, iMaxItemCount - iCurItemCount ); |
|
_snwprintf( wszBackpackSlotCount, ARRAYSIZE( wszBackpackSlotCount ), L"%d", iBaseFreeSlots ); |
|
|
|
// Breaking out bundles into individual items, etc., how many backpack slots will the |
|
// items in our cart take up? |
|
const int iItemsInCart = EconUI()->GetStorePanel()->GetCart()->GetTotalConcreteItems(); |
|
|
|
if ( iItemsInCart == 0 || econ_never_show_items_in_cart_count.GetBool() ) |
|
{ |
|
g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#Store_FreeBackpackSpace" ), 1, wszBackpackSlotCount ); |
|
} |
|
else |
|
{ |
|
wchar_t wszCartCount[16]; |
|
_snwprintf( wszCartCount, ARRAYSIZE( wszCartCount ), L"%d", iItemsInCart ); |
|
|
|
#if defined( TF_CLIENT_DLL ) |
|
if ( IsFreeTrialAccount() ) |
|
{ |
|
wchar_t wszUpgradeSlotCount[16]; |
|
_snwprintf( wszUpgradeSlotCount, ARRAYSIZE( wszUpgradeSlotCount ), L"%d", DEFAULT_NUM_BACKPACK_SLOTS - DEFAULT_NUM_BACKPACK_SLOTS_FREE_TRIAL_ACCOUNT ); |
|
|
|
// We're a free trial account so we show the number of backpack slots we really have, |
|
// the number of slots we get as a bonus when purchasing, and then the number of items |
|
// in our cart. |
|
g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#Store_FreeBackpackSpace_WithCartItems_WithUpgrade" ), 3, wszBackpackSlotCount, wszCartCount, wszUpgradeSlotCount ); |
|
} |
|
else |
|
#endif // defined( TF_CLIENT_DLL ) |
|
{ |
|
// We aren't a free trial account, so there is no account upgrade included in |
|
// this purchase, so fall back to showing the number of items in our cart. |
|
g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#Store_FreeBackpackSpace_WithCartItems" ), 2, wszBackpackSlotCount, wszCartCount ); |
|
} |
|
} |
|
|
|
SetDialogVariable( "freebackpackspace", wszLocalized ); |
|
|
|
if ( m_pBackpackLabel ) |
|
{ |
|
const Color clrTooMany = ShouldUseNewStore() ? Color(200,80,60,255) : Color(255,0,0,255); |
|
m_pBackpackLabel->SetFgColor( InventoryManager()->GetLocalInventory()->CanPurchaseItems( iItemsInCart ) ? m_colBackpackOrg : clrTooMany ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::UpdateFilterComboBox( void ) |
|
{ |
|
if ( !m_pFilterComboBox ) |
|
return; |
|
|
|
m_pFilterComboBox->RemoveAll(); |
|
|
|
// All items |
|
KeyValues *pKeyValues = new KeyValues( "data" ); |
|
pKeyValues->SetInt( "filter", FILTER_ALL_ITEMS ); |
|
m_pFilterComboBox->AddItem( "#Store_ClassFilter_None", pKeyValues ); |
|
|
|
pKeyValues->deleteThis(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::PreviewSelectionItem( void ) |
|
{ |
|
if ( !m_pSelectedPanel ) |
|
return; |
|
|
|
// Get the entry for the panel. |
|
const econ_store_entry_t *pEntry = GetSelectedEntry(); |
|
if ( !pEntry ) |
|
return; |
|
|
|
if ( !pEntry->CanPreview() ) |
|
return; |
|
|
|
DoPreviewItem( pEntry->GetItemDefinitionIndex() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::DoPreviewItem( item_definition_index_t usItemDef ) |
|
{ |
|
#ifdef TF_CLIENT_DLL |
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "do_try_out_item", CFmtStr( "%i", usItemDef ).Access() ); |
|
#endif |
|
|
|
if ( usItemDef == InventoryManager()->GetLocalInventory()->GetPreviewItemDef() ) |
|
{ |
|
ShowMessageBox( "#ItemPreview_AlreadyPreviewTitle", "#ItemPreview_AlreadyPreviewText", "#GameUI_OK" ); |
|
return; |
|
} |
|
|
|
// Send a message to the GC asking if this player can preview an item. |
|
GCSDK::CGCMsg< MsgGCCheckItemPreviewStatus_t > msg( k_EMsgGCItemPreviewCheckStatus ); |
|
msg.Body().m_unItemDefIndex = usItemDef; |
|
|
|
// OGS LOGGING HERE |
|
|
|
GCClientSystem()->BSendMessage( msg ); |
|
|
|
// Response is handled in item_rental_ui.cpp. |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CStorePage::OnPreviewItem( KeyValues *pData ) |
|
{ |
|
DoPreviewItem( pData->GetInt( "item_def_index" ) ); |
|
}
|
|
|