diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/vgui/item_ad_panel.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/tf/vgui/item_ad_panel.cpp')
| -rw-r--r-- | game/client/tf/vgui/item_ad_panel.cpp | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/game/client/tf/vgui/item_ad_panel.cpp b/game/client/tf/vgui/item_ad_panel.cpp new file mode 100644 index 0000000..75206cc --- /dev/null +++ b/game/client/tf/vgui/item_ad_panel.cpp @@ -0,0 +1,489 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "item_ad_panel.h" +#include "econ_item_system.h" +#include "item_model_panel.h" +#include "econ_store.h" +#include "econ_ui.h" +#include "store/store_panel.h" +#include "tf_controls.h" +#include "econ_item_description.h" +#include "vgui/IInput.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CBaseAdPanel::CBaseAdPanel( Panel *parent, const char *panelName ) + : BaseClass( parent, panelName ) +{} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseAdPanel::ApplySettings( KeyValues *inResourceData ) +{ + BaseClass::ApplySettings( inResourceData ); + + m_flPresentTime = inResourceData->GetFloat( "present_time", 10.f ); +} + +bool CBaseAdPanel::CheckForRequiredSteamComponents( const char* pszSteamRequried, const char* pszOverlayRequired ) +{ + // Make sure we've got the appropriate connections to Steam + if ( !steamapicontext || !steamapicontext->SteamUtils() ) + { + OpenStoreStatusDialog( NULL, pszSteamRequried, true, false ); + return false; + } + + if ( !steamapicontext->SteamUtils()->IsOverlayEnabled() ) + { + OpenStoreStatusDialog( NULL, pszOverlayRequired, true, false ); + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CItemAdPanel::CItemAdPanel( Panel *parent, const char *panelName, item_definition_index_t itemDefIndex ) + : BaseClass( parent, panelName ) + , m_ItemDefIndex( itemDefIndex ) + , m_bShowMarketButton( true ) +{ + SetDialogVariable( "price", "..." ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CItemAdPanel::ApplySchemeSettings( IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + LoadControlSettings( GetItemDef()->GetAdResFile() ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CItemAdPanel::ApplySettings( KeyValues *inResourceData ) +{ + BaseClass::ApplySettings( inResourceData ); + + m_bShowMarketButton = inResourceData->GetBool( "show_market", true ); // Default to showing market + + if ( !m_bShowMarketButton ) + { + // Tick every second as we try to get our price from the store + vgui::ivgui()->AddTickSignal( GetVPanel(), 1000 ); + } + + const CTFItemDefinition* pItemDef = GetItemDef(); + CItemModelPanel* pItemImage = FindControl< CItemModelPanel >( "ItemIcon" ); + if ( pItemImage ) + { + CEconItemView adItem; + adItem.Init( pItemDef->GetDefinitionIndex(), AE_UNIQUE, 1, 1 ); + pItemImage->InvalidateLayout( true, true ); + pItemImage->SetItem( &adItem ); + + KeyValuesAD modelpanelKV( "modelpanel_kv" ); + KeyValues *itemKV = new KeyValues( "itemmodelpanel" ); + itemKV->SetBool( "inventory_image_type", true ); + itemKV->SetBool( "use_item_rendertarget", false ); + itemKV->SetBool( "allow_rot", false ); + + modelpanelKV->AddSubKey( itemKV ); + pItemImage->ApplySettings( modelpanelKV ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CItemAdPanel::PerformLayout() +{ + BaseClass::PerformLayout(); + + const CTFItemDefinition* pItemDef = GetItemDef(); + + // Get the ad text for the item. If it's not there, juse use the description text. + SetDialogVariable( "item_name", g_pVGuiLocalize->Find( pItemDef->GetItemBaseName() ) ); + const char* pszAdtext = pItemDef->GetAdTextToken() ? pItemDef->GetAdTextToken() : pItemDef->GetItemDesc(); + CExScrollingEditablePanel* pScrollableItemText = FindControl< CExScrollingEditablePanel >( "ScrollableItemText", true ); + if ( pszAdtext && pScrollableItemText ) + { + pScrollableItemText->SetDialogVariable( "item_ad_text", g_pVGuiLocalize->Find( pszAdtext ) ); + + Label* pAdLabel = pScrollableItemText->FindControl< Label >( "ItemAdText", true ); + if ( pAdLabel ) + { + int nWide, nTall; + pAdLabel->GetContentSize( nWide, nTall ); + pAdLabel->SetTall( nTall ); + } + + pScrollableItemText->InvalidateLayout( true ); + } + + CExButton* pBuyButton = FindControl< CExButton >( "BuyButton", true ); + CExButton* pMarketButton = FindControl< CExButton >( "MarketButton", true ); + if ( pBuyButton && pMarketButton ) + { + + pBuyButton->SetVisible( !m_bShowMarketButton ); + pMarketButton->SetVisible( m_bShowMarketButton ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CItemAdPanel::OnTick() +{ + const CTFItemDefinition* pItemDef = GetItemDef(); + bool bStoreIsReady = EconUI()->GetStorePanel() && EconUI()->GetStorePanel()->GetPriceSheet() && EconUI()->GetStorePanel()->GetCart() && steamapicontext && steamapicontext->SteamUser() && pItemDef; + if ( bStoreIsReady ) + { + // Get the price of the item + const ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); + const econ_store_entry_t *pEntry = EconUI()->GetStorePanel()->GetPriceSheet()->GetEntry( pItemDef->GetDefinitionIndex() ); + if ( pEntry ) + { + item_price_t unPrice = pEntry->GetCurrentPrice( eCurrency ); + // Set that price into the button + wchar_t wzLocalizedPrice[ kLocalizedPriceSizeInChararacters ]; + MakeMoneyString( wzLocalizedPrice, ARRAYSIZE( wzLocalizedPrice ), unPrice, eCurrency ); + SetDialogVariable( "price", wzLocalizedPrice ); + + // Don't need to tick anymore + vgui::ivgui()->RemoveTickSignal( GetVPanel() ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const CTFItemDefinition* CItemAdPanel::GetItemDef() const +{ + return (CTFItemDefinition*)ItemSystem()->GetItemSchema()->GetItemDefinition( m_ItemDefIndex ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CItemAdPanel::OnCommand( const char *command ) +{ + if ( FStrEq( "purchase", command ) ) + { + if ( !CheckForRequiredSteamComponents( "#StoreUpdate_SteamRequired", "#MMenu_OverlayRequired" ) ) + return; + + const CTFItemDefinition* pItemDef = GetItemDef(); + if ( pItemDef ) + { + if ( EconUI()->GetStorePanel() && EconUI()->GetStorePanel()->GetPriceSheet() && EconUI()->GetStorePanel()->GetCart() && steamapicontext && steamapicontext->SteamUser() ) + { + // Add a the item to the users cart and checkout + EconUI()->GetStorePanel()->GetCart()->EmptyCart(); + AddItemToCartHelper( NULL, pItemDef->GetDefinitionIndex(), kCartItem_Purchase ); + EconUI()->GetStorePanel()->InitiateCheckout( true ); + } + } + } + else if ( FStrEq( "market", command ) ) + { + if ( !CheckForRequiredSteamComponents( "#StoreUpdate_SteamRequired", "#MMenu_OverlayRequired" ) ) + return; + + const CTFItemDefinition* pItemDef = GetItemDef(); + if ( pItemDef && steamapicontext && steamapicontext->SteamFriends() ) + { + const char *pszPrefix = ""; + if ( GetUniverse() == k_EUniverseBeta ) + { + pszPrefix = "beta."; + } + + static char pszItemName[256]; + g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find ( pItemDef->GetItemBaseName() ) , pszItemName, sizeof(pszItemName) ); + + char szURL[512]; + V_snprintf( szURL, sizeof(szURL), "http://%ssteamcommunity.com/market/listings/%d/%s", pszPrefix, engine->GetAppID(), pszItemName ); + steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( szURL ); + } + } +} + + + +DECLARE_BUILD_FACTORY( CCyclingAdContainerPanel ); + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CCyclingAdContainerPanel::CCyclingAdContainerPanel( Panel *parent, const char *panelName ) + : BaseClass( parent, panelName ) + , m_pAdsContainer( NULL ) + , m_pKVItems( NULL ) + , m_nCurrentIndex( 0 ) + , m_nXPos( 0 ) + , m_nTargetIndex( 0 ) + , m_nTransitionStartOffsetX( 0 ) + , m_bTransitionRight( true ) + , m_bSettingsApplied( false ) + , m_bNeedsToCreatePanels( false ) +{ + m_pAdsContainer = new EditablePanel( this, "AdsContainer" ); + m_pFadePanel = new EditablePanel( this, "FadeTransition" ); + m_pNextButton = new CExButton( this, "NextButton", ">", this, "next" ); + m_pPrevButton = new CExButton( this, "PrevButton", "<", this, "prev" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CCyclingAdContainerPanel::~CCyclingAdContainerPanel() +{ + if ( m_pKVItems ) + { + m_pKVItems->deleteThis(); + m_pKVItems = NULL; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCyclingAdContainerPanel::ApplySchemeSettings( IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + LoadControlSettings( "Resource/UI/econ/CyclingAdContainer.res" ); + + m_bSettingsApplied = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCyclingAdContainerPanel::ApplySettings( KeyValues *inResourceData ) +{ + BaseClass::ApplySettings( inResourceData ); + + KeyValues* pKVItems = inResourceData->FindKey( "items" ); + if ( pKVItems ) + { + SetItemKVs( pKVItems ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCyclingAdContainerPanel::CreatePanels() +{ + if ( ItemSystem()->GetItemSchema()->GetVersion() == 0 ) + return; + + m_vecPossibleAds.Purge(); + + FOR_EACH_TRUE_SUBKEY( m_pKVItems, pKVItem ) + { + const char* pszItemName = pKVItem->GetString( "item" ); + const CEconItemDefinition *pDef = ItemSystem()->GetItemSchema()->GetItemDefinitionByName( pszItemName ); + if ( pDef ) + { + AdData_t& adData = m_vecPossibleAds[ m_vecPossibleAds.AddToTail() ]; + adData.m_pAdPanel = new CItemAdPanel( m_pAdsContainer, "ad", pDef->GetDefinitionIndex() ); + + adData.m_pAdPanel->InvalidateLayout( true, true ); // Default settings + adData.m_pAdPanel->ApplySettings( pKVItem ); + adData.m_pAdPanel->InvalidateLayout(); + } + else + { + AssertMsg( 0, "Invalid item def '%s'!", pszItemName ); + } + } + + m_bNeedsToCreatePanels = false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCyclingAdContainerPanel::PerformLayout() +{ + BaseClass::PerformLayout(); + + PresentIndex( 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCyclingAdContainerPanel::OnThink() +{ + BaseClass::OnThink(); + + if ( m_bNeedsToCreatePanels && m_bSettingsApplied ) + { + CreatePanels(); + PresentIndex( 0 ); + } + + UpdateAdPanelPositions(); + + // See if it's time to auto-cycle to the next ad + if ( m_ShowTimer.HasStarted() && m_ShowTimer.IsElapsed() && m_vecPossibleAds.Count() > 1 ) + { + m_ShowTimer.Invalidate(); + PresentIndex( m_nTargetIndex + 1 ); + } + + int nMouseX, nMouseY; + vgui::input()->GetCursorPos( nMouseX, nMouseY ); + bool bControlsVisible = IsWithin( nMouseX, nMouseY ) && m_vecPossibleAds.Count() > 1; + m_pPrevButton->SetVisible( bControlsVisible ); + m_pNextButton->SetVisible( bControlsVisible ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCyclingAdContainerPanel::SetItemKVs( KeyValues* pKVItems ) +{ + if ( pKVItems ) + { + if ( m_pKVItems ) + { + m_pKVItems->deleteThis(); + m_pKVItems = NULL; + } + m_pKVItems = pKVItems->MakeCopy(); + } + + m_bNeedsToCreatePanels = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCyclingAdContainerPanel::OnCommand( const char *command ) +{ + if ( FStrEq( "next", command ) ) + { + PresentIndex( m_nTargetIndex + 1 ); + } + else if ( FStrEq( "prev", command ) ) + { + PresentIndex( m_nTargetIndex - 1 ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCyclingAdContainerPanel::PresentIndex( int nIndex ) +{ + if ( m_vecPossibleAds.IsEmpty() ) + return; + + if ( m_nCurrentIndex == nIndex ) + return; + + // Figure out which way we want to ransition + m_bTransitionRight = nIndex > m_nCurrentIndex; + + // Wrap if needed + if ( nIndex >= m_vecPossibleAds.Count() ) + { + nIndex = 0; + } + else if ( nIndex < 0 ) + { + nIndex = m_vecPossibleAds.Count() - 1; + } + + m_nTargetIndex = nIndex; + + // If they click more times while transitioning out, just change the target. If we're + // into transitioning in to the next panel, then we need to start the whole thing over. + if ( !IsTransitioningOut() ) + { + m_nTransitionStartOffsetX = m_nXPos; + float flTransitionTime = 1.f; + m_TransitionTimer.Start( flTransitionTime ); + + m_ShowTimer.Start( flTransitionTime + m_vecPossibleAds[ m_nCurrentIndex ].m_pAdPanel->GetPresentTime() ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCyclingAdContainerPanel::UpdateAdPanelPositions() +{ + // Figure out how far along a transition we are + float flPercent = Clamp( m_TransitionTimer.GetElapsedTime() / m_TransitionTimer.GetCountdownDuration(), 0.f, 1.f ); + flPercent = Gain( flPercent, 0.8f ); + + // At a certain point, we're no longer transitioning out the old -- we're transitioning in the new + const float flTransitionCutOff = m_TransitionTimer.GetCountdownDuration() / 2.f; + bool bTransitionOut = flPercent < flTransitionCutOff; + + int nStartX = 0; + int nTargetX = 0; + float flFadeAmount = 0.f; + + if ( bTransitionOut ) + { + nStartX = m_nTransitionStartOffsetX; + nTargetX = m_bTransitionRight ? -100 : 100; + flFadeAmount = RemapValClamped( flPercent, 0.f, flTransitionCutOff * 0.75f, 0.f, 255.f ); + } + else + { + // Once we've passed the middle, show the target + m_nCurrentIndex = m_nTargetIndex; + nStartX = m_bTransitionRight ? 100 : -100; + nTargetX = 0; + flFadeAmount = RemapValClamped( flPercent, flTransitionCutOff * 1.25f, 1.f, 255.f, 0.f ); + } + + // Alpha fades up entirely near the middle to cover the swap + m_pFadePanel->SetAlpha( flFadeAmount ); + + m_nXPos = RemapVal( flPercent, 0.f, 1.f, nStartX, nTargetX ); + FOR_EACH_VEC( m_vecPossibleAds, i ) + { + m_vecPossibleAds[i].m_pAdPanel->SetPos( m_nXPos, m_vecPossibleAds[i].m_pAdPanel->GetYPos() ); + m_vecPossibleAds[i].m_pAdPanel->SetVisible( i == m_nCurrentIndex ); + } +} + +float CCyclingAdContainerPanel::GetTransitionProgress() const +{ + float flPercent = Clamp( m_TransitionTimer.GetElapsedTime() / m_TransitionTimer.GetCountdownDuration(), 0.f, 1.f ); + return Gain( flPercent, 0.8f ); +} + +bool CCyclingAdContainerPanel::IsTransitioningOut() const +{ + const float flTransitionCutOff = m_TransitionTimer.GetCountdownDuration() / 2.f; + return GetTransitionProgress() < flTransitionCutOff; +}
\ No newline at end of file |