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.
1367 lines
46 KiB
1367 lines
46 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
|
|
#include "cbase.h" |
|
#include "store/v2/tf_store_preview_item2.h" |
|
#include "econ_item_description.h" |
|
#include "vgui_controls/TextImage.h" |
|
#include "vgui_controls/ScrollBar.h" |
|
#include "vgui_controls/ScrollBarSlider.h" |
|
#include "vgui/IInput.h" |
|
#include "tf_item_schema.h" |
|
#include "econ_item_system.h" |
|
#include "store/store_panel.h" |
|
#include "c_tf_gamestats.h" |
|
#include "tf_playermodelpanel.h" |
|
#include "navigationpanel.h" |
|
#include "tf_mouseforwardingpanel.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
inline float LerpScale( float flIn, float flInMin, float flInMax, float flOutMin, float flOutMax ) |
|
{ |
|
float flDenom = flInMax - flInMin; |
|
if ( flDenom == 0.0f ) |
|
return 0.0f; |
|
|
|
float t = clamp( ( flIn - flInMin ) / flDenom, 0.0f, 1.0f ); |
|
return Lerp( t, flOutMin, flOutMax ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
inline float SCurve( float t ) |
|
{ |
|
t = clamp( t, 0.0f, 1.0f ); |
|
return t * t * (3 - 2*t); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CFullscreenStorePreviewItem::CFullscreenStorePreviewItem( vgui::Panel *pParent, EditablePanel *pOwner ) |
|
: BaseClass( pParent, "FullscreenStorePreview" ), |
|
m_iItemDef( INVALID_ITEM_ID ), |
|
m_pCycleTextLabel( NULL ), |
|
m_pTeamNavPanel( NULL ), |
|
m_pPreviewButton( NULL ), |
|
m_pRotLeftButton( NULL ), |
|
m_pRotRightButton( NULL ), |
|
m_pZoomButton( NULL ), |
|
m_pOverlayPanel( NULL ), |
|
m_flGoFullscreenStartTime( 0.0f ), |
|
m_flLastMouseMoveTime( 0.0f ), |
|
m_bIsHalloweenOrFullmoonOnlyItem( false ) |
|
{ |
|
m_hOwner = pOwner; |
|
} |
|
|
|
void CFullscreenStorePreviewItem::SetItemDef( itemid_t iItemDef ) |
|
{ |
|
m_iItemDef = iItemDef; |
|
|
|
CStorePanel *pStorePanel = EconUI()->GetStorePanel(); |
|
if ( pStorePanel ) |
|
{ |
|
const CEconStorePriceSheet *pPriceSheet = pStorePanel->GetPriceSheet(); |
|
CExButton *pPreviewButton = dynamic_cast<CExButton *>( FindChildByName( "TryItOutButton" ) ); |
|
if ( pPriceSheet && pPreviewButton ) |
|
{ |
|
const econ_store_entry_t *pStoreEntry = pPriceSheet->GetEntry( m_iItemDef ); |
|
pPreviewButton->SetVisible( pStoreEntry && pStoreEntry->CanPreview() ); |
|
} |
|
} |
|
} |
|
|
|
void CFullscreenStorePreviewItem::GoFullscreen( CTFPlayerModelPanel *pPlayerModelPanel ) |
|
{ |
|
m_Stats.Clear(); |
|
|
|
m_flGoFullscreenStartTime = gpGlobals->realtime; |
|
|
|
SetAlpha( 0 ); |
|
SetVisible( true ); |
|
MoveToFront(); |
|
|
|
m_pPlayerModelPanel = pPlayerModelPanel; |
|
|
|
if ( !m_pPlayerModelPanel.Get() ) |
|
return; |
|
|
|
// Cache old player model panel bounds and such |
|
m_pPlayerModelPanel->GetBounds( m_OldModelState.m_aPlayerModelPanelBounds[0], m_OldModelState.m_aPlayerModelPanelBounds[1], m_OldModelState.m_aPlayerModelPanelBounds[2], m_OldModelState.m_aPlayerModelPanelBounds[3] ); |
|
m_OldModelState.m_vecPlayerPos = m_pPlayerModelPanel->m_vecPlayerPos; |
|
m_OldModelState.m_bZoomed = m_pPlayerModelPanel->IsZoomed(); |
|
|
|
// Fullscreen panel is new parent |
|
m_pPlayerModelPanel->SetParent( this ); |
|
|
|
// Get team state |
|
if ( m_pTeamNavPanel ) |
|
{ |
|
m_pTeamNavPanel->UpdateButtonSelectionStates( m_pPlayerModelPanel->GetTeam() == TF_TEAM_RED ? 0 : 1 ); |
|
} |
|
} |
|
|
|
void CFullscreenStorePreviewItem::ExitFullscreen() |
|
{ |
|
if ( !m_hOwner.Get() ) |
|
return; |
|
|
|
if ( m_pPlayerModelPanel.Get() ) |
|
{ |
|
m_pPlayerModelPanel->SetParent( m_hOwner.Get() ); |
|
m_pPlayerModelPanel->SetBounds( m_OldModelState.m_aPlayerModelPanelBounds[0], m_OldModelState.m_aPlayerModelPanelBounds[1], m_OldModelState.m_aPlayerModelPanelBounds[2], m_OldModelState.m_aPlayerModelPanelBounds[3] ); |
|
|
|
// Reset the player position to it's pre-fullscreen location, but add on any zoom delta if needed. |
|
const Vector vecZoomOffset = m_OldModelState.m_bZoomed != m_pPlayerModelPanel->IsZoomed() ? m_pPlayerModelPanel->GetZoomOffset() : vec3_origin; |
|
m_pPlayerModelPanel->m_vecPlayerPos = m_OldModelState.m_vecPlayerPos + vecZoomOffset; |
|
} |
|
|
|
m_flGoFullscreenStartTime = 0.0f; |
|
SetVisible( false ); |
|
|
|
PostMessage( m_hOwner.Get(), new KeyValues( "ExitFullscreen" ) ); |
|
} |
|
|
|
bool CFullscreenStorePreviewItem::IsFullscreenMode() |
|
{ |
|
return IsVisible(); |
|
} |
|
|
|
void CFullscreenStorePreviewItem::OnNavButtonSelected( KeyValues *pData ) |
|
{ |
|
const int iTeam = pData->GetInt( "userdata", -1 ); AssertMsg( iTeam >= 0, "Bad filter" ); |
|
if ( iTeam < 0 ) |
|
return; |
|
|
|
if ( !m_pPlayerModelPanel.Get() ) |
|
return; |
|
|
|
m_pPlayerModelPanel->SetTeam( iTeam ); |
|
|
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "team_switch_%s(store_preview_item_panel_fullscreen)", iTeam == TF_TEAM_RED ? "red" : "blu" ); |
|
} |
|
|
|
void CFullscreenStorePreviewItem::OnThink() |
|
{ |
|
BaseClass::OnThink(); |
|
|
|
if ( m_flGoFullscreenStartTime == 0.0f ) |
|
{ |
|
SetVisible( false ); |
|
return; |
|
} |
|
|
|
// We are fading, or already faded in |
|
SetVisible( true ); |
|
|
|
// Keep track of mouse movement - if the mouse button is down, force the mouse-moving state so we |
|
// don't end up fading out while the player is rotating or clicking-and-holding anywhere else |
|
int nMouseX, nMouseY; |
|
vgui::input()->GetCursorPos( nMouseX, nMouseY ); |
|
bool bMouseMoved = false; |
|
const bool bMouseButtonDown = vgui::input()->IsMouseDown( MOUSE_LEFT ); |
|
const bool bForceMouseMoving = bMouseButtonDown; |
|
if ( bForceMouseMoving || nMouseX != m_nLastMouseX || nMouseY != m_nLastMouseY ) |
|
{ |
|
bMouseMoved = true; |
|
m_nLastMouseX = nMouseX; |
|
m_nLastMouseY = nMouseY; |
|
m_flLastMouseMoveTime = gpGlobals->realtime; |
|
} |
|
|
|
// Fade in the button blocker if the mouse has been idle for some period of time |
|
if ( m_pOverlayPanel ) |
|
{ |
|
const float flButtonBlockerFade = SCurve( |
|
LerpScale( |
|
gpGlobals->realtime, |
|
m_flLastMouseMoveTime + m_flUiFadeoutTime, |
|
m_flLastMouseMoveTime + m_flUiFadeoutTime + m_flUiFadeoutDuration, |
|
0.0f, |
|
1.0f |
|
) |
|
); |
|
|
|
m_pOverlayPanel->SetVisible( flButtonBlockerFade > 0.0f ); |
|
|
|
m_pOverlayPanel->SetAlpha( (int)( 255 * flButtonBlockerFade ) ); |
|
|
|
// Set to layer above overlay panel, so it will always be visible |
|
m_pPlayerModelPanel->SetZPos( flButtonBlockerFade > 0.0f ? ( m_pOverlayPanel->GetZPos() + 1 ) : 0 ); |
|
} |
|
|
|
const float flFade = SCurve( |
|
LerpScale( |
|
gpGlobals->realtime, |
|
m_flGoFullscreenStartTime, |
|
m_flGoFullscreenStartTime + m_flFullscreenFadeToBlackDuration, |
|
0.0f, |
|
1.0f |
|
) |
|
); |
|
|
|
SetAlpha( (int)( 255 * flFade ) ); |
|
|
|
if ( !m_pPlayerModelPanel.Get() ) |
|
return; |
|
|
|
// Resize 3D model panel |
|
const int aDstBounds[4] = { 0, 0, ScreenWidth(), ScreenHeight() }; |
|
const int aBounds[4] = { |
|
Lerp( flFade, m_OldModelState.m_aPlayerModelPanelBounds[0], aDstBounds[0] ), |
|
Lerp( flFade, m_OldModelState.m_aPlayerModelPanelBounds[1], aDstBounds[1] ), |
|
Lerp( flFade, m_OldModelState.m_aPlayerModelPanelBounds[2], aDstBounds[2] ), |
|
Lerp( flFade, m_OldModelState.m_aPlayerModelPanelBounds[3], aDstBounds[3] ) |
|
}; |
|
m_pPlayerModelPanel->SetBounds( aBounds[0], aBounds[1], aBounds[2], aBounds[3] ); |
|
|
|
if ( flFade < 0.999f ) |
|
{ |
|
const Vector vecZoomOffset = m_pPlayerModelPanel->IsZoomed() ? m_pPlayerModelPanel->GetZoomOffset() : vec3_origin; |
|
const Vector vecFullscreenOrigin( m_flModelPanelOriginX, m_flModelPanelOriginY, m_flModelPanelOriginZ ); |
|
m_pPlayerModelPanel->m_vecPlayerPos = Lerp( flFade, m_OldModelState.m_vecPlayerPos, vecFullscreenOrigin + vecZoomOffset ); |
|
} |
|
|
|
if ( m_pZoomButton ) |
|
{ |
|
m_pZoomButton->SetEnabled( flFade == 1.0f ); |
|
} |
|
|
|
if ( bMouseButtonDown && m_pRotLeftButton && m_pRotRightButton ) |
|
{ |
|
float flDeltaAngle = 0; |
|
const float kScale = 100.0f; |
|
if ( m_pRotLeftButton->IsWithin( nMouseX, nMouseY ) ) |
|
{ |
|
flDeltaAngle = -gpGlobals->frametime * kScale; |
|
} |
|
else if ( m_pRotRightButton->IsWithin( nMouseX, nMouseY ) ) |
|
{ |
|
flDeltaAngle = gpGlobals->frametime * kScale; |
|
} |
|
|
|
m_pPlayerModelPanel->RotateYaw( flDeltaAngle ); |
|
|
|
// Accumulate time rotation buttons are being pressed for stat tracking |
|
m_Stats.m_flRotationTime += gpGlobals->frametime; |
|
} |
|
} |
|
|
|
void CFullscreenStorePreviewItem::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
LoadControlSettings( "Resource/UI/econ/store/v2/StorePreviewItemPanel_Fullscreen.res" ); |
|
|
|
m_pOverlayPanel = dynamic_cast<EditablePanel *>( FindChildByName( "OverlayPanel" ) ); |
|
m_pRotLeftButton = dynamic_cast<CExButton *>( FindChildByName( "RotateLeftButton" ) ); |
|
m_pRotRightButton = dynamic_cast<CExButton *>( FindChildByName( "RotateRightButton" ) ); |
|
m_pZoomButton = dynamic_cast<CExButton *>( FindChildByName( "ZoomButton" ) ); |
|
m_pTeamNavPanel = dynamic_cast<CNavigationPanel *>( FindChildByName( "TeamNavPanel" ) ); |
|
} |
|
|
|
void CFullscreenStorePreviewItem::OnCommand( const char *command ) |
|
{ |
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "on_command(store_preview_item_panel_fullscreen)", command ); |
|
|
|
if ( !V_strnicmp( command, "close", 6 ) ) |
|
{ |
|
ExitFullscreen(); |
|
return; |
|
} |
|
|
|
if ( m_hOwner.Get() ) |
|
{ |
|
// Let the owner handle the command |
|
m_hOwner->OnCommand( command ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTFStorePreviewItemPanel2::CTFStorePreviewItemPanel2( vgui::Panel *pParent, const char *pResFile, const char *pPanelName, CStorePage *pOwner ) |
|
: BaseClass( pParent, pResFile, "storepreviewitem", pOwner ) |
|
{ |
|
m_pScrollBar = new ScrollBar( this, "ScrollBar", true ); |
|
m_pScrollBar->AddActionSignalTarget( this ); |
|
|
|
m_pFullscreenPanel = new CFullscreenStorePreviewItem( this, this ); |
|
m_pFullscreenPanel->AddActionSignalTarget( this ); |
|
|
|
m_pMouseOverItemPanel = vgui::SETUP_PANEL( new CItemModelPanel( this, "mouseoveritempanel" ) ); |
|
m_pMouseOverTooltip = new CItemModelPanelToolTip( this ); |
|
m_pMouseOverTooltip->SetupPanels( this, m_pMouseOverItemPanel ); |
|
m_pMouseOverTooltip->SetPositioningStrategy( IPTTP_BOTTOM_SIDE ); |
|
m_pMouseOverItemPanel->MoveToFront(); |
|
|
|
m_pItemViewData = NULL; |
|
m_pSOEconItemData = NULL; |
|
Clear(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::Clear() |
|
{ |
|
m_pPlayerModelPanel = NULL; |
|
|
|
m_pPreviewButton = NULL; |
|
m_pDialogFrame = NULL; |
|
m_pPreviewViewportBg = NULL; |
|
m_pItemNameLabel = NULL; |
|
m_pAttributesLabel = NULL; |
|
m_pItemCollectionHighlight = NULL; |
|
m_pDetailsView = NULL; |
|
m_pDetailsViewChild = NULL; // Scrollable |
|
m_pItemWikiPageButton = NULL; |
|
m_pTeamNavPanel = NULL; |
|
m_pCycleTextLabel = NULL; |
|
m_pScrollableChild = NULL; |
|
m_pGoFullscreenButton = NULL; |
|
m_nNumAttribLinesAdded = 0; |
|
m_bArmoryTextAdded = false; |
|
m_nNumAttribLinesAdded = 0; |
|
m_iSliderPos = 0; |
|
m_aClickPos[0] = m_aClickPos[1] = 0; |
|
m_bCloseOnUp = false; |
|
m_bMouseWasDown = false; |
|
m_bIsHalloweenOrFullmoonOnlyItem = false; |
|
|
|
for ( int i = 0; i < ARRAYSIZE( m_pAddRentalToCartButtons ); i++ ) |
|
{ |
|
m_pAddRentalToCartButtons[i] = NULL; |
|
} |
|
|
|
m_vecReferenceItemPanels.RemoveAll(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
Clear(); |
|
|
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
FOR_EACH_VEC( m_pItemIcons, i ) |
|
{ |
|
// Strip tooltips. |
|
// We have all the same data already |
|
m_pItemIcons[i]->GetItemPanel()->SetTooltip( NULL, NULL ); |
|
} |
|
|
|
m_pDialogFrame = dynamic_cast<EditablePanel *>( FindChildByName( "DialogFrame" ) ); |
|
m_pPreviewButton = dynamic_cast<CExButton *>( FindChildByName( "TryItOutButton" ) ); |
|
m_pCycleTextLabel = dynamic_cast<CExLabel *>( FindChildByName( "CycleTextLabel" ) ); |
|
m_pGoFullscreenButton = dynamic_cast<CExImageButton *>( FindChildByName( "GoFullscreenButton" ) ); |
|
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE( m_pAddRentalToCartButtons ) == 3 ); |
|
#ifdef ENABLE_STORE_RENTAL_BACKEND |
|
m_pAddRentalToCartButtons[0] = dynamic_cast<CExButton *>( FindChildByName( "AddRentalToCartButton_1Day" ) ); |
|
m_pAddRentalToCartButtons[1] = dynamic_cast<CExButton *>( FindChildByName( "AddRentalToCartButton_3Day" ) ); |
|
m_pAddRentalToCartButtons[2] = dynamic_cast<CExButton *>( FindChildByName( "AddRentalToCartButton_7Day" ) ); |
|
#endif |
|
|
|
if ( m_pDialogFrame ) |
|
{ |
|
m_pPreviewViewportBg = dynamic_cast<EditablePanel *>( m_pDialogFrame->FindChildByName( "PreviewViewportBg" ) ); |
|
m_pItemNameLabel = dynamic_cast<CExLabel *>( m_pDialogFrame->FindChildByName( "ItemNameLabel" ) ); |
|
m_pDetailsView = dynamic_cast<EditablePanel *>( m_pDialogFrame->FindChildByName( "DetailsView" ) ); |
|
|
|
if ( m_pDetailsView ) |
|
{ |
|
m_pDetailsViewChild = dynamic_cast<EditablePanel *>( m_pDetailsView->FindChildByName( "ScrollableChild" ) ); |
|
|
|
if ( !m_pDetailsViewChild ) |
|
{ |
|
m_pDetailsViewChild = m_pDetailsView; |
|
} |
|
|
|
m_pAttributesLabel = dynamic_cast<CExLabel *>( m_pDetailsViewChild->FindChildByName( "AttributesLabel" ) ); |
|
m_pItemCollectionHighlight = dynamic_cast<EditablePanel *>( m_pDetailsViewChild->FindChildByName( "collectionhighlight" ) ); |
|
if ( m_pItemCollectionHighlight ) |
|
{ |
|
m_pItemCollectionHighlight->InvalidateLayout( true, true ); |
|
} |
|
m_pItemWikiPageButton = dynamic_cast<CExButton *>( m_pDetailsViewChild->FindChildByName( "ItemWikiPageButton" ) ); |
|
|
|
if ( m_pItemWikiPageButton ) |
|
{ |
|
m_pItemWikiPageButton->AddActionSignalTarget( this ); |
|
} |
|
} |
|
} |
|
|
|
m_pTeamNavPanel = dynamic_cast<CNavigationPanel *>( FindChildByName( "TeamNavPanel" ) ); |
|
|
|
m_pMouseOverItemPanel->SetBorder( pScheme->GetBorder("LoadoutItemPopupBorder") ); |
|
|
|
SetState( PS_ITEM ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Given two controls A and B, place B such that it is (nXOffset,nYOffset) |
|
// pixels offset from A, using it's content width or height, depending on bVertical. |
|
// pControlNameA can be NULL, in which case zeros will be used as the offset. |
|
//----------------------------------------------------------------------------- |
|
int CTFStorePreviewItemPanel2::PlaceControl( Panel *pParent, const char *pControlNameA, const char *pControlNameB, int nOffset, bool bVertical, bool bSizeAToContents/*=true*/, bool bUseContentSize/*=true*/ ) |
|
{ |
|
if ( !pParent || !pControlNameB ) |
|
{ |
|
AssertMsg( 0, "Bad!" ); |
|
return 0; |
|
} |
|
|
|
Label *pControlA = pControlNameA ? dynamic_cast<Label *>( pParent->FindChildByName( pControlNameA ) ) : NULL; |
|
Label *pControlB = dynamic_cast<Label *>( pParent->FindChildByName( pControlNameB ) ); |
|
if ( !pControlB ) |
|
{ |
|
return 0; |
|
} |
|
|
|
if ( !pControlA && bVertical ) |
|
{ |
|
pControlA = m_pLastNewLineControl; |
|
} |
|
|
|
int aSize[2] = { 0, 0 }; |
|
int aPos[2] = { 0, 0 }; |
|
if ( pControlA ) |
|
{ |
|
pControlA->SetVisible( true ); |
|
|
|
if ( bSizeAToContents ) |
|
{ |
|
pControlA->SizeToContents(); |
|
pControlA->InvalidateLayout( true ); |
|
} |
|
|
|
if ( bUseContentSize ) |
|
{ |
|
pControlA->GetContentSize( aSize[0], aSize[1] ); |
|
} |
|
else |
|
{ |
|
pControlA->GetSize( aSize[0], aSize[1] ); |
|
} |
|
|
|
pControlA->GetPos( aPos[0], aPos[1] ); |
|
} |
|
|
|
int aOffset[2] = { 0, 0 }; |
|
if ( bVertical ) |
|
{ |
|
aOffset[1] = aSize[1] + nOffset; |
|
} |
|
else |
|
{ |
|
aOffset[0] = aSize[0] + nOffset; |
|
} |
|
|
|
// NOTE: We add in the slider position here |
|
pControlB->SetPos( aPos[0] + aOffset[0], aPos[1] + aOffset[1] ); |
|
|
|
pControlB->SetVisible( true ); |
|
|
|
#if _DEBUG |
|
/* |
|
Msg( "control A: %s size: w=%i h=%i pos: (%i, %i)\n", pControlNameA, aSize[0], aSize[1], aPos[0], aPos[1] ); |
|
int x,y; |
|
pControlB->GetPos(x,y); |
|
Msg( "control B: %s pos: (%i, %i)\n", pControlNameB, x,y ); |
|
*/ |
|
#endif |
|
|
|
if ( bVertical ) |
|
{ |
|
m_pLastNewLineControl = pControlB; |
|
} |
|
|
|
m_nViewMaxHeight = MAX( m_nViewMaxHeight, aPos[1] + aOffset[1] + pControlB->GetTall() ); |
|
return m_nViewMaxHeight; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::PerformLayout( void ) |
|
{ |
|
// BaseClass::PerformLayout(); // We override completely here |
|
|
|
// center the icons (we need to redo some of the work of CStorePreviewItemPanel, because we |
|
// center the base item icons along with our TF specific class ones) |
|
int iNumItemIcons = 0; |
|
FOR_EACH_VEC( m_pItemIcons, i ) |
|
{ |
|
if ( m_pItemIcons[i]->IsVisible() ) |
|
{ |
|
++iNumItemIcons; |
|
} |
|
} |
|
|
|
int iNumClassIcons = 0; |
|
FOR_EACH_VEC( m_pClassIcons, i ) |
|
{ |
|
if ( m_pClassIcons[i]->IsVisible() ) |
|
{ |
|
++iNumClassIcons; |
|
} |
|
} |
|
|
|
if ( m_pDialogFrame && ( iNumItemIcons || iNumClassIcons ) ) |
|
{ |
|
int aDialogFramePos[2]; |
|
m_pDialogFrame->GetPos( aDialogFramePos[0], aDialogFramePos[1] ); |
|
|
|
int iCenterX = aDialogFramePos[0] + m_pDialogFrame->GetWide() / 4; |
|
int interval = XRES(2); |
|
int totalWidth = (iNumItemIcons > 0 ? iNumItemIcons * m_pItemIcons[0]->GetWide() : 0) + (iNumClassIcons * m_pClassIcons[0]->GetWide()) + (interval * (iNumItemIcons + iNumClassIcons - 1)); |
|
int iX = iCenterX - ( totalWidth / 2 ); |
|
|
|
int posX, posY; |
|
if ( iNumItemIcons > 0 ) |
|
{ |
|
m_pItemIcons[0]->GetPos( posX, posY ); |
|
} |
|
else |
|
{ |
|
m_pClassIcons[0]->GetPos( posX, posY ); |
|
} |
|
|
|
int iButton = 0; |
|
for ( int i = 0; i < m_pItemIcons.Count(); i++ ) |
|
{ |
|
if ( m_pItemIcons[i]->IsVisible() ) |
|
{ |
|
m_pItemIcons[i]->SetPos( iX, posY ); |
|
iX += m_pItemIcons[i]->GetWide() + interval; |
|
|
|
iButton++; |
|
} |
|
} |
|
|
|
for ( int i = 0; i < m_pClassIcons.Count(); i++ ) |
|
{ |
|
if ( m_pClassIcons[i]->IsVisible() ) |
|
{ |
|
m_pClassIcons[i]->SetPos( iX, posY ); |
|
iX += m_pClassIcons[i]->GetWide() + interval; |
|
|
|
iButton++; |
|
} |
|
} |
|
} |
|
|
|
if ( !m_pPreviewViewportBg || !m_pItemNameLabel || !m_pDetailsViewChild || !m_pDetailsView || !m_pDialogFrame ) |
|
{ |
|
m_pScrollBar->SetVisible( false ); |
|
return; |
|
} |
|
|
|
// Make sure we size the item name in case it needs multiple lines. |
|
m_pItemNameLabel->SizeToContents(); |
|
m_pItemNameLabel->InvalidateLayout( true ); |
|
if ( m_pItemNameLabel && m_item.IsValid() ) |
|
{ |
|
const CEconItemRarityDefinition* pItemRarity = GetItemSchema()->GetRarityDefinition( m_item.GetItemDefinition()->GetRarity() ); |
|
|
|
// Setup the rarity color overlay |
|
{ |
|
Color color( 255, 255, 255, 255 ); |
|
if ( pItemRarity ) |
|
{ |
|
attrib_colors_t attribColor = pItemRarity->GetAttribColor(); |
|
vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); |
|
color = pScheme->GetColor( GetColorNameForAttribColor( attribColor ), Color( 255, 255, 255, 255 ) ); |
|
} |
|
m_pItemNameLabel->SetColorStr( color ); |
|
} |
|
} |
|
|
|
int aItemNameLabelPos[2]; |
|
m_pItemNameLabel->GetPos( aItemNameLabelPos[0], aItemNameLabelPos[1] ); |
|
|
|
// This is the item label's new bottom y coordinate after it's been sized |
|
const int nNewYRelativeToDlgFrame = aItemNameLabelPos[1] + m_pItemNameLabel->GetTall(); |
|
|
|
// Set ypos for details view and scroll bar |
|
int aDetailsViewPos[2]; |
|
m_pDetailsView->GetPos( aDetailsViewPos[0], aDetailsViewPos[1] ); |
|
m_pDetailsView->SetPos( aDetailsViewPos[0], nNewYRelativeToDlgFrame ); |
|
|
|
int aDialogFramePos[2]; |
|
m_pDialogFrame->GetPos( aDialogFramePos[0], aDialogFramePos[1] ); |
|
|
|
if ( m_pScrollBar ) |
|
{ |
|
int aScrollBar[2]; |
|
m_pScrollBar->GetPos( aScrollBar[0], aScrollBar[1] ); |
|
m_pScrollBar->SetPos( aScrollBar[0], nNewYRelativeToDlgFrame + aDialogFramePos[1] ); |
|
} |
|
|
|
int nNewHeight = m_pPreviewViewportBg->GetTall() - m_pItemNameLabel->GetTall(); |
|
m_pDetailsView->SetTall( nNewHeight ); |
|
if ( m_pScrollBar ) |
|
{ |
|
m_pScrollBar->SetTall( nNewHeight ); |
|
} |
|
|
|
// Place paint and style buttons |
|
CUtlVector<CExButton *> vecVisibleButtons; |
|
const int nNumPossibilyVisibleWeapons = 1; |
|
CExButton *pPossiblyVisibleButtons[nNumPossibilyVisibleWeapons] = { m_pNextWeaponButton }; |
|
for ( int i = 0; i < nNumPossibilyVisibleWeapons; ++i ) |
|
{ |
|
CExButton *pCurButton = pPossiblyVisibleButtons[i]; |
|
if ( !pCurButton || !pCurButton->IsVisible() ) |
|
continue; |
|
|
|
vecVisibleButtons.AddToTail( pCurButton ); |
|
} |
|
|
|
int nNumButtonsNeeded = vecVisibleButtons.Count(); |
|
if ( nNumButtonsNeeded ) |
|
{ |
|
// Center however many buttons we need to along the top of the viewport |
|
int aViewportPos[2]; |
|
m_pPreviewViewportBg->GetPos( aViewportPos[0], aViewportPos[1] ); |
|
for ( int i = 0; i < nNumButtonsNeeded; ++i ) |
|
{ |
|
CExButton *pCurButton = vecVisibleButtons[i]; |
|
pCurButton->SetPos( aDialogFramePos[0] + aViewportPos[0] + ( i + 1 ) * m_pPreviewViewportBg->GetWide() / ( nNumButtonsNeeded + 1 ) - m_iControlButtonWidth / 2, m_iControlButtonY ); |
|
pCurButton->SetSize( m_iControlButtonWidth, m_iControlButtonHeight ); |
|
} |
|
} |
|
|
|
m_pLastNewLineControl = NULL; |
|
m_nViewMaxHeight = 0; |
|
|
|
PlaceControl( m_pDetailsViewChild, NULL, "ItemLevelInfoLabel", m_iSmallVerticalBreakSize, true ); |
|
|
|
if ( m_bIsHalloweenOrFullmoonOnlyItem ) |
|
{ |
|
PlaceControl( m_pDetailsViewChild, "ItemLevelInfoLabel", "RestrictionsLabel", m_iMediumVerticalBreakSize, true ); |
|
PlaceControl( m_pDetailsViewChild, "RestrictionsLabel", "RestrictionsTextLabel", m_iHorizontalBreakSize, false ); |
|
PlaceControl( m_pDetailsViewChild, "RestrictionsLabel", "UsedByLabel", m_iSmallVerticalBreakSize, true ); |
|
} |
|
else |
|
{ |
|
PlaceControl( m_pDetailsViewChild, "ItemLevelInfoLabel", "UsedByLabel", m_iMediumVerticalBreakSize, true ); |
|
} |
|
|
|
PlaceControl( m_pDetailsViewChild, "UsedByLabel", "UsedByTextLabel", m_iHorizontalBreakSize, false ); |
|
PlaceControl( m_pDetailsViewChild, "UsedByLabel", "SlotLabel", m_iSmallVerticalBreakSize, true ); |
|
PlaceControl( m_pDetailsViewChild, "SlotLabel", "SlotTextLabel", m_iHorizontalBreakSize, false ); |
|
PlaceControl( m_pDetailsViewChild, "SlotLabel", "PriceLabel", m_iBigVerticalBreakSize, true ); |
|
|
|
if ( m_bArmoryTextAdded ) |
|
{ |
|
PlaceControl( m_pDetailsViewChild, "PriceLabel", "ArmoryTextLabel", m_iBigVerticalBreakSize, true ); |
|
PlaceControl( m_pDetailsViewChild, "ArmoryTextLabel", "AttributesLabel", m_iBigVerticalBreakSize, true ); |
|
} |
|
else |
|
{ |
|
PlaceControl( m_pDetailsViewChild, "PriceLabel", "AttributesLabel", m_iBigVerticalBreakSize, true ); |
|
} |
|
|
|
PlaceControl( m_pDetailsViewChild, m_nNumAttribLinesAdded == 0 ? "PriceLabel" : "AttributesLabel", "ItemWikiPageButton", m_iBigVerticalBreakSize, true ); |
|
|
|
PlaceControl( m_pDetailsViewChild, "ItemWikiPageButton", "TradableLabel", m_iBigVerticalBreakSize, true, false, false ); |
|
PlaceControl( m_pDetailsViewChild, "TradableLabel", "TradableTextLabel", m_iHorizontalBreakSize, false ); |
|
PlaceControl( m_pDetailsViewChild, "TradableLabel", "CraftableLabel", m_iSmallVerticalBreakSize, true ); |
|
PlaceControl( m_pDetailsViewChild, "CraftableLabel", "CraftableTextLabel", m_iHorizontalBreakSize, false ); |
|
PlaceControl( m_pDetailsViewChild, "CraftableLabel", "GiftableLabel", m_iSmallVerticalBreakSize, true ); |
|
PlaceControl( m_pDetailsViewChild, "GiftableLabel", "GiftableTextLabel", m_iHorizontalBreakSize, false ); |
|
PlaceControl( m_pDetailsViewChild, "GiftableLabel", "NameableLabel", m_iSmallVerticalBreakSize, true ); |
|
PlaceControl( m_pDetailsViewChild, "NameableLabel", "NameableTextLabel", m_iHorizontalBreakSize, false ); |
|
|
|
if ( m_pScrollBar ) |
|
{ |
|
m_pScrollBar->SetVisible( true ); |
|
m_pScrollBar->InvalidateLayout( true ); |
|
m_pScrollBar->SetRange( 0, m_nViewMaxHeight ); |
|
m_pScrollBar->SetRangeWindow( m_pScrollBar->GetTall() ); |
|
|
|
m_pDetailsViewChild->SetTall( m_nViewMaxHeight ); |
|
UpdateScrollableChild(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::UpdateScrollableChild() |
|
{ |
|
m_pDetailsViewChild->SetPos( 0, -m_iSliderPos ); |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnCommand( const char *command ) |
|
{ |
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "on_command(store_preview_item_panel)", command ); |
|
|
|
if ( !V_strnicmp( command, "closex", 5 ) ) |
|
{ |
|
// This is just a way for us to differentiate between 'x' button being pressed vs. |
|
// the "back" button vs. clicking outside the preview window. |
|
DoClose(); |
|
} |
|
else if ( !V_strnicmp( command, "tryitout", 8 ) ) |
|
{ |
|
// OGS data gets written elsewhere for this event |
|
PostMessage( m_pOwner, new KeyValues( "PreviewItem", "item_def_index", m_item.GetItemDefIndex() ) ); |
|
DoClose(); |
|
} |
|
else if ( !V_strnicmp( command, "addtocart", 9 ) |
|
#ifdef ENABLE_STORE_RENTAL_BACKEND |
|
|| !V_strnicmp( command, "addrentaltocart", 15 ) |
|
#endif |
|
) |
|
{ |
|
#ifdef ENABLE_STORE_RENTAL_BACKEND |
|
ECartItemType eCartItemType = !V_stricmp( command, "addrentaltocart_1day" ) |
|
? kCartItem_Rental_1Day |
|
: !V_stricmp( command, "addrentaltocart_3day" ) |
|
? kCartItem_Rental_3Day |
|
: !V_stricmp( command, "addrentaltocart_7day" ) |
|
? kCartItem_Rental_7Day |
|
: kCartItem_Purchase; |
|
#else |
|
ECartItemType eCartItemType = kCartItem_Purchase; |
|
#endif |
|
|
|
KeyValues *pParams = new KeyValues( "AddItemToCart" ); |
|
pParams->SetInt( "item_def", m_item.GetItemDefIndex() ); |
|
pParams->SetInt( "cart_add_type", eCartItemType ); |
|
PostMessage( m_pOwner, pParams ); |
|
DoClose(); |
|
} |
|
else if ( !V_strnicmp( command, "viewwikipage", 12 ) ) |
|
{ |
|
if ( steamapicontext && steamapicontext->SteamFriends() && m_pItemFullImage ) |
|
{ |
|
CEconItemView *pItem = m_pItemFullImage->GetItem(); |
|
if ( pItem->IsValid() ) |
|
{ |
|
// Determine which language we should use |
|
char uilanguage[ 64 ]; |
|
uilanguage[0] = 0; |
|
engine->GetUILanguage( uilanguage, sizeof( uilanguage ) ); |
|
ELanguage iLang = PchLanguageToELanguage( uilanguage ); |
|
|
|
char szURL[512]; |
|
Q_snprintf( szURL, sizeof(szURL), "http://wiki.teamfortress.com/scripts/itemredirect.php?id=%d&lang=%s", pItem->GetItemDefIndex(), GetLanguageICUName( iLang ) ); |
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( szURL ); |
|
|
|
C_CTF_GameStats.Event_Catalog( IE_ARMORY_BROWSE_WIKI, NULL, pItem ); |
|
} |
|
} |
|
} |
|
else if ( !V_strnicmp( command, "team_", 5 ) ) |
|
{ |
|
const char *pTeam = command + 5; |
|
if ( !V_strnicmp( pTeam, "red", 3 ) ) |
|
{ |
|
m_pPlayerModelPanel->SetTeam( TF_TEAM_RED ); |
|
} |
|
else |
|
{ |
|
m_pPlayerModelPanel->SetTeam( TF_TEAM_BLUE ); |
|
} |
|
} |
|
else if ( !V_strnicmp( command, "gofullscreen", 11 ) ) |
|
{ |
|
if ( m_pFullscreenPanel ) |
|
{ |
|
m_pFullscreenPanel->GoFullscreen( m_pPlayerModelPanel ); |
|
} |
|
} |
|
else |
|
{ |
|
BaseClass::OnCommand( command ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnClassIconSelected( KeyValues *data ) |
|
{ |
|
BaseClass::OnClassIconSelected( data ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnHideClassIconMouseover( void ) |
|
{ |
|
BaseClass::OnHideClassIconMouseover(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnShowClassIconMouseover( KeyValues *data ) |
|
{ |
|
// We decided not to show the "this item is |
|
// usable by the [Class name]" tooltip. |
|
//BaseClass::OnShowClassIconMouseover( data ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::PreviewItemCopy( int iClass, CEconItemView *pItem, const econ_store_entry_t* pEntry ) |
|
{ |
|
// Make a copy of SO data since it comes from the market and will fall out of scope |
|
if ( m_pItemViewData ) |
|
{ |
|
delete m_pItemViewData; |
|
m_pItemViewData = NULL; |
|
} |
|
|
|
if ( m_pSOEconItemData ) |
|
{ |
|
delete m_pSOEconItemData; |
|
m_pSOEconItemData = NULL; |
|
} |
|
|
|
m_pItemViewData = new CEconItemView( *pItem ); |
|
m_pSOEconItemData = new CEconItem( *pItem->GetSOCData() ); |
|
m_pItemViewData->SetNonSOEconItem( m_pSOEconItemData ); |
|
PreviewItem( iClass, m_pItemViewData, pEntry ); |
|
} |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::PreviewItem( int iClass, CEconItemView *pItem, const econ_store_entry_t* pEntry ) |
|
{ |
|
BaseClass::PreviewItem( iClass, pItem, pEntry ); |
|
|
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_preview_item_panel(preview_item)", CFmtStr( "%i", m_item.GetItemDefIndex() ).Access() ); |
|
|
|
// Reload the .res file right now, since we need to make sure the item name label, on which all other controls |
|
// base their position, is valid. |
|
InvalidateLayout( true, true ); |
|
|
|
// Update the fullscreen item def index |
|
if ( m_pFullscreenPanel ) |
|
{ |
|
m_pFullscreenPanel->SetItemDef( m_item.GetItemDefIndex() ); |
|
} |
|
|
|
// If we didn't have a store entry passed in, look for one. |
|
if ( !pEntry ) |
|
{ |
|
CStorePanel *pStorePanel = EconUI()->GetStorePanel(); |
|
if ( pStorePanel ) |
|
{ |
|
pEntry = pStorePanel->GetPriceSheet()->GetEntry( m_item.GetItemDefIndex() ); |
|
} |
|
} |
|
|
|
if ( m_pDialogFrame && m_pDetailsView && m_pItemFullImage && m_pItemFullImage->GetItem() && m_pAttributesLabel ) |
|
{ |
|
const CEconItemView *pFullItem = m_pItemFullImage->GetItem(); |
|
const CEconItemDefinition *pBaseDef = pFullItem->GetItemDefinition(); |
|
const CTFItemDefinition *pDef = dynamic_cast<const CTFItemDefinition *>( pBaseDef ); |
|
|
|
if ( pFullItem && pDef ) |
|
{ |
|
m_pDialogFrame->SetDialogVariable( "itemname", pFullItem->GetItemName() ); |
|
|
|
// Holiday restrictions? |
|
const char *pHolidayRestriction = pDef->GetHolidayRestriction() ? pDef->GetHolidayRestriction() : ""; |
|
m_bIsHalloweenOrFullmoonOnlyItem = StringHasPrefix( pHolidayRestriction, "halloween" ); |
|
|
|
CTFItemSchema *pSchema = ItemSystem()->GetItemSchema(); |
|
if ( pSchema ) |
|
{ |
|
// Build a list of classes by which this item can be used |
|
const CBitVec<LOADOUT_COUNT> *pbvClassUsability = pDef->GetClassUsability(); |
|
|
|
const int kClassNamesSize = 512; |
|
wchar_t wszClassNames[ kClassNamesSize ] = L""; |
|
int nClassAdded = 0; |
|
bool bAllClasses = true; |
|
for ( int i = TF_FIRST_NORMAL_CLASS; i < TF_LAST_NORMAL_CLASS; ++i ) |
|
{ |
|
if ( !pbvClassUsability->IsBitSet( i ) ) |
|
{ |
|
bAllClasses = false; |
|
break; |
|
} |
|
} |
|
|
|
if ( bAllClasses ) |
|
{ |
|
m_pDetailsViewChild->SetDialogVariable( "used_by_classes", g_pVGuiLocalize->Find( "#Store_ItemDesc_AllClasses" ) ); |
|
} |
|
else |
|
{ |
|
for ( int i = 0; i < LOADOUT_COUNT; ++i ) |
|
{ |
|
if ( pbvClassUsability->IsBitSet( i ) ) |
|
{ |
|
V_wcscat_safe( wszClassNames, nClassAdded++ == 0 ? L"" : L", " ); // add empty lines everywhere except before the first line |
|
V_wcscat_safe( wszClassNames, g_pVGuiLocalize->Find( g_aPlayerClassNames[i] ) ); |
|
} |
|
} |
|
m_pDetailsViewChild->SetDialogVariable( "used_by_classes", wszClassNames ); |
|
} |
|
|
|
// Setup the slot string |
|
const CUtlVector< const char * > &vecLoadoutStrings = pSchema->GetLoadoutStrings( pDef->GetEquipType() ); |
|
const int iSlot = pDef->GetDefaultLoadoutSlot(); |
|
const bool bSlotValid = vecLoadoutStrings.IsValidIndex( iSlot ); |
|
m_pDetailsViewChild->SetDialogVariable( "slot", g_pVGuiLocalize->Find( bSlotValid ? CFmtStr( "#LoadoutSlot_%s", vecLoadoutStrings[iSlot] ).Access() : "#Store_ItemDesc_Slot_None" ) ); |
|
|
|
// Make an attempt to display tradability accurately even though we don't have an item to pull from. |
|
static CSchemaAttributeDefHandle pAttrib_CannotTrade( "cannot trade" ); |
|
Assert( pAttrib_CannotTrade ); |
|
|
|
// Get localized versions of "yes" and "no" |
|
const wchar_t *pYesNo[2] = { |
|
g_pVGuiLocalize->Find( "#Store_ItemDesc_Yes" ), |
|
g_pVGuiLocalize->Find( "#Store_ItemDesc_No" ) |
|
}; |
|
bool bIsMapStamp = pDef->GetItemClass() && !V_strncmp( pDef->GetItemClass(), "map_token", 9 ); |
|
bool bIsTradeable = bIsMapStamp || FindAttribute( pDef, pAttrib_CannotTrade ) |
|
? pYesNo[ 1 ] |
|
: g_pVGuiLocalize->Find( "#Attrib_Store_TradableAfterDate" ); |
|
|
|
m_pDetailsViewChild->SetDialogVariable( "giftable", bIsTradeable ); |
|
m_pDetailsViewChild->SetDialogVariable( "nameable", ( pDef->GetCapabilities() & ITEM_CAP_NAMEABLE ) != 0 ? pYesNo[0] : pYesNo[1] ); |
|
|
|
m_pDetailsViewChild->SetDialogVariable( "tradable", bIsTradeable ); |
|
|
|
// No store-bought items are craftable, but items that were going to be tradable would show as craftable because |
|
// they weren't real items with a real origin that would prevent them from being crafted. In the short term it makes |
|
// more sense to just force this to always display "false" because at least it will never be wrong. |
|
m_pDetailsViewChild->SetDialogVariable( "craftable", pDef->IsBundle() |
|
? g_pVGuiLocalize->Find( "#Attrib_CannotCraftWeapons" ) |
|
: pDef->GetCapabilities() & ITEM_CAP_CAN_BE_CRAFTED_IF_PURCHASED |
|
? pYesNo[0] |
|
: pYesNo[1] ); |
|
|
|
// Setup price |
|
if ( pEntry ) |
|
{ |
|
ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency(); |
|
|
|
int iTotalPrice = pEntry->GetCurrentPrice( eCurrency ); |
|
wchar_t wzLocalizedPrice[ kLocalizedPriceSizeInChararacters ]; |
|
MakeMoneyString( wzLocalizedPrice, ARRAYSIZE( wzLocalizedPrice ), iTotalPrice, eCurrency ); |
|
|
|
#ifdef ENABLE_STORE_RENTAL_BACKEND |
|
const wchar_t *pwsRentalPriceFormat = GLocalizationProvider()->Find( "#TF_Store_RentalPriceFormat" ); |
|
if ( pEntry->IsRentable() && pwsRentalPriceFormat ) |
|
{ |
|
wchar_t wzRentalLocalizedPrice[ kLocalizedPriceSizeInChararacters ]; |
|
MakeMoneyString( wzRentalLocalizedPrice, ARRAYSIZE( wzRentalLocalizedPrice ), pEntry->GetRentalPriceScale() * iTotalPrice, eCurrency ) |
|
|
|
wchar_t wzLocalizedPriceString[96]; |
|
::ILocalize::ConstructString_safe( wzLocalizedPriceString, pwsRentalPriceFormat, 2, wzLocalizedPrice, wzRentalLocalizedPrice ); |
|
m_pDetailsViewChild->SetDialogVariable( "price", wzLocalizedPriceString ); |
|
} |
|
else |
|
#endif |
|
{ |
|
if ( pEntry->m_bIsMarketItem ) |
|
{ |
|
if ( iTotalPrice != 0 ) |
|
{ |
|
wchar_t wzMarketString[96]; |
|
g_pVGuiLocalize->ConstructString_safe( |
|
wzMarketString, |
|
LOCCHAR( "%s1 %s2" ), |
|
2, |
|
g_pVGuiLocalize->Find( "#Store_StartingAt" ), |
|
wzLocalizedPrice ); |
|
|
|
m_pDetailsViewChild->SetDialogVariable( "price", wzMarketString ); |
|
} |
|
else |
|
{ |
|
m_pDetailsViewChild->SetDialogVariable( "price", "..." ); |
|
} |
|
} |
|
else |
|
{ |
|
// if market item. Prefix 'Starting at' |
|
m_pDetailsViewChild->SetDialogVariable( "price", wzLocalizedPrice ); |
|
} |
|
} |
|
} |
|
|
|
// Show/hide rental button. |
|
for ( int i = 0; i < ARRAYSIZE( m_pAddRentalToCartButtons ); i++ ) |
|
{ |
|
if ( m_pAddRentalToCartButtons[i] ) |
|
{ |
|
m_pAddRentalToCartButtons[i]->SetVisible( pEntry && pEntry->IsRentable() ); |
|
} |
|
} |
|
} |
|
|
|
// Final label value for our armory description text block. |
|
const wchar_t *pwszLabelValue = L""; |
|
m_bArmoryTextAdded = false; |
|
|
|
const char *pszArmoryDescString = pDef->GetArmoryDescString(); |
|
if ( pszArmoryDescString ) |
|
{ |
|
const ArmoryStringDict_t& ArmoryKeys = GetItemSchema()->GetArmoryDataItems(); |
|
const ArmoryStringDict_t::IndexType_t armoryIndex = ArmoryKeys.Find( pszArmoryDescString ); |
|
|
|
if ( ArmoryKeys.IsValidIndex( armoryIndex ) ) |
|
{ |
|
const char *pszArmoryDescLocalizationKey = ArmoryKeys[ armoryIndex ].Get(); |
|
|
|
pwszLabelValue = g_pVGuiLocalize->Find( pszArmoryDescLocalizationKey ); |
|
m_bArmoryTextAdded = true; |
|
} |
|
} |
|
|
|
m_pDetailsViewChild->SetDialogVariable( "armory_text", pwszLabelValue ); |
|
} |
|
|
|
// clear all old reference item panels before adding new ones |
|
FOR_EACH_VEC( m_vecReferenceItemPanels, i ) |
|
{ |
|
m_vecReferenceItemPanels[i]->MarkForDeletion(); |
|
} |
|
m_vecReferenceItemPanels.RemoveAll(); |
|
int iReferenceItemHeight = 0; |
|
|
|
const CEconItemDescription *pDescription = m_pItemFullImage->GetItem()->GetDescription(); |
|
if ( pDescription ) |
|
{ |
|
TextImage *pAttributesTextImage = m_pAttributesLabel->GetTextImage(); // This pointer already verified above |
|
pAttributesTextImage->ClearColorChangeStream(); |
|
|
|
const int kAttribBufferSize = 4 * 1024; |
|
wchar_t wszAttribBuffer[ kAttribBufferSize ] = L""; |
|
|
|
int iAttribLine = 0; |
|
m_nNumAttribLinesAdded = 0; |
|
Color clrPrev( 0, 0, 0, 0 ); |
|
uint32 unCurrentTextStreamIndex = 0; |
|
IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); |
|
int iFontHeight = surface()->GetFontTall( m_pAttributesLabel->GetFont() ); |
|
|
|
if ( m_pItemCollectionHighlight ) |
|
{ |
|
m_pItemCollectionHighlight->SetVisible( false ); |
|
} |
|
|
|
iReferenceItemHeight = iFontHeight; |
|
|
|
int iAttributePanelX, iAttributePanelY; |
|
m_pAttributesLabel->GetPos( iAttributePanelX, iAttributePanelY ); |
|
|
|
for ( uint32 i = 0; i < pDescription->GetLineCount(); ++i ) |
|
{ |
|
const econ_item_description_line_t& line = pDescription->GetLine(i); |
|
int nLineLength = StringFuncs<locchar_t>::Length( line.sText.Get() ); |
|
if ( ( line.unMetaType & kDescLineFlag_Type ) != 0 ) |
|
{ |
|
m_pDetailsViewChild->SetDialogVariable( "item_level_info", line.sText.Get() ); |
|
} |
|
else if ( ( line.unMetaType & kDescLineFlagSet_DisplayInAttributeBlock ) != 0 && m_pAttributesLabel ) |
|
{ |
|
++iAttribLine; |
|
|
|
// current collection item line |
|
bool bIsCurrentCollectionItem = ( line.unMetaType & kDescLineFlag_CollectionCurrentItem ) != 0; |
|
// use bg color as text color for current item for a better highlight |
|
Color col = bIsCurrentCollectionItem ? Color( 0, 0, 0, 255 ) : pScheme->GetColor( GetColorNameForAttribColor( line.eColor ), Color( 255, 255, 255, 255 ) ); |
|
|
|
// Output a color change if necessary. |
|
if ( i == 0 || clrPrev != col ) |
|
{ |
|
pAttributesTextImage->AddColorChange( col, unCurrentTextStreamIndex ); |
|
clrPrev = col; |
|
} |
|
|
|
// Current line highlight |
|
if ( bIsCurrentCollectionItem && m_pItemCollectionHighlight ) |
|
{ |
|
// use text color as bg color for the current item for a better highlight |
|
Color bgColor = pScheme->GetColor( GetColorNameForAttribColor( line.eColor ), Color( 255, 255, 255, 255 ) ); |
|
|
|
// Get the current ypos |
|
int x, y; |
|
m_pAttributesLabel->GetPos( x, y ); |
|
m_pItemCollectionHighlight->SetPos( x, y + ( iAttribLine - 1 ) * iFontHeight ); |
|
m_pItemCollectionHighlight->SetBgColor( bgColor ); |
|
m_pItemCollectionHighlight->SetVisible( bIsCurrentCollectionItem ); |
|
} |
|
|
|
if ( ( line.unMetaType & ( kDescLineFlag_Name | kDescLineFlag_Type ) ) == 0 ) |
|
{ |
|
V_wcscat_safe( wszAttribBuffer, m_nNumAttribLinesAdded++ == 0 ? L"" : L"\n" ); // add empty lines everywhere except before the first line |
|
V_wcscat_safe( wszAttribBuffer, line.sText.Get() ); |
|
unCurrentTextStreamIndex += nLineLength + 1; // add one character to deal with newlines |
|
} |
|
|
|
if ( line.unDefIndex != INVALID_ITEM_DEF_INDEX ) |
|
{ |
|
// set text and recalculate the size now to compute for button pos |
|
m_pAttributesLabel->SetText( wszAttribBuffer ); |
|
m_pAttributesLabel->SizeToContents(); |
|
|
|
CItemModelPanel* pItemModelPanel = new CItemModelPanel( m_pAttributesLabel, CFmtStr( "reference_item_%d", m_vecReferenceItemPanels.Count() ) ); |
|
pItemModelPanel->SetActAsButton( true, true ); |
|
pItemModelPanel->SetAutoDelete( true ); |
|
|
|
pItemModelPanel->SetPos( 0, m_pAttributesLabel->GetTall() - iFontHeight ); |
|
pItemModelPanel->SetZPos( m_pAttributesLabel->GetZPos() + 1 ); |
|
|
|
CEconItemView itemData; |
|
itemData.Init( line.unDefIndex, AE_UNIQUE, AE_USE_SCRIPT_VALUE, true ); |
|
itemData.SetClientItemFlags( kEconItemFlagClient_Preview ); |
|
pItemModelPanel->SetItem( &itemData ); |
|
pItemModelPanel->MakeFakeButton(); |
|
|
|
pItemModelPanel->SetTooltip( m_pMouseOverTooltip, "" ); |
|
|
|
m_vecReferenceItemPanels.AddToTail( pItemModelPanel ); |
|
} |
|
} |
|
} |
|
|
|
// Make sure our string is NUL-terminated. |
|
wszAttribBuffer[ kAttribBufferSize-1 ] = 0; |
|
|
|
m_pAttributesLabel->SetText( wszAttribBuffer ); |
|
} |
|
|
|
// match the highlight width to attribute width |
|
if ( m_pItemCollectionHighlight && m_pItemCollectionHighlight->IsVisible() ) |
|
{ |
|
m_pAttributesLabel->SizeToContents(); |
|
m_pItemCollectionHighlight->SetWide( m_pAttributesLabel->GetWide() ); |
|
} |
|
|
|
if ( m_vecReferenceItemPanels.Count() ) |
|
{ |
|
m_pAttributesLabel->SizeToContents(); |
|
FOR_EACH_VEC( m_vecReferenceItemPanels, i ) |
|
{ |
|
m_vecReferenceItemPanels[i]->SetSize( m_pAttributesLabel->GetWide(), iReferenceItemHeight ); |
|
} |
|
} |
|
|
|
// Get PerformLayout() called, now that we have text in our controls - without this, SizeToContents() sizes all the labels as tall and narrow. |
|
InvalidateLayout( true ); |
|
} |
|
|
|
// Set the visibility of the "Try it now!" button based on whether we as a client think this item should be able |
|
// to be previewed. |
|
const CEconStorePriceSheet *pPriceSheet = EconUI()->GetStorePanel()->GetPriceSheet(); |
|
if ( pPriceSheet && m_pPreviewButton ) |
|
{ |
|
const econ_store_entry_t *pStoreEntry = pPriceSheet->GetEntry( m_item.GetItemDefIndex() ); |
|
m_pPreviewButton->SetVisible( pStoreEntry && pStoreEntry->CanPreview() ); |
|
} |
|
|
|
m_pItemFullImage->InvalidateLayout(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::SetState( preview_state_t iState ) |
|
{ |
|
BaseClass::SetState( iState ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::UpdateIcons( void ) |
|
{ |
|
BaseClass::UpdateIcons(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::UpdatePlayerModelButtons() |
|
{ |
|
BaseClass::UpdatePlayerModelButtons(); |
|
|
|
if ( m_pPlayerModelPanel ) |
|
{ |
|
if ( m_pTeamNavPanel ) |
|
{ |
|
m_pTeamNavPanel->SetVisible( m_pPlayerModelPanel->IsVisible() ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::SetPlayerModelVisible( bool bVisible ) |
|
{ |
|
BaseClass::SetPlayerModelVisible( bVisible ); |
|
|
|
if ( m_pCycleTextLabel ) |
|
{ |
|
m_pCycleTextLabel->SetVisible( bVisible ); |
|
} |
|
|
|
if ( m_pGoFullscreenButton ) |
|
{ |
|
m_pGoFullscreenButton->SetVisible( bVisible ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::SetCycleLabelText( vgui::Label *pTargetLabel, const char *pCycleText ) |
|
{ |
|
BaseClass::SetCycleLabelText( pTargetLabel, pCycleText ); |
|
|
|
if ( m_pCycleTextLabel ) |
|
{ |
|
const wchar_t *pwszText = g_pVGuiLocalize->Find( pCycleText ); |
|
m_pCycleTextLabel->SetText( pwszText ? pwszText : L"" ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnNavButtonSelected( KeyValues *pData ) |
|
{ |
|
const int iTeam = pData->GetInt( "userdata", -1 ); AssertMsg( iTeam >= 0, "Bad filter" ); |
|
if ( iTeam < 0 ) |
|
return; |
|
|
|
if ( !m_pPlayerModelPanel ) |
|
return; |
|
|
|
m_pPlayerModelPanel->SetTeam( iTeam ); |
|
CyclePaint( false ); |
|
|
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "team_switch(store_preview_item_panel)", iTeam == TF_TEAM_RED ? "red" : "blu" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnExitFullscreen( KeyValues *pData ) |
|
{ |
|
if ( !m_pPlayerModelPanel ) |
|
return; |
|
|
|
// If team or class changed in fullscreen mode, update our ui components here |
|
if ( m_pTeamNavPanel ) |
|
{ |
|
m_pTeamNavPanel->UpdateButtonSelectionStates( m_pPlayerModelPanel->GetTeam() == TF_TEAM_RED ? 0 : 1 ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnTick( void ) |
|
{ |
|
BaseClass::OnTick(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnMouseWheeled( int delta ) |
|
{ |
|
if ( !m_pScrollBar ) |
|
return; |
|
|
|
int val = m_pScrollBar->GetValue(); |
|
val -= (delta * 50); |
|
m_pScrollBar->SetValue( val ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnSliderMoved( int position ) |
|
{ |
|
m_iSliderPos = position; |
|
UpdateScrollableChild(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::OnThink() |
|
{ |
|
BaseClass::OnThink(); |
|
|
|
Assert( IsVisible() ); |
|
|
|
// If the user clicks outside of the dialog frame, close the preview, like |
|
// many web sites do on the internet. |
|
bool bMouseDown = vgui::input()->IsMouseDown( MOUSE_LEFT ); |
|
|
|
// User just clicked? |
|
if ( !m_pFullscreenPanel || !m_pFullscreenPanel->IsFullscreenMode() ) |
|
{ |
|
if ( !m_bMouseWasDown && bMouseDown ) |
|
{ |
|
vgui::input()->GetCursorPos( m_aClickPos[0], m_aClickPos[1] ); |
|
m_bMouseWasDown = true; |
|
} |
|
else if ( m_pDialogFrame && bMouseDown && !m_pDialogFrame->IsWithin( m_aClickPos[0], m_aClickPos[1] ) ) |
|
{ |
|
//m_bCloseOnUp = true; |
|
} |
|
else if ( !bMouseDown ) |
|
{ |
|
if ( m_bCloseOnUp ) |
|
{ |
|
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_preview_item_panel", "close_from_outside_click" ); |
|
|
|
DoClose(); |
|
} |
|
m_bCloseOnUp = false; |
|
m_bMouseWasDown = false; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFStorePreviewItemPanel2::DoClose() |
|
{ |
|
if ( m_pFullscreenPanel ) |
|
{ |
|
m_pFullscreenPanel->ExitFullscreen(); |
|
} |
|
|
|
OnClose(); |
|
|
|
SetVisible( false ); |
|
}
|
|
|