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.
849 lines
28 KiB
849 lines
28 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
|
|
#include "cbase.h" |
|
#include "store/v2/tf_store_page2.h" |
|
#include "store/v2/tf_store_preview_item2.h" |
|
#include "c_tf_freeaccount.h" |
|
#include "store/store_panel.h" |
|
#include "store/tf_store.h" |
|
#include "navigationpanel.h" |
|
#include "econ/store/store_page_new.h" |
|
#include "econ_item_system.h" |
|
#include "c_tf_gamestats.h" |
|
#include "vgui_controls/TextImage.h" |
|
#include "econ_item_description.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
static const int kNumSortTypes = 5; |
|
ItemSortTypeData_t g_StoreSortTypes[ kNumSortTypes ] = |
|
{ |
|
{ "#Store_SortType_DateNewest", kEconStoreSortType_DateNewest }, |
|
{ "#Store_SortType_DateOldest", kEconStoreSortType_DateOldest }, |
|
{ "#Store_SortType_HighestPrice", kEconStoreSortType_Price_HighestToLowest }, |
|
{ "#Store_SortType_LowestPrice", kEconStoreSortType_Price_LowestToHighest }, |
|
{ "#Store_SortType_Alphabetical", kEconStoreSortType_Name_AToZ }, |
|
}; |
|
|
|
class CClassFilterTooltip : public vgui::BaseTooltip |
|
{ |
|
public: |
|
CClassFilterTooltip( CTFStorePage2 *pStorePage ) |
|
: BaseTooltip( pStorePage ) |
|
, m_pStorePage( pStorePage ) |
|
{ |
|
} |
|
|
|
CTFStorePage2 *m_pStorePage; |
|
|
|
virtual void SetText(const char *text) |
|
{ |
|
m_pStorePage->m_pClassFilterTooltipLabel->SetText( text ); |
|
} |
|
|
|
virtual void ShowTooltip(Panel *currentPanel) |
|
{ |
|
int x = 0; |
|
int y = currentPanel->GetTall(); |
|
currentPanel->LocalToScreen( x, y ); |
|
m_pStorePage->ScreenToLocal( x, y ); |
|
|
|
// The tooltip wants to be centered around the given panel, but it's constrained by the left and right boundaries |
|
// of the navigation panel. |
|
if ( m_pStorePage->m_pClassFilterButtons ) |
|
{ |
|
// Right side of tooltip should not pass right boundary of nav panel |
|
int aClassFilterNavPos[2] = { 0, 0 }; |
|
m_pStorePage->m_pClassFilterButtons->GetPos( aClassFilterNavPos[0], aClassFilterNavPos[1] ); |
|
const int nTipWide = m_pStorePage->m_pClassFilterTooltipLabel->GetWide(); |
|
x = clamp( |
|
x + ( currentPanel->GetWide() - nTipWide ) / 2, |
|
aClassFilterNavPos[0], |
|
aClassFilterNavPos[0] + m_pStorePage->m_pClassFilterButtons->GetWide() - nTipWide ); |
|
} |
|
|
|
m_pStorePage->m_pClassFilterTooltipLabel->SetPos( x, y ); |
|
m_pStorePage->m_pClassFilterTooltipLabel->SetVisible( true ); |
|
} |
|
virtual void HideTooltip() |
|
{ |
|
m_pStorePage->m_pClassFilterTooltipLabel->SetVisible( false ); |
|
} |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFStorePage2::CTFStorePage2(Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData, const char *pPreviewItemResFile ) |
|
: BaseClass( parent, pPageData, pPreviewItemResFile ), |
|
m_pSubcategoriesFilterCombo( NULL ), |
|
m_pSortByCombo( NULL ), |
|
m_pHomeCategoryTabs( NULL ), |
|
m_pClassFilterButtons( NULL ), |
|
m_pNameFilterTextEntry( NULL ), |
|
m_pSubcategoriesFilterLabel( NULL ), |
|
m_iCurrentSubcategory( 2 ), // Switch to Featured items tab on home page when store launches; BRETT SAID I COULD DO THIS |
|
m_pClassFilterTooltipLabel( NULL ), |
|
m_pClassFilterTooltip( NULL ), |
|
m_flFilterItemTime( 0.0f ) |
|
{ |
|
const CEconStorePriceSheet *pPriceSheet = EconUI()->GetStorePanel()->GetPriceSheet(); |
|
|
|
if ( IsHomePage() ) |
|
{ |
|
bool bAtLeastOneItemIsOnSale = false; |
|
if ( pPriceSheet ) |
|
{ |
|
const CEconStorePriceSheet::StoreEntryMap_t& mapStoreEntries = pPriceSheet->GetEntries(); |
|
FOR_EACH_MAP_FAST( mapStoreEntries, i ) |
|
{ |
|
if ( mapStoreEntries[i].IsOnSale( EconUI()->GetStorePanel()->GetCurrency() ) ) |
|
{ |
|
bAtLeastOneItemIsOnSale = true; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
m_pHomeCategoryTabs = new CNavigationPanel( this, "ItemCategoryTabs" ); |
|
|
|
FOR_EACH_VEC( m_pPageData->m_vecSubcategories, i ) |
|
{ |
|
// Skip over adding the "On Sale!" tab if no items are currently on sale. |
|
const char *pchName = m_pPageData->m_vecSubcategories[i]->m_pchName; |
|
bool bIsOnSaleCategory = m_pPageData->m_vecSubcategories[i]->m_unID == CEconStoreCategoryManager::k_CategoryID_OnSale; |
|
|
|
// Skip over the "Top Sellers" tab as we're replacing it with the 'Starter Packs' tab for now |
|
bool bIsPopularCategory = m_pPageData->m_vecSubcategories[i]->m_unID == CEconStoreCategoryManager::k_CategoryID_Popular; |
|
|
|
// Skip over the "New" tab as we're replacing it with the 'Featured' tab for now |
|
bool bIsNew = m_pPageData->m_vecSubcategories[i]->m_unID == CEconStoreCategoryManager::k_CategoryID_New; |
|
|
|
// We include all of the sale items in the Featured tab currently, so we don't need to add these categories back in at the moment |
|
bAtLeastOneItemIsOnSale = false; |
|
|
|
if ( ( !bIsPopularCategory && !bIsOnSaleCategory && !bIsNew ) || ( bAtLeastOneItemIsOnSale && bIsOnSaleCategory ) ) |
|
{ |
|
m_pHomeCategoryTabs->AddButton( i, pchName ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
CTFStorePage2::~CTFStorePage2() |
|
{ |
|
delete m_pClassFilterTooltip; |
|
m_pClassFilterTooltip = NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnPostCreate() |
|
{ |
|
BaseClass::OnPostCreate(); |
|
|
|
m_bShouldDeletePreviewPanel = true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFStorePage2::HasSubcategories() const |
|
{ |
|
return m_pPageData && m_pPageData->HasSubcategories(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
if ( m_pSubcategoriesFilterCombo ) |
|
{ |
|
m_pSubcategoriesFilterCombo->SetVisible( HasSubcategories() ); |
|
} |
|
|
|
if ( m_pSubcategoriesFilterLabel ) |
|
{ |
|
m_pSubcategoriesFilterLabel->SetVisible( HasSubcategories() ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
m_pNameFilterTextEntry = FindControl<vgui::TextEntry>( "NameFilterTextEntry" ); |
|
if ( m_pNameFilterTextEntry ) |
|
{ |
|
m_pNameFilterTextEntry->AddActionSignalTarget( this ); |
|
} |
|
|
|
m_pSortByCombo = dynamic_cast< ComboBox * >( FindChildByName( "SortFilterComboBox" ) ); |
|
if ( m_pSortByCombo ) |
|
{ |
|
m_pSortByCombo->RemoveAll(); |
|
vgui::HFont hFont = pScheme->GetFont( "HudFontSmallestBold", true ); |
|
m_pSortByCombo->SetFont( hFont ); |
|
KeyValues *pKeyValues = new KeyValues( "data" ); |
|
for ( int i = 0; i < ARRAYSIZE(g_StoreSortTypes); i++ ) |
|
{ |
|
pKeyValues->SetInt( "sortby", i ); |
|
m_pSortByCombo->AddItem( g_StoreSortTypes[i].szSortDesc, pKeyValues ); |
|
} |
|
pKeyValues->deleteThis(); |
|
m_pSortByCombo->ActivateItemByRow( 0 ); |
|
} |
|
|
|
m_pSubcategoriesFilterCombo = dynamic_cast< ComboBox * >( FindChildByName( "SubcategoryFilterComboBox" ) ); |
|
if ( m_pSubcategoriesFilterCombo ) |
|
{ |
|
vgui::HFont hFont = pScheme->GetFont( "HudFontSmallestBold", true ); |
|
m_pSubcategoriesFilterCombo->SetFont( hFont ); |
|
|
|
m_pSubcategoriesFilterCombo->RemoveAll(); |
|
|
|
if ( m_pPageData ) |
|
{ |
|
// Add "all items" explicitly |
|
KeyValuesAD kvAllItems( "data" ); |
|
kvAllItems->SetInt( "index", GetNumSubcategories() ); |
|
m_pSubcategoriesFilterCombo->AddItem( "#Store_ClassFilter_None", kvAllItems ); |
|
|
|
FOR_EACH_VEC( m_pPageData->m_vecSubcategories, i ) |
|
{ |
|
KeyValues *pData = new KeyValues( "data" ); |
|
pData->SetInt( "index", i ); |
|
|
|
m_pSubcategoriesFilterCombo->AddItem( m_pPageData->m_vecSubcategories[i]->m_pchName, pData ); |
|
|
|
pData->deleteThis(); |
|
} |
|
} |
|
|
|
// Move to "All items" selected |
|
m_pSubcategoriesFilterCombo->ActivateItemByRow( 0 ); |
|
|
|
m_pSubcategoriesFilterCombo->GetComboButton()->SetFgColor( Color( 117,107,94,255 ) ); |
|
m_pSubcategoriesFilterCombo->GetComboButton()->SetDefaultColor( Color( 117,107,94,255), Color( 0,0,0,0) ); |
|
m_pSubcategoriesFilterCombo->GetComboButton()->SetArmedColor( Color( 117,107,94,255), Color( 0,0,0,0) ); |
|
m_pSubcategoriesFilterCombo->GetComboButton()->SetDepressedColor( Color( 117,107,94,255), Color( 0,0,0,0) ); |
|
} |
|
|
|
m_pClassFilterButtons = dynamic_cast< CNavigationPanel * >( FindChildByName( "ClassFilterNavPanel" ) ); |
|
m_pSubcategoriesFilterLabel = dynamic_cast< CExLabel * >( FindChildByName( "SubcategoryFiltersLabel" ) ); |
|
|
|
m_pClassFilterTooltipLabel = dynamic_cast< CExLabel * >( FindChildByName( "ClassFilterTooltipLabel" ) ); |
|
if ( m_pClassFilterTooltipLabel && m_pClassFilterButtons ) |
|
{ |
|
m_pClassFilterTooltip = new CClassFilterTooltip(this); |
|
for ( int i = 0 ; i < m_pClassFilterButtons->NumButtons() ; ++i ) |
|
{ |
|
CExButton *pButton = m_pClassFilterButtons->GetButton( i ); |
|
CUtlString sSaveText = pButton->GetEffectiveTooltipText(); |
|
pButton->SetTooltip( m_pClassFilterTooltip, sSaveText ); |
|
} |
|
} |
|
|
|
// Setup title text in home page |
|
if ( IsHomePage() && g_pVGuiLocalize ) |
|
{ |
|
CExLabel *pTitleLabel = dynamic_cast<CExLabel *>( FindChildByName( "TitleLabel" ) ); |
|
wchar_t *pHomePageTitle = g_pVGuiLocalize->Find( "#Store_HomePageTitle" ); |
|
wchar_t *pRedText = g_pVGuiLocalize->Find( "#Store_HomePageTitleRedText" ); |
|
|
|
if ( pTitleLabel && pHomePageTitle && pRedText ) |
|
{ |
|
const store_promotion_spend_for_free_item_t *pPromotion = EconUI()->GetStorePanel()->GetPriceSheet()->GetStorePromotion_SpendForFreeItem(); |
|
|
|
ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); |
|
AssertMsg( eCurrency >= k_ECurrencyUSD && eCurrency < k_ECurrencyMax, "Invalid currency!" ); |
|
int iPriceThreshold = pPromotion->m_rgusPriceThreshold[ eCurrency ]; |
|
wchar_t wszPriceThreshold[ kLocalizedPriceSizeInChararacters ]; |
|
MakeMoneyString( wszPriceThreshold, ARRAYSIZE( wszPriceThreshold ), iPriceThreshold, EconUI()->GetStorePanel()->GetCurrency() ); |
|
|
|
static wchar_t wszText[512]; |
|
g_pVGuiLocalize->ConstructString_safe( wszText, pHomePageTitle, 2, pRedText, wszPriceThreshold ); |
|
|
|
pTitleLabel->SetText( wszText ); |
|
TextImage *pTextImage = pTitleLabel->GetTextImage(); |
|
const wchar_t *pFound = wcsstr( wszText, pRedText ); |
|
if ( pTextImage && pFound ) |
|
{ |
|
const int iRedTextPos = pFound - wszText; |
|
const int nRedTextLen = wcslen( pRedText ); |
|
pTextImage->ClearColorChangeStream(); |
|
pTextImage->AddColorChange( Color(200,80,60,255), iRedTextPos ); |
|
pTextImage->AddColorChange( pTitleLabel->GetFgColor(), iRedTextPos + nRedTextLen ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char *CTFStorePage2::GetPageResFile( void ) |
|
{ |
|
if ( IsHomePage() ) |
|
{ |
|
Assert( ShouldUseNewStore() ); |
|
|
|
return "Resource/UI/econ/store/v2/StoreHome_Premium.res"; |
|
} |
|
|
|
return m_pPageData->m_pchPageRes; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnPageShow( void ) |
|
{ |
|
BaseClass::OnPageShow(); |
|
|
|
if ( m_pClassFilterButtons ) |
|
{ |
|
m_pClassFilterButtons->UpdateButtonSelectionStates( 0 ); |
|
} |
|
|
|
ClearNameFilter( true ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnCommand( const char *command ) |
|
{ |
|
BaseClass::OnCommand( command ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnItemDetails( vgui::Panel *panel ) |
|
{ |
|
CStoreItemControlsPanel *pControlsPanel = dynamic_cast< CStoreItemControlsPanel * >( panel ); |
|
if ( pControlsPanel ) |
|
{ |
|
const econ_store_entry_t *pEntry = pControlsPanel->GetItem(); |
|
if ( pEntry && m_pPreviewPanel ) |
|
{ |
|
ShowPreviewWindow( pEntry->GetItemDefinitionIndex() ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnItemDefDetails( KeyValues *pData ) |
|
{ |
|
ShowPreviewWindow( pData->GetInt("ItemDefIndex", -1) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::ShowPreviewWindow( item_definition_index_t usDefIndex ) |
|
{ |
|
if ( m_pPreviewPanel ) |
|
{ |
|
CEconItemView itemData; |
|
itemData.Init( usDefIndex, AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); |
|
itemData.SetClientItemFlags( kEconItemFlagClient_Preview ); |
|
|
|
m_pPreviewPanel->PreviewItem( 0, &itemData ); |
|
m_pPreviewPanel->SetState( PS_ITEM ); // Adding this, since without it, only the item icon shows up |
|
m_pPreviewPanel->SetVisible( true ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnNavButtonSelected( KeyValues *pData ) |
|
{ |
|
Panel *pPanel = (Panel *)pData->GetPtr( "panel" ); |
|
|
|
if ( pPanel == m_pClassFilterButtons ) |
|
{ |
|
const int iFilter = pData->GetInt( "userdata", -1 ); AssertMsg( iFilter >= 0, "Bad filter" ); |
|
if ( iFilter < 0 ) |
|
return; |
|
|
|
SetFilter( iFilter ); |
|
m_iCurrentPage = 0; |
|
UpdateModelPanels(); |
|
|
|
if ( m_pCheckoutButton ) |
|
{ |
|
m_pCheckoutButton->RequestFocus(); |
|
} |
|
|
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_page_2_nav(class)", CFmtStr( "%i", iFilter ).Access() ); |
|
} |
|
else if ( pPanel == m_pHomeCategoryTabs ) |
|
{ |
|
int iSelectedTab = pData->GetInt( "userdata", -1 ); |
|
if ( iSelectedTab < 0 ) |
|
return; |
|
|
|
if ( !m_pPageData || !m_pPageData->m_vecSubcategories.IsValidIndex( iSelectedTab ) ) |
|
return; |
|
|
|
m_iCurrentSubcategory = iSelectedTab; |
|
|
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
// Delete the old one |
|
m_vecItemPanels[i].m_pStorePricePanel->MarkForDeletion(); |
|
|
|
// Create a new one and cache it |
|
CStorePricePanel *pPricePanel = CreatePricePanel( i ); |
|
pPricePanel->InvalidateLayout(); |
|
pPricePanel->SetMouseInputEnabled( false ); |
|
pPricePanel->SetKeyBoardInputEnabled( false ); |
|
|
|
m_vecItemPanels[i].m_pStorePricePanel = pPricePanel; |
|
|
|
// Setup the mouse handler |
|
m_vecItemPanels[i].m_pItemControlsPanel->SetMouseHoverHandler( pPricePanel ); |
|
} |
|
|
|
m_iCurrentPage = 0; |
|
|
|
UpdateFilteredItems(); |
|
UpdateModelPanels(); |
|
|
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_page_2_nav(category)", CFmtStr( "%i", iSelectedTab ).Access() ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Called when text changes in combo box |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnTextChanged( KeyValues *data ) |
|
{ |
|
Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") ); |
|
|
|
vgui::TextEntry *pTextEntry = dynamic_cast<vgui::TextEntry *>( pPanel ); |
|
|
|
if ( pTextEntry ) |
|
{ |
|
if ( pTextEntry == m_pNameFilterTextEntry ) |
|
{ |
|
m_wNameFilter.RemoveAll(); |
|
if ( m_pNameFilterTextEntry->GetTextLength() ) |
|
{ |
|
m_wNameFilter.EnsureCount( m_pNameFilterTextEntry->GetTextLength() + 1 ); |
|
m_pNameFilterTextEntry->GetText( m_wNameFilter.Base(), m_wNameFilter.Count() * sizeof(wchar_t) ); |
|
V_wcslower( m_wNameFilter.Base() ); |
|
} |
|
m_flFilterItemTime = gpGlobals->curtime + 0.5f; |
|
return; |
|
} |
|
} |
|
|
|
vgui::ComboBox *pComboBox = dynamic_cast<vgui::ComboBox *>( pPanel ); |
|
|
|
if ( pComboBox ) |
|
{ |
|
if ( pComboBox == m_pSubcategoriesFilterCombo ) |
|
{ |
|
// the class selection combo box changed, update class details |
|
KeyValues *pUserData = m_pSubcategoriesFilterCombo->GetActiveItemUserData(); |
|
if ( !pUserData ) |
|
return; |
|
|
|
// Update current subcategory filter |
|
m_iCurrentSubcategory = pUserData->GetInt( "index", 0 ); |
|
m_bFilterDirty = true; |
|
|
|
m_iCurrentPage = 0; |
|
UpdateModelPanels(); |
|
|
|
if ( m_pCheckoutButton ) |
|
{ |
|
m_pCheckoutButton->RequestFocus(); |
|
} |
|
|
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_page_2_nav(subcategories)", CFmtStr( "%i", m_iCurrentSubcategory ).Access() ); |
|
} |
|
|
|
else if ( pComboBox == m_pSortByCombo ) |
|
{ |
|
// the class selection combo box changed, update class details |
|
KeyValues *pUserData = m_pSortByCombo->GetActiveItemUserData(); |
|
if ( !pUserData ) |
|
return; |
|
|
|
int iSortTypeSelectionIndex = pUserData->GetInt( "sortby", -1 ); |
|
m_bFilterDirty = true; |
|
if ( iSortTypeSelectionIndex >= 0 ) |
|
{ |
|
eEconStoreSortType iSortType = (eEconStoreSortType)g_StoreSortTypes[iSortTypeSelectionIndex].iSortType; |
|
|
|
UpdateFilteredItems(); |
|
UpdateModelPanels(); |
|
|
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_page_2_nav(sort_by)", CFmtStr( "%i", iSortType ).Access() ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::GetFiltersForDef( GameItemDefinition_t *pDef, CUtlVector<int> *pVecFilters ) |
|
{ |
|
BaseClass::GetFiltersForDef( pDef, pVecFilters ); |
|
} |
|
|
|
bool CTFStorePage2::FindAndSelectEntry( const econ_store_entry_t *pEntry ) |
|
{ |
|
m_iCurrentSubcategory = GetAllSubcategoriesIndex(); |
|
m_bFilterDirty = true; |
|
if ( BaseClass::FindAndSelectEntry( pEntry ) ) |
|
{ |
|
ivgui()->PostMessage( GetVPanel(), new KeyValues( "ItemDefDetails", "ItemDefIndex", pEntry->GetItemDefinitionIndex() ), GetVPanel() ); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::ClearNameFilter( bool bUpdateModelPanels ) |
|
{ |
|
// don't do anything if we don't have any filter |
|
if ( m_wNameFilter.Count() == 0 ) |
|
return; |
|
|
|
m_wNameFilter.RemoveAll(); |
|
if( m_pNameFilterTextEntry ) |
|
{ |
|
m_pNameFilterTextEntry->SetText( "" ); |
|
} |
|
|
|
if ( bUpdateModelPanels ) |
|
{ |
|
m_flFilterItemTime = gpGlobals->curtime + 0.1f; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CTFStorePage2::GetAllSubcategoriesIndex() const |
|
{ |
|
return m_pPageData ? m_pPageData->GetNumSubcategories() : 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::UpdateFilteredItems() |
|
{ |
|
if ( m_bFilterDirty ) |
|
{ |
|
// Make sure list of unfiltered items is sorted |
|
m_pSortByCombo = dynamic_cast< ComboBox * >( FindChildByName( "SortFilterComboBox" ) ); |
|
if ( m_pSortByCombo ) |
|
{ |
|
KeyValues *pUserData = m_pSortByCombo->GetActiveItemUserData(); |
|
if ( pUserData ) |
|
{ |
|
int iSortTypeSelectionIndex = pUserData->GetInt( "sortby", -1 ); |
|
if ( iSortTypeSelectionIndex >= 0 ) |
|
{ |
|
eEconStoreSortType iSortType = (eEconStoreSortType)g_StoreSortTypes[iSortTypeSelectionIndex].iSortType; |
|
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 ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
if ( !IsHomePage() ) |
|
{ |
|
BaseClass::UpdateFilteredItems(); |
|
return; |
|
} |
|
|
|
m_FilteredEntries.Purge(); |
|
|
|
// Subcategories on the home page are special cases, as they aren't based on |
|
// an item's tags. |
|
const StoreCategoryID_t unSubcategoryID = m_pPageData->m_vecSubcategories[ m_iCurrentSubcategory ]->m_unID; |
|
|
|
CStorePanel *pStorePanel = EconUI()->GetStorePanel(); |
|
if ( !pStorePanel ) |
|
return; |
|
|
|
FOR_EACH_VEC( m_vecItemPanels, idx ) |
|
{ |
|
m_vecItemPanels[idx].m_pItemModelPanel->SetShowQuantity( unSubcategoryID != CEconStoreCategoryManager::k_CategoryID_Popular ); |
|
} |
|
|
|
if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_Popular ) |
|
{ |
|
const CUtlVector<uint32>& popularItems = pStorePanel->GetPopularItems(); |
|
for ( int i = 0; i < MIN( m_vecItemPanels.Count(), popularItems.Count() ); ++i ) |
|
{ |
|
const econ_store_entry_t *pEntry = pStorePanel->GetPriceSheet()->GetEntry( popularItems[i] ); |
|
m_FilteredEntries.AddToTail( pEntry ); |
|
} |
|
} |
|
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_New ) |
|
{ |
|
// Add all new items |
|
const CUtlMap< uint16, econ_store_entry_t > &mapEntries = pStorePanel->GetPriceSheet()->GetEntries(); |
|
FOR_EACH_MAP_FAST( mapEntries, i ) |
|
{ |
|
const econ_store_entry_t *pCurEntry = &mapEntries[i]; |
|
if ( pCurEntry->m_bNew ) |
|
{ |
|
m_FilteredEntries.AddToTail( pCurEntry ); |
|
} |
|
} |
|
} |
|
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_OnSale ) |
|
{ |
|
ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); |
|
|
|
// Add all entries that are on sale |
|
const CEconStorePriceSheet::StoreEntryMap_t &mapEntries = pStorePanel->GetPriceSheet()->GetEntries(); |
|
FOR_EACH_MAP_FAST( mapEntries, i ) |
|
{ |
|
const econ_store_entry_t *pCurEntry = &mapEntries[i]; |
|
|
|
if ( pCurEntry->IsOnSale( eCurrency ) ) |
|
{ |
|
m_FilteredEntries.AddToTail( pCurEntry ); |
|
} |
|
} |
|
} |
|
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_Featured ) |
|
{ |
|
const CEconStorePriceSheet::FeaturedItems_t& vecFeaturedItems = pStorePanel->GetPriceSheet()->GetFeaturedItems(); |
|
FOR_EACH_VEC( vecFeaturedItems, i ) |
|
{ |
|
const econ_store_entry_t *pEntry = pStorePanel->GetPriceSheet()->GetEntry( vecFeaturedItems[i] ); |
|
if ( pEntry ) |
|
{ |
|
m_FilteredEntries.AddToTail( pEntry ); |
|
} |
|
else |
|
{ |
|
AssertMsg( 0, "trying to add featured item that's not in the store price sheet.\n" ); |
|
} |
|
} |
|
} |
|
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_ClassBundles ) |
|
{ |
|
// Let's find the class bundles |
|
const CEconStorePriceSheet::StoreEntryMap_t &mapEntries = pStorePanel->GetPriceSheet()->GetEntries(); |
|
FOR_EACH_MAP_FAST( mapEntries, i ) |
|
{ |
|
const econ_store_entry_t *pCurEntry = &mapEntries[i]; |
|
|
|
if ( pCurEntry->IsListedInCategory( CEconStoreCategoryManager::k_CategoryID_ClassBundles ) ) |
|
{ |
|
m_FilteredEntries.AddToTail( pCurEntry ); |
|
} |
|
} |
|
|
|
// Sort by date to get the weapon bundles before the keyless crates |
|
//extern int ItemNameSortComparator( const econ_store_entry_t *const *ppEntryA, const econ_store_entry_t *const *ppEntryB ); |
|
extern int FirstSaleDateSortComparator( const econ_store_entry_t *const *ppItemA, const econ_store_entry_t *const *ppItemB ); |
|
|
|
m_FilteredEntries.Sort( &FirstSaleDateSortComparator ); |
|
|
|
} |
|
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_Taunts ) |
|
{ |
|
const CEconStorePriceSheet::StoreEntryMap_t &mapEntries = pStorePanel->GetPriceSheet()->GetEntries(); |
|
FOR_EACH_MAP_FAST( mapEntries, i ) |
|
{ |
|
const econ_store_entry_t *pCurEntry = &mapEntries[i]; |
|
|
|
if ( pCurEntry->IsListedInCategory( CEconStoreCategoryManager::k_CategoryID_Taunts ) ) |
|
{ |
|
m_FilteredEntries.AddToTail( pCurEntry ); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
AssertMsg( 0, "Subcategory has no defined behavior in code" ); |
|
} |
|
|
|
// If we're either "New" category or the "On Sale" category or the "Taunts" category, sort our contents |
|
// by sale date. |
|
if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_New || unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_OnSale || unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_Taunts ) |
|
{ |
|
extern int FirstSaleDateSortComparator( const econ_store_entry_t *const *ppItemA, const econ_store_entry_t *const *ppItemB ); |
|
|
|
m_FilteredEntries.Sort( &FirstSaleDateSortComparator ); |
|
} |
|
|
|
m_bFilterDirty = false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFStorePage2::DoesEntryFilterPassSecondaryFilter( const econ_store_entry_t *pEntry ) |
|
{ |
|
if ( !DoesEntryFilterPassSubcategoryFilter( pEntry ) ) |
|
{ |
|
return false; |
|
} |
|
|
|
if ( m_wNameFilter.Count() > 0 ) |
|
{ |
|
CEconItemView itemData; |
|
itemData.Init( pEntry->GetItemDefinitionIndex(), AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); |
|
itemData.SetClientItemFlags( kEconItemFlagClient_Preview | kEconItemFlagClient_StoreItem ); |
|
return DoesItemPassSearchFilter( itemData.GetDescription(), m_wNameFilter.Base() ); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFStorePage2::DoesEntryFilterPassSubcategoryFilter( const econ_store_entry_t *pEntry ) |
|
{ |
|
Assert( pEntry ); |
|
Assert( m_pPageData ); |
|
|
|
// Make sure pages without subcategories can still function |
|
if ( !HasSubcategories() ) |
|
return true; |
|
|
|
// "All subcategories" item selected? |
|
if ( m_iCurrentSubcategory == GetAllSubcategoriesIndex() ) |
|
return true; |
|
|
|
if ( !m_pPageData->m_vecSubcategories.IsValidIndex( m_iCurrentSubcategory ) ) |
|
return false; |
|
|
|
// Get the subcategory ID |
|
const StoreCategoryID_t unSubCategoryID = m_pPageData->m_vecSubcategories[ m_iCurrentSubcategory ]->m_unID; |
|
|
|
// If the store entry is covered by the currently selected category, return true. |
|
// return pEntry->m_vecTagIds.Find( unSubCategoryID ) != pEntry->m_vecTagIds.InvalidIndex(); |
|
return pEntry->IsListedInCategory( unSubCategoryID ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::UpdateFilterComboBox( void ) |
|
{ |
|
BaseClass::UpdateFilterComboBox(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnThink( void ) |
|
{ |
|
BaseClass::OnThink(); |
|
|
|
if ( m_flFilterItemTime && gpGlobals->curtime >= m_flFilterItemTime ) |
|
{ |
|
m_bFilterDirty = true; |
|
UpdateFilteredItems(); |
|
UpdateModelPanels(); |
|
m_flFilterItemTime = 0.0f; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CStorePreviewItemPanel *CTFStorePage2::CreatePreviewPanel( void ) |
|
{ |
|
return new CTFStorePreviewItemPanel2( EconUI()->GetStorePanel(), m_pPreviewItemResFile, "storepreviewitem", this ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CStorePricePanel* CTFStorePage2::CreatePricePanel( int iIndex ) |
|
{ |
|
if ( m_pPageData && |
|
m_pPageData->m_bIsHome && |
|
HasSubcategories() && |
|
m_pPageData->m_vecSubcategories.IsValidIndex( m_iCurrentSubcategory ) && |
|
m_pPageData->m_vecSubcategories[ m_iCurrentSubcategory ]->m_unID == CEconStoreCategoryManager::k_CategoryID_Popular ) |
|
{ |
|
return vgui::SETUP_PANEL( new CStorePricePanel_Popular( this, "StorePrice", iIndex + 1 ) ); |
|
} |
|
|
|
return BaseClass::CreatePricePanel( iIndex ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnAddItemToCart( KeyValues *pData ) |
|
{ |
|
item_definition_index_t iItemDef = (item_definition_index_t)pData->GetInt( "item_def", INVALID_ITEM_DEF_INDEX ); |
|
|
|
AddItemToCartHelper( GetPageName(), iItemDef, (ECartItemType)pData->GetInt( "cart_add_type", kCartItem_Purchase ) ); |
|
UpdateCart(); |
|
|
|
// Turn the free slots indicator red if we can't fit everything. |
|
UpdateBackpackLabel(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnItemPanelMouseReleased( vgui::Panel *panel ) |
|
{ |
|
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel ); |
|
if ( pItemPanel && IsVisible() && pItemPanel->HasItem() ) |
|
{ |
|
FOR_EACH_VEC( m_vecItemPanels, i ) |
|
{ |
|
if ( m_vecItemPanels[i].m_pItemModelPanel == pItemPanel ) |
|
{ |
|
ShowPreviewWindow( m_vecItemPanels[i].m_pItemModelPanel->GetItem()->GetItemDefIndex() ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePage2::OnItemPanelMouseDoublePressed( vgui::Panel *panel ) |
|
{ |
|
// Do nothing |
|
}
|
|
|