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.
1183 lines
37 KiB
1183 lines
37 KiB
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
|
|
#include "cbase.h"
|
|
#include "store/tf_store_preview_item_base.h"
|
|
#include "store/store_page.h"
|
|
#include "vgui/ISurface.h"
|
|
#include "vgui/IInput.h"
|
|
#include "vgui/ILocalize.h"
|
|
#include "gamestringpool.h"
|
|
#include "tf_item_inventory.h"
|
|
#include "tf_playermodelpanel.h"
|
|
#include "econ_item_system.h"
|
|
#include "item_model_panel.h"
|
|
#include "c_tf_gamestats.h"
|
|
#include "econ_ui.h"
|
|
#include "econ_item_tools.h"
|
|
#include "vgui_controls/MenuItem.h"
|
|
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include <tier0/memdbgon.h>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
CTFStorePreviewItemPanelBase::CTFStorePreviewItemPanelBase( vgui::Panel *pParent, const char *pResFile, const char *pPanelName, CStorePage *pOwner )
|
|
: CStorePreviewItemPanel( pParent, pResFile, "storepreviewitem", pOwner )
|
|
{
|
|
ResetHandles();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::ResetHandles( void )
|
|
{
|
|
m_pPlayerModelPanel = NULL;
|
|
m_iCurrentClass = TF_CLASS_SCOUT;
|
|
m_iCurrentHeldItem = 0;
|
|
m_pClassIconMouseoverLabel = NULL;
|
|
m_pRotRightButton = NULL;
|
|
m_pRotLeftButton = NULL;
|
|
m_pNextWeaponButton = NULL;
|
|
m_pZoomButton = NULL;
|
|
m_pOptionsButton = NULL;
|
|
m_pTeamButton = NULL;
|
|
m_pDataTextRichText = NULL;
|
|
m_iCurrentIconPosition = 0;
|
|
m_iState = PS_ITEM;
|
|
m_unPaintDef = 0;
|
|
m_unPaintRGB0 = 0;
|
|
m_unPaintRGB1 = 0;
|
|
m_pPaintNameLabel = NULL;
|
|
m_pStyleNameLabel = NULL;
|
|
m_pCustomizeMenu = NULL;
|
|
m_pClassIcons.Purge();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::SetCycleLabelText( vgui::Label *pTargetLabel, const char *pCycleText )
|
|
{
|
|
if ( pTargetLabel )
|
|
{
|
|
pTargetLabel->SetText( pCycleText );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::ApplySchemeSettings( vgui::IScheme *pScheme )
|
|
{
|
|
ResetHandles();
|
|
|
|
BaseClass::ApplySchemeSettings( pScheme );
|
|
|
|
m_pPlayerModelPanel = dynamic_cast<CTFPlayerModelPanel*>( FindChildByName("classmodelpanel") );
|
|
m_pClassIconMouseoverLabel = dynamic_cast<vgui::Label*>( FindChildByName("ClassUsageMouseoverLabel") );
|
|
m_pRotRightButton = dynamic_cast<CExButton*>( FindChildByName("RotRightButton") );
|
|
m_pRotLeftButton = dynamic_cast<CExButton*>( FindChildByName("RotLeftButton") );
|
|
m_pNextWeaponButton = dynamic_cast<CExButton*>( FindChildByName("NextWeaponButton") );
|
|
m_pZoomButton = dynamic_cast<CExButton*>( FindChildByName("ZoomButton") );
|
|
m_pOptionsButton = dynamic_cast<CExButton*>( FindChildByName("OptionsButton") );
|
|
m_pTeamButton = dynamic_cast<CExButton*>( FindChildByName("TeamButton") );
|
|
m_pPaintNameLabel = dynamic_cast<vgui::Label*>( FindChildByName("PaintNameLabel") );
|
|
m_pStyleNameLabel = dynamic_cast<vgui::Label*>( FindChildByName("StyleNameLabel") );
|
|
|
|
if ( m_pClassIconMouseoverLabel )
|
|
{
|
|
m_pClassIconMouseoverLabel->SetVisible( false );
|
|
}
|
|
|
|
// Find all the class images
|
|
CStorePreviewClassIcon *pClassImage = NULL;
|
|
int iIcon = 1;
|
|
do
|
|
{
|
|
pClassImage = dynamic_cast<CStorePreviewClassIcon*>( FindChildByName( VarArgs("ClassUsageImage%d",iIcon)) );
|
|
if ( pClassImage )
|
|
{
|
|
m_pClassIcons.AddToTail( pClassImage );
|
|
}
|
|
iIcon++;
|
|
} while ( pClassImage );
|
|
|
|
// Update our class icons. Hide them all first. The code below will unhide ones used.
|
|
for ( int i = 0; i < m_pClassIcons.Count(); i++ )
|
|
{
|
|
m_pClassIcons[i]->SetVisible( false );
|
|
}
|
|
|
|
SetState( PS_ITEM );
|
|
|
|
m_vecPaintCans.Purge();
|
|
const CEconItemSchema::ToolsItemDefinitionMap_t &toolDefs = GetItemSchema()->GetToolsItemDefinitionMap();
|
|
|
|
// Store all of the active paint can item defs
|
|
FOR_EACH_MAP_FAST( toolDefs, i )
|
|
{
|
|
const CEconItemDefinition *pItemDef = toolDefs[i];
|
|
|
|
// ignore everything that is not a paint can tool
|
|
const IEconTool *pEconTool = pItemDef->GetEconTool();
|
|
if ( pEconTool && !V_strcmp( pEconTool->GetTypeName(), "paint_can" ) )
|
|
{
|
|
m_vecPaintCans.AddToTail( pItemDef->GetDefinitionIndex() );
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::PerformLayout( void )
|
|
{
|
|
BaseClass::PerformLayout();
|
|
|
|
// 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 ( iNumItemIcons || iNumClassIcons )
|
|
{
|
|
int iCenterX = GetWide() / 2;
|
|
int interval = XRES(2);
|
|
int totalWidth = (iNumItemIcons * m_pItemIcons[0]->GetWide()) + (iNumClassIcons * m_pClassIcons[0]->GetWide()) + (interval * (iNumItemIcons + iNumClassIcons - 1));
|
|
int iX = iCenterX - ( totalWidth / 2 );
|
|
|
|
int posX, posY;
|
|
m_pItemIcons[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++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
static bool IsAnythingPaintable( const CUtlVector<CEconItemView*>& vecItems )
|
|
{
|
|
FOR_EACH_VEC( vecItems, i )
|
|
{
|
|
if ( vecItems[i]->GetStaticData()->GetCapabilities() & ITEM_CAP_PAINTABLE )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
static void UpdatePaintColorsForTeam( CTFPlayerModelPanel *pPlayerModelPanel, uint32 unRGB0, uint32 unRGB1 )
|
|
{
|
|
Assert( pPlayerModelPanel );
|
|
|
|
static CSchemaAttributeDefHandle pAttrDef_ItemTintRGB( "set item tint RGB" );
|
|
|
|
if ( !pAttrDef_ItemTintRGB )
|
|
return;
|
|
|
|
const CUtlVector<CEconItemView*> &items = pPlayerModelPanel->GetCarriedItems();
|
|
if ( !IsAnythingPaintable( items ) )
|
|
return;
|
|
|
|
for ( int i=0; i<items.Count(); ++i )
|
|
{
|
|
if ( items[i]->GetStaticData()->GetCapabilities() & ITEM_CAP_PAINTABLE )
|
|
{
|
|
items[i]->GetAttributeList()->SetRuntimeAttributeValue( pAttrDef_ItemTintRGB, pPlayerModelPanel->GetTeam() == TF_TEAM_RED ? unRGB0 : unRGB1 );
|
|
items[i]->InvalidateColor();
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::OnCommand( const char *command )
|
|
{
|
|
if ( !Q_strnicmp( command, "team_toggle", 11 ) )
|
|
{
|
|
if ( m_pPlayerModelPanel )
|
|
{
|
|
m_pPlayerModelPanel->SetTeam( m_pPlayerModelPanel->GetTeam() == TF_TEAM_RED ? TF_TEAM_BLUE : TF_TEAM_RED );
|
|
}
|
|
|
|
// Also toggle team paint color if necessary.
|
|
if ( m_unPaintRGB0 != m_unPaintRGB1 )
|
|
{
|
|
UpdatePaintColorsForTeam( m_pPlayerModelPanel, m_unPaintRGB0, m_unPaintRGB1 );
|
|
}
|
|
}
|
|
else if ( !Q_strnicmp( command, "zoom_toggle", 11 ) )
|
|
{
|
|
if ( m_pPlayerModelPanel )
|
|
{
|
|
m_pPlayerModelPanel->ToggleZoom();
|
|
}
|
|
}
|
|
else if ( !Q_strnicmp( command, "paint_toggle", 12 ) )
|
|
{
|
|
CyclePaint();
|
|
}
|
|
else if ( !Q_strnicmp( command, "set_red", 7 ) )
|
|
{
|
|
if ( m_pPlayerModelPanel )
|
|
{
|
|
m_pPlayerModelPanel->SetSkin( 0 );
|
|
}
|
|
return;
|
|
}
|
|
else if ( !Q_strnicmp( command, "set_blu", 7 ) )
|
|
{
|
|
if ( m_pPlayerModelPanel )
|
|
{
|
|
m_pPlayerModelPanel->SetSkin( 1 );
|
|
}
|
|
return;
|
|
}
|
|
else if ( !Q_strnicmp( command, "next_weapon", 11 ) )
|
|
{
|
|
if ( m_pPlayerModelPanel )
|
|
{
|
|
const CUtlVector<CEconItemView*> &items = m_pPlayerModelPanel->GetCarriedItems();
|
|
int iLastItem = m_iCurrentHeldItem;
|
|
do
|
|
{
|
|
m_iCurrentHeldItem = ( m_iCurrentHeldItem + 1 ) % items.Count();
|
|
} while ( m_iCurrentHeldItem != iLastItem && m_pPlayerModelPanel->HoldItem( m_iCurrentHeldItem ) == false );
|
|
}
|
|
m_pPlayerModelPanel->SetTeam( m_pPlayerModelPanel->GetTeam() );
|
|
return;
|
|
}
|
|
else if ( !Q_strnicmp( command, "next_style", 10 ) )
|
|
{
|
|
CycleStyle();
|
|
return;
|
|
}
|
|
else if ( V_strncasecmp( command, "SetPaint", V_strlen( "SetPaint" ) ) == 0 )
|
|
{
|
|
item_definition_index_t iItemDef = V_atoi( &command[ V_strlen( "SetPaint" ) ] );
|
|
SetPaint( iItemDef );
|
|
}
|
|
else if ( V_strncasecmp( command, "SetStyle", V_strlen( "SetStyle" ) ) == 0 )
|
|
{
|
|
style_index_t unStyle = V_atoi( &command[ V_strlen( "SetStyle" ) ] );
|
|
SetStyle( unStyle );
|
|
}
|
|
else if ( V_strncasecmp( command, "SetUnusual", V_strlen( "SetUnusual" ) ) == 0 )
|
|
{
|
|
int iUnusual = V_atoi( &command[ V_strlen( "SetUnusual" ) ] );
|
|
SetUnusual( iUnusual );
|
|
}
|
|
else if ( FStrEq( command, "options" ) )
|
|
{
|
|
UpdateCustomizeMenu();
|
|
}
|
|
else
|
|
{
|
|
BaseClass::OnCommand( command );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::OnClassIconSelected( KeyValues *data )
|
|
{
|
|
int iClass = data->GetInt( "class", 0 );
|
|
if ( iClass < TF_FIRST_NORMAL_CLASS || iClass >= TF_LAST_NORMAL_CLASS )
|
|
{
|
|
iClass = TF_CLASS_SCOUT;
|
|
}
|
|
m_iCurrentClass = iClass;
|
|
UpdateModelPanel();
|
|
|
|
SetState( PS_PLAYER );
|
|
|
|
// C_CTF_GameStats.Event_Store( IE_STORE_ITEM_PREVIEWED, NULL, NULL, m_iCurrentClass );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::SetPlayerModelVisible( bool bVisible )
|
|
{
|
|
if( m_pPlayerModelPanel )
|
|
{
|
|
m_pPlayerModelPanel->SetVisible( bVisible );
|
|
if ( m_pRotRightButton )
|
|
{
|
|
m_pRotRightButton->SetVisible( bVisible );
|
|
}
|
|
if ( m_pRotLeftButton )
|
|
{
|
|
m_pRotLeftButton->SetVisible( bVisible );
|
|
}
|
|
UpdatePlayerModelButtons();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::PreviewItem( int iClass, CEconItemView *pItem, const econ_store_entry_t* pEntry )
|
|
{
|
|
m_iCurrentClass = 0;
|
|
BaseClass::PreviewItem( iClass, pItem, pEntry );
|
|
|
|
UpdateModelPanel();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::SetState( preview_state_t iState )
|
|
{
|
|
BaseClass::SetState( iState );
|
|
SetPlayerModelVisible( m_iState == PS_PLAYER );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
int CTFStorePreviewItemPanelBase::GetPreviewTeam() const
|
|
{
|
|
return m_pPlayerModelPanel
|
|
? m_pPlayerModelPanel->GetTeam()
|
|
: TF_TEAM_RED;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::UpdateIcons( void )
|
|
{
|
|
// Don't bother calling back to the base class UpdateIcons, because
|
|
// we'd need to redo it all with the class icons factored in.
|
|
|
|
bool bAdditionalIcons = false;
|
|
|
|
// Do the item icons first
|
|
if ( m_iState == PS_DETAILS )
|
|
{
|
|
// Show as many of the items in the bundle as possible
|
|
const CEconItemDefinition *pItemData = m_item.GetItemDefinition();
|
|
if ( pItemData )
|
|
{
|
|
const bundleinfo_t *pBundleInfo = pItemData->GetBundleInfo();
|
|
if ( pBundleInfo )
|
|
{
|
|
FOR_EACH_VEC( m_pItemIcons, i )
|
|
{
|
|
// If we haven't scrolled, the first item is the bundle itself
|
|
if ( m_iCurrentIconPosition == 0 && i == 0 )
|
|
{
|
|
m_pItemIcons[0]->SetItem( 0, &m_item );
|
|
continue;
|
|
}
|
|
|
|
int iItemPos = (i - 1 + m_iCurrentIconPosition);
|
|
if ( pBundleInfo->vecItemDefs.Count() > iItemPos && pBundleInfo->vecItemDefs[iItemPos] )
|
|
{
|
|
m_pItemIcons[i]->SetItem( i, pBundleInfo->vecItemDefs[iItemPos]->GetDefinitionIndex() );
|
|
m_pItemIcons[i]->SetVisible( true );
|
|
}
|
|
else
|
|
{
|
|
m_pItemIcons[i]->SetVisible( false );
|
|
}
|
|
}
|
|
|
|
bAdditionalIcons = (m_iCurrentIconPosition + m_pItemIcons.Count()) <= pBundleInfo->vecItemDefs.Count();
|
|
}
|
|
else if ( m_pItemIcons.Count() )
|
|
{
|
|
m_pItemIcons[0]->SetVisible( true );
|
|
m_pItemIcons[0]->SetItem( 0, &m_item );
|
|
FOR_EACH_VEC( m_pItemIcons, i )
|
|
{
|
|
if ( i != 0 )
|
|
{
|
|
m_pItemIcons[i]->SetVisible( false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Hide all the class icons
|
|
for ( int i = 0; i < m_pClassIcons.Count(); i++ )
|
|
{
|
|
m_pClassIcons[i]->SetVisible( false );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Hide all item icons first (but not the first if we haven't scrolled)
|
|
FOR_EACH_VEC( m_pItemIcons, i )
|
|
{
|
|
m_pItemIcons[i]->SetVisible( m_iCurrentIconPosition == 0 && i == 0 );
|
|
}
|
|
|
|
// First icon is always the store entry (item/bundle), if we haven't scrolled right
|
|
if ( m_iCurrentIconPosition == 0 && m_pItemIcons.Count() )
|
|
{
|
|
m_pItemIcons[0]->SetItem( 0, &m_item );
|
|
}
|
|
|
|
// Then do the class icons
|
|
const CTFItemDefinition *pItemData = m_item.GetItemDefinition();
|
|
if ( pItemData )
|
|
{
|
|
int iButton = 0;
|
|
int iMaxButtons = m_pClassIcons.Count();
|
|
int iNumClasses = (TF_LAST_NORMAL_CLASS - TF_FIRST_NORMAL_CLASS);
|
|
// we show one less class icon when the item is visible
|
|
if ( iMaxButtons < iNumClasses && m_iCurrentIconPosition == 0 )
|
|
{
|
|
iMaxButtons -= 1;
|
|
}
|
|
for ( int iClass = TF_FIRST_NORMAL_CLASS + m_iCurrentIconPosition; iClass < TF_LAST_NORMAL_CLASS; iClass++ )
|
|
{
|
|
if ( !pItemData->CanBeUsedByClass(iClass) )
|
|
continue;
|
|
|
|
// Run out of buttons?
|
|
if ( iButton >= iMaxButtons )
|
|
{
|
|
bAdditionalIcons = true;
|
|
break;
|
|
}
|
|
|
|
m_pClassIcons[iButton]->SetVisible( true );
|
|
m_pClassIcons[iButton]->SetClass(iClass);
|
|
iButton++;
|
|
|
|
if ( !m_iCurrentClass )
|
|
{
|
|
m_iCurrentClass = iClass;
|
|
}
|
|
}
|
|
for ( ; iButton < m_pClassIcons.Count(); ++iButton )
|
|
{
|
|
m_pClassIcons[iButton]->SetVisible( false );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( m_pIconsMoveLeftButton )
|
|
m_pIconsMoveLeftButton->SetVisible( (m_iCurrentIconPosition > 0) );
|
|
if( m_pIconsMoveRightButton )
|
|
m_pIconsMoveRightButton->SetVisible( bAdditionalIcons );
|
|
|
|
InvalidateLayout();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::OnTick( void )
|
|
{
|
|
BaseClass::OnTick();
|
|
|
|
if ( !IsVisible() )
|
|
{
|
|
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
|
|
return;
|
|
}
|
|
|
|
if ( m_iCurrentRotation )
|
|
{
|
|
m_pPlayerModelPanel->RotateYaw( m_iCurrentRotation );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::UpdateModelPanel()
|
|
{
|
|
if ( m_pPlayerModelPanel )
|
|
{
|
|
m_iCurrentHeldItem = 0;
|
|
m_pPlayerModelPanel->SetToPlayerClass( m_iCurrentClass, false );
|
|
m_pPlayerModelPanel->ClearCarriedItems();
|
|
|
|
|
|
if ( m_item.IsValid() )
|
|
{
|
|
CTFItemDefinition *pItemDef = m_item.GetStaticData();
|
|
if ( pItemDef->GetBundleInfo() != NULL )
|
|
{
|
|
const bundleinfo_t *pBundleInfo = pItemDef->GetBundleInfo();
|
|
FOR_EACH_VEC( pBundleInfo->vecItemDefs, i )
|
|
{
|
|
CTFItemDefinition *pBundledItem = dynamic_cast<CTFItemDefinition *>( pBundleInfo->vecItemDefs[i] );
|
|
if ( pBundledItem && pBundledItem->CanBeUsedByClass( m_iCurrentClass ) )
|
|
{
|
|
CEconItemView bundleItemData;
|
|
bundleItemData.Init( pBundledItem->GetDefinitionIndex(), AE_UNIQUE, AE_USE_SCRIPT_VALUE, true );
|
|
bundleItemData.SetClientItemFlags( kEconItemFlagClient_Preview );
|
|
int iItemIdx = m_pPlayerModelPanel->AddCarriedItem( &bundleItemData );
|
|
// try to hold it
|
|
if ( m_pPlayerModelPanel->HoldItem( iItemIdx ) )
|
|
{
|
|
m_iCurrentHeldItem = iItemIdx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pPlayerModelPanel->AddCarriedItem( &m_item );
|
|
|
|
// Now make sure we're holding it if it's a non-wearable
|
|
int iLoadoutSlot = m_item.GetStaticData()->GetLoadoutSlot( m_iCurrentClass );
|
|
m_pPlayerModelPanel->HoldItemInSlot( iLoadoutSlot );
|
|
}
|
|
}
|
|
|
|
UpdatePlayerModelButtons();
|
|
|
|
// Fix a problem where changing the class would change the preview mesh but wouldn't
|
|
// update the paint. This is a hack and won't work if we have multi-class styles or
|
|
// just about anything else.
|
|
CyclePaint( false );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::UpdatePlayerModelButtons()
|
|
{
|
|
UpdateOptionsButton();
|
|
UpdateNextWeaponButton();
|
|
UpdateZoomButton();
|
|
UpdateTeamButton();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::UpdateCustomizeMenu( void )
|
|
{
|
|
if ( m_pCustomizeMenu )
|
|
{
|
|
delete m_pCustomizeMenu;
|
|
m_pCustomizeMenu = NULL;
|
|
}
|
|
|
|
if ( !m_pPlayerModelPanel->IsVisible() )
|
|
return;
|
|
|
|
if ( !m_pOptionsButton || !m_pOptionsButton->IsVisible() )
|
|
return;
|
|
|
|
if ( !m_item.IsValid() )
|
|
return;
|
|
|
|
m_pCustomizeMenu = new Menu( this, "CustomizeMenu" );
|
|
MenuBuilder contextMenuBuilder( m_pCustomizeMenu, this );
|
|
const char *pszContextMenuBorder = "NotificationDefault";
|
|
const char *pszContextMenuFont = "HudFontMediumSecondary";
|
|
m_pCustomizeMenu->SetBorder( scheme()->GetIScheme( GetScheme() )->GetBorder( pszContextMenuBorder ) );
|
|
m_pCustomizeMenu->SetFont( scheme()->GetIScheme( GetScheme() )->GetFont( pszContextMenuFont ) );
|
|
|
|
// Add paint options sub menu
|
|
{
|
|
Menu *pPaintSubMenu = NULL;
|
|
FOR_EACH_VEC( m_vecPaintCans, i )
|
|
{
|
|
item_definition_index_t paintItemDefIndex = m_vecPaintCans[ i ];
|
|
GameItemDefinition_t * pPaintCanDef = dynamic_cast<GameItemDefinition_t*>( GEconItemSchema().GetItemDefinition( paintItemDefIndex ) );
|
|
if ( !CEconSharedToolSupport::ToolCanApplyToDefinition( dynamic_cast<const GameItemDefinition_t *>( pPaintCanDef ), m_item.GetStaticData() ) )
|
|
continue;
|
|
|
|
if ( pPaintSubMenu == NULL )
|
|
{
|
|
pPaintSubMenu = new Menu( this, "PaintSubMenu" );
|
|
pPaintSubMenu->SetBorder( scheme()->GetIScheme( GetScheme() )->GetBorder( pszContextMenuBorder ) );
|
|
pPaintSubMenu->SetFont( scheme()->GetIScheme( GetScheme() )->GetFont( pszContextMenuFont ) );
|
|
contextMenuBuilder.AddCascadingMenuItem( "#Context_Paint", pPaintSubMenu, "customization" );
|
|
}
|
|
|
|
wchar_t wBuff[256] = { 0 };
|
|
V_swprintf_safe( wBuff, L" %ls", g_pVGuiLocalize->Find( pPaintCanDef->GetItemBaseName() ) );
|
|
int nIndex = pPaintSubMenu->AddMenuItem( "", new KeyValues( "Command", "command", CFmtStr( "SetPaint%d", paintItemDefIndex ) ), this );
|
|
vgui::MenuItem *pMenuItem = pPaintSubMenu->GetMenuItem( nIndex );
|
|
pMenuItem->SetText( wBuff );
|
|
pMenuItem->InvalidateLayout( true, false );
|
|
|
|
uint32 unPaintRGB0 = 0;
|
|
uint32 unPaintRGB1 = 0;
|
|
|
|
static CSchemaAttributeDefHandle pAttrDef_PaintRGB( "set item tint RGB" );
|
|
static CSchemaAttributeDefHandle pAttrDef_PaintRGB2( "set item tint RGB 2" );
|
|
|
|
float fRGB = 0.0f;
|
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pPaintCanDef, pAttrDef_PaintRGB, &fRGB ) && fRGB != 0.0f )
|
|
{
|
|
unPaintRGB0 = fRGB;
|
|
|
|
// We may or may not have a secondary paint color as well. If we don't, we just use the primary
|
|
// paint color to fill both slots.
|
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pPaintCanDef, pAttrDef_PaintRGB2, &fRGB ) )
|
|
{
|
|
unPaintRGB1 = fRGB;
|
|
}
|
|
else
|
|
{
|
|
unPaintRGB1 = unPaintRGB0;
|
|
}
|
|
}
|
|
|
|
CItemMaterialCustomizationIconPanel *pCustomPanel = new CItemMaterialCustomizationIconPanel( pMenuItem, "paint" );
|
|
pCustomPanel->SetZPos( -100 );
|
|
pCustomPanel->SetTall( 30 );
|
|
pCustomPanel->SetWide( 30 );
|
|
pCustomPanel->m_colPaintColors.AddToTail( Color( clamp( (unPaintRGB0 & 0xFF0000) >> 16, 0, 255 ), clamp( (unPaintRGB0 & 0xFF00) >> 8, 0, 255 ), clamp( (unPaintRGB0 & 0xFF), 0, 255 ), 255 ) );
|
|
pCustomPanel->m_colPaintColors.AddToTail( Color( clamp( (unPaintRGB1 & 0xFF0000) >> 16, 0, 255 ), clamp( (unPaintRGB1 & 0xFF00) >> 8, 0, 255 ), clamp( (unPaintRGB1 & 0xFF), 0, 255 ), 255 ) );
|
|
}
|
|
}
|
|
|
|
// Add style
|
|
{
|
|
Menu *pStyleSubMenu = NULL;
|
|
if ( m_item.GetStaticData()->GetNumSelectableStyles() > 1 )
|
|
{
|
|
for ( style_index_t unStyle=0; unStyle<m_item.GetStaticData()->GetNumStyles(); ++unStyle )
|
|
{
|
|
const CEconStyleInfo *pStyle = m_item.GetStaticData()->GetStyleInfo( unStyle );
|
|
if ( !pStyle )
|
|
continue;
|
|
|
|
if ( !pStyle->IsSelectable() )
|
|
continue;
|
|
|
|
if ( pStyleSubMenu == NULL )
|
|
{
|
|
pStyleSubMenu = new Menu( this, "StyleSubMenu" );
|
|
pStyleSubMenu->SetBorder( scheme()->GetIScheme( GetScheme() )->GetBorder( pszContextMenuBorder ) );
|
|
pStyleSubMenu->SetFont( scheme()->GetIScheme( GetScheme() )->GetFont( pszContextMenuFont ) );
|
|
contextMenuBuilder.AddCascadingMenuItem( "#Context_Style", pStyleSubMenu, "customization" );
|
|
}
|
|
|
|
int nIndex = pStyleSubMenu->AddMenuItem( "", new KeyValues( "Command", "command", CFmtStr( "SetStyle%d", unStyle ) ), this );
|
|
vgui::MenuItem *pMenuItem = pStyleSubMenu->GetMenuItem( nIndex );
|
|
pMenuItem->SetText( pStyle->GetName() );
|
|
pMenuItem->InvalidateLayout( true, false );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add unusual
|
|
{
|
|
const CUtlVector< int > *pUnusualList = GetUnusualList();
|
|
if ( pUnusualList )
|
|
{
|
|
Menu *pUnusualSubMenu = NULL;
|
|
for ( int i=0; i<pUnusualList->Count(); ++i )
|
|
{
|
|
if ( pUnusualSubMenu == NULL )
|
|
{
|
|
pUnusualSubMenu = new Menu( this, "UnusualSubMenu" );
|
|
pUnusualSubMenu->SetBorder( scheme()->GetIScheme( GetScheme() )->GetBorder( pszContextMenuBorder ) );
|
|
pUnusualSubMenu->SetFont( scheme()->GetIScheme( GetScheme() )->GetFont( pszContextMenuFont ) );
|
|
contextMenuBuilder.AddCascadingMenuItem( "#Context_Unusual", pUnusualSubMenu, "customization" );
|
|
}
|
|
|
|
int iParticleIndex = pUnusualList->Element( i );
|
|
int nIndex = pUnusualSubMenu->AddMenuItem( "", new KeyValues( "Command", "command", CFmtStr( "SetUnusual%d", iParticleIndex ) ), this );
|
|
vgui::MenuItem *pMenuItem = pUnusualSubMenu->GetMenuItem( nIndex );
|
|
pMenuItem->SetText( GetItemSchema()->GetParticleSystemLocalizedName( iParticleIndex ) );
|
|
pMenuItem->InvalidateLayout( true, false );
|
|
}
|
|
}
|
|
}
|
|
|
|
int nX, nY;
|
|
g_pVGuiInput->GetCursorPosition( nX, nY );
|
|
m_pCustomizeMenu->SetPos( nX - 1, nY - 1 );
|
|
|
|
m_pCustomizeMenu->SetVisible(true);
|
|
m_pCustomizeMenu->AddActionSignalTarget(this);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::UpdateOptionsButton( void )
|
|
{
|
|
if ( !m_pOptionsButton )
|
|
return;
|
|
|
|
m_pOptionsButton->SetVisible( false );
|
|
|
|
if ( !m_pPlayerModelPanel->IsVisible() )
|
|
return;
|
|
|
|
if ( !m_item.IsValid() )
|
|
return;
|
|
|
|
const CEconItemDefinition *pItemData = m_item.GetItemDefinition();
|
|
if ( !pItemData )
|
|
return;
|
|
|
|
bool bVisible = false;
|
|
|
|
// Is the selected item paintable
|
|
if ( pItemData->GetCapabilities() & ITEM_CAP_PAINTABLE )
|
|
{
|
|
bVisible = true;
|
|
}
|
|
// has multiple styles?
|
|
else if ( pItemData->GetNumSelectableStyles() > 1 )
|
|
{
|
|
bVisible = true;
|
|
}
|
|
// can have unusual?
|
|
else if ( GetUnusualList() != NULL )
|
|
{
|
|
bVisible = true;
|
|
}
|
|
|
|
m_pOptionsButton->SetVisible( bVisible );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::UpdateZoomButton( void )
|
|
{
|
|
if ( !m_pZoomButton )
|
|
return;
|
|
|
|
m_pZoomButton->SetVisible( m_pPlayerModelPanel->IsVisible() );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::UpdateTeamButton( void )
|
|
{
|
|
if ( !m_pTeamButton )
|
|
return;
|
|
|
|
m_pTeamButton->SetVisible( m_pPlayerModelPanel->IsVisible() );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::UpdateNextWeaponButton( void )
|
|
{
|
|
if ( !m_pNextWeaponButton )
|
|
return;
|
|
|
|
if ( !m_pPlayerModelPanel->IsVisible() )
|
|
{
|
|
m_pNextWeaponButton->SetVisible( false );
|
|
return;
|
|
}
|
|
|
|
bool bShowNextWeaponsButton = false;
|
|
const CUtlVector<CEconItemView*> &items = m_pPlayerModelPanel->GetCarriedItems();
|
|
int iNumItemsArray[CLASS_LOADOUT_POSITION_COUNT];
|
|
memset( iNumItemsArray, 0, sizeof( iNumItemsArray ) );
|
|
FOR_EACH_VEC( items, i )
|
|
{
|
|
CEconItemView *pItem = items[i];
|
|
int iLoadoutSlot = pItem->GetStaticData()->GetLoadoutSlot( m_iCurrentClass );
|
|
if ( iLoadoutSlot >= 0 && iLoadoutSlot < CLASS_LOADOUT_POSITION_COUNT )
|
|
{
|
|
++iNumItemsArray[iLoadoutSlot];
|
|
}
|
|
}
|
|
bShowNextWeaponsButton |= iNumItemsArray[LOADOUT_POSITION_PRIMARY] + iNumItemsArray[LOADOUT_POSITION_SECONDARY] + iNumItemsArray[LOADOUT_POSITION_MELEE] > 1;
|
|
|
|
m_pNextWeaponButton->SetVisible( bShowNextWeaponsButton );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::OnHideClassIconMouseover( void )
|
|
{
|
|
if ( m_pClassIconMouseoverLabel )
|
|
{
|
|
m_pClassIconMouseoverLabel->SetVisible( false );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::OnShowClassIconMouseover( KeyValues *data )
|
|
{
|
|
if ( m_pClassIconMouseoverLabel )
|
|
{
|
|
const CEconItemDefinition *pItemData = m_item.GetItemDefinition();
|
|
bool bIsABundle = pItemData ? (pItemData->GetBundleInfo() != NULL) : false;
|
|
|
|
// Set the text to the correct string
|
|
int iClass = data->GetInt( "class", 0 );
|
|
if ( iClass >= TF_FIRST_NORMAL_CLASS && iClass < TF_LAST_NORMAL_CLASS )
|
|
{
|
|
wchar_t wzLocalized[256];
|
|
const char *pszLocString = bIsABundle ? "#Store_ClassImageMouseoverBundle" : "#Store_ClassImageMouseover";
|
|
g_pVGuiLocalize->ConstructString_safe( wzLocalized, g_pVGuiLocalize->Find( pszLocString ), 1, g_pVGuiLocalize->Find( g_aPlayerClassNames[iClass] ) );
|
|
m_pClassIconMouseoverLabel->SetText( wzLocalized );
|
|
}
|
|
else
|
|
{
|
|
const char *pszLocString = bIsABundle ? "#Store_ClassImageMouseoverAllBundle" : "#Store_ClassImageMouseoverAll";
|
|
m_pClassIconMouseoverLabel->SetText( pszLocString );
|
|
}
|
|
|
|
m_pClassIconMouseoverLabel->SetVisible( true );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::CycleStyle( void )
|
|
{
|
|
if ( !m_pPlayerModelPanel )
|
|
return;
|
|
|
|
// Find and cycle the style based on the first item we're previewing that has
|
|
// styles. If we are previewing multiple items at the same time where more than
|
|
// one of them has styles, we'll only cycle through the names/options of the
|
|
// first one in the list.
|
|
CEconItemView *pPreviewItemView = NULL;
|
|
|
|
const CUtlVector<CEconItemView*> &vecItems = m_pPlayerModelPanel->GetCarriedItems();
|
|
FOR_EACH_VEC( vecItems, i )
|
|
{
|
|
CEconItemView *pItem = vecItems[i];
|
|
if ( pItem->GetStaticData()->GetNumStyles() && ( pItem->GetFlags() & kEconItemFlagClient_Preview ) )
|
|
{
|
|
pPreviewItemView = pItem;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !pPreviewItemView )
|
|
return;
|
|
|
|
// Cycle.
|
|
style_index_t unStyleCount = pPreviewItemView->GetStaticData()->GetNumStyles();
|
|
Assert( unStyleCount >= 1 );
|
|
|
|
style_index_t unStyle = pPreviewItemView->GetItemStyle();
|
|
// Default to style 0 if we're getting an invalid index
|
|
unStyle = unStyle == INVALID_STYLE_INDEX ? 0 : unStyle;
|
|
|
|
// Try to find the next selectable style
|
|
const CEconStyleInfo *pStyle = NULL;
|
|
style_index_t unStartingStyle = unStyle;
|
|
do
|
|
{
|
|
unStyle = (unStyle + 1) % unStyleCount;
|
|
pStyle = pPreviewItemView->GetStaticData()->GetStyleInfo( unStyle );
|
|
Assert( pStyle );
|
|
}
|
|
while ( unStyle != unStartingStyle && ( !pStyle || !pStyle->IsSelectable() ) );
|
|
|
|
pPreviewItemView->SetItemStyleOverride( unStyle );
|
|
SetCycleLabelText( m_pStyleNameLabel, pStyle->GetName() );
|
|
|
|
// Re-equip our held item. This causes all of our equipped items to get reloaded, and thus
|
|
// their styles updated
|
|
m_pPlayerModelPanel->SwitchHeldItemTo( m_pPlayerModelPanel->GetHeldItem() );
|
|
m_pPlayerModelPanel->UpdatePreviewVisuals();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::SetPaint( item_definition_index_t iItemDef )
|
|
{
|
|
if ( !m_pPlayerModelPanel )
|
|
return;
|
|
|
|
if ( !IsAnythingPaintable( m_pPlayerModelPanel->GetCarriedItems() ) )
|
|
return;
|
|
|
|
static CSchemaAttributeDefHandle pAttribDef_Paint( "set item tint RGB" );
|
|
static CSchemaAttributeDefHandle pAttribDef_Paint2( "set item tint RGB 2" );
|
|
|
|
// Find the next paint color.
|
|
const CEconItemSchema::SortedItemDefinitionMap_t &mapDefs = GetItemSchema()->GetSortedItemDefinitionMap();
|
|
|
|
m_unPaintRGB0 = 0;
|
|
m_unPaintRGB1 = 0;
|
|
|
|
if ( iItemDef != INVALID_ITEM_DEF_INDEX )
|
|
{
|
|
int iteratorName = mapDefs.FirstInorder();
|
|
while ( iteratorName != mapDefs.InvalidIndex() )
|
|
{
|
|
// Find the next sub
|
|
int iIndex = mapDefs[iteratorName]->GetDefinitionIndex();
|
|
if ( iIndex == iItemDef )
|
|
{
|
|
// Is this definition something that has paint attributes on it?
|
|
const CEconItemDefinition *pData = mapDefs[iteratorName];
|
|
|
|
float fRGB = 0.0f;
|
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pData, pAttribDef_Paint, &fRGB ) && fRGB != 0.0f )
|
|
{
|
|
m_unPaintRGB0 = fRGB;
|
|
|
|
// We may or may not have a secondary paint color as well. If we don't, we just use the primary
|
|
// paint color to fill both slots.
|
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pData, pAttribDef_Paint2, &fRGB ) )
|
|
{
|
|
m_unPaintRGB1 = fRGB;
|
|
}
|
|
else
|
|
{
|
|
m_unPaintRGB1 = m_unPaintRGB0;
|
|
}
|
|
|
|
m_unPaintDef = pData->GetDefinitionIndex();
|
|
SetCycleLabelText( m_pPaintNameLabel, pData->GetItemBaseName() );
|
|
}
|
|
else
|
|
{
|
|
Warning( "CTFStorePreviewItemPanelBase::SetPaint iItemDef[%d] is not paint item", iItemDef );
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
iteratorName = mapDefs.NextInorder( iteratorName );
|
|
}
|
|
}
|
|
|
|
if ( m_unPaintRGB0 == 0 )
|
|
{
|
|
m_unPaintDef = 0;
|
|
SetCycleLabelText( m_pPaintNameLabel, "#Store_NoPaint" );
|
|
}
|
|
|
|
UpdatePaintColorsForTeam( m_pPlayerModelPanel, m_unPaintRGB0, m_unPaintRGB1 );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::SetStyle( style_index_t unStyle )
|
|
{
|
|
if ( !m_pPlayerModelPanel )
|
|
return;
|
|
|
|
// Find and cycle the style based on the first item we're previewing that has
|
|
// styles. If we are previewing multiple items at the same time where more than
|
|
// one of them has styles, we'll only cycle through the names/options of the
|
|
// first one in the list.
|
|
CEconItemView *pPreviewItemView = NULL;
|
|
|
|
const CUtlVector<CEconItemView*> &vecItems = m_pPlayerModelPanel->GetCarriedItems();
|
|
FOR_EACH_VEC( vecItems, i )
|
|
{
|
|
CEconItemView *pItem = vecItems[i];
|
|
if ( pItem->GetStaticData()->GetNumSelectableStyles() > 1 )
|
|
{
|
|
pPreviewItemView = pItem;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !pPreviewItemView )
|
|
return;
|
|
|
|
pPreviewItemView->SetItemStyleOverride( unStyle );
|
|
const CEconStyleInfo *pStyle = pPreviewItemView->GetStaticData()->GetStyleInfo( unStyle );
|
|
Assert( pStyle && pStyle->IsSelectable() );
|
|
if ( pStyle )
|
|
{
|
|
SetCycleLabelText( m_pStyleNameLabel, pStyle->GetName() );
|
|
}
|
|
|
|
// Re-equip our held item. This causes all of our equipped items to get reloaded, and thus
|
|
// their styles updated
|
|
m_pPlayerModelPanel->SwitchHeldItemTo( m_pPlayerModelPanel->GetHeldItem() );
|
|
m_pPlayerModelPanel->UpdatePreviewVisuals();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::SetUnusual( uint32 iUnusualIndex )
|
|
{
|
|
if ( !m_pPlayerModelPanel )
|
|
return;
|
|
|
|
static CSchemaAttributeDefHandle pAttrDef_AttachParticleEffect( "attach particle effect" );
|
|
static CSchemaAttributeDefHandle pAttrDef_OnTauntAttachParticleIndex( "on taunt attach particle index" );
|
|
const CUtlVector<CEconItemView*> &vecItems = m_pPlayerModelPanel->GetCarriedItems();
|
|
|
|
FOR_EACH_VEC( vecItems, i )
|
|
{
|
|
CEconItemView *pItem = vecItems[i];
|
|
if ( pItem->GetStaticData()->GetTauntData() )
|
|
{
|
|
const float& value_as_float = (float&)iUnusualIndex;
|
|
pItem->GetAttributeList()->SetRuntimeAttributeValue( pAttrDef_OnTauntAttachParticleIndex, value_as_float );
|
|
}
|
|
else
|
|
{
|
|
pItem->GetAttributeList()->SetRuntimeAttributeValue( pAttrDef_AttachParticleEffect, iUnusualIndex );
|
|
}
|
|
}
|
|
m_pPlayerModelPanel->InvalidateParticleEffects();
|
|
m_pPlayerModelPanel->SwitchHeldItemTo( m_pPlayerModelPanel->GetHeldItem() );
|
|
}
|
|
|
|
|
|
const CUtlVector< int > *CTFStorePreviewItemPanelBase::GetUnusualList() const
|
|
{
|
|
if ( !AllowUnusualPreview() )
|
|
return NULL;
|
|
|
|
int iLoadoutSlot = m_item.GetStaticData()->GetLoadoutSlot( m_iCurrentClass );
|
|
if ( IsValidPickupWeaponSlot( iLoadoutSlot ) )
|
|
{
|
|
return GetItemSchema()->GetWeaponUnusualParticleIndexes();
|
|
}
|
|
// is hat or whole head?
|
|
else if ( m_item.GetItemDefinition()->GetEquipRegionMask() & GetItemSchema()->GetEquipRegionBitMaskByName( "hat" ) || m_item.GetItemDefinition()->GetEquipRegionMask() & GetItemSchema()->GetEquipRegionBitMaskByName( "whole_head" ) )
|
|
{
|
|
return GetItemSchema()->GetCosmeticUnusualParticleIndexes();
|
|
}
|
|
else if ( IsTauntSlot( iLoadoutSlot ) )
|
|
{
|
|
return GetItemSchema()->GetTauntUnusualParticleIndexes();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFStorePreviewItemPanelBase::CyclePaint( bool bActuallyCycle )
|
|
{
|
|
if ( !m_pPlayerModelPanel )
|
|
return;
|
|
|
|
if ( !IsAnythingPaintable( m_pPlayerModelPanel->GetCarriedItems() ) )
|
|
return;
|
|
|
|
static CSchemaAttributeDefHandle pAttribDef_Paint( "set item tint RGB" );
|
|
static CSchemaAttributeDefHandle pAttribDef_Paint2( "set item tint RGB 2" );
|
|
|
|
// Find the next paint color.
|
|
const CEconItemSchema::SortedItemDefinitionMap_t &mapDefs = GetItemSchema()->GetSortedItemDefinitionMap();
|
|
|
|
m_unPaintRGB0 = 0;
|
|
m_unPaintRGB1 = 0;
|
|
|
|
if ( bActuallyCycle || m_unPaintDef > 0 )
|
|
{
|
|
int iteratorName = mapDefs.FirstInorder();
|
|
while ( iteratorName != mapDefs.InvalidIndex() )
|
|
{
|
|
// Find the next sub
|
|
int iIndex = mapDefs[iteratorName]->GetDefinitionIndex();
|
|
if ( bActuallyCycle ? iIndex > m_unPaintDef : iIndex >= m_unPaintDef )
|
|
{
|
|
// Is this definition something that has paint attributes on it?
|
|
const CEconItemDefinition *pData = mapDefs[iteratorName];
|
|
|
|
float fRGB = 0.0f;
|
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pData, pAttribDef_Paint, &fRGB ) && fRGB != 0.0f )
|
|
{
|
|
if ( V_strstr( pData->GetItemBaseName(), "Halloween" ) )
|
|
{
|
|
iteratorName = mapDefs.NextInorder( iteratorName );
|
|
continue;
|
|
}
|
|
|
|
m_unPaintRGB0 = fRGB;
|
|
|
|
// We may or may not have a secondary paint color as well. If we don't, we just use the primary
|
|
// paint color to fill both slots.
|
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pData, pAttribDef_Paint2, &fRGB ) )
|
|
{
|
|
m_unPaintRGB1 = fRGB;
|
|
}
|
|
else
|
|
{
|
|
m_unPaintRGB1 = m_unPaintRGB0;
|
|
}
|
|
|
|
m_unPaintDef = pData->GetDefinitionIndex();
|
|
SetCycleLabelText( m_pPaintNameLabel, pData->GetItemBaseName() );
|
|
break;
|
|
}
|
|
}
|
|
|
|
iteratorName = mapDefs.NextInorder( iteratorName );
|
|
}
|
|
}
|
|
|
|
if ( m_unPaintRGB0 == 0 )
|
|
{
|
|
m_unPaintDef = 0;
|
|
SetCycleLabelText( m_pPaintNameLabel, "#Store_NoPaint" );
|
|
}
|
|
|
|
UpdatePaintColorsForTeam( m_pPlayerModelPanel, m_unPaintRGB0, m_unPaintRGB1 );
|
|
}
|