summaryrefslogtreecommitdiff
path: root/game/client/tf/vgui/item_ad_panel.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/vgui/item_ad_panel.cpp
downloadarchived-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.cpp489
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