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.
3934 lines
120 KiB
3934 lines
120 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "vgui/IInput.h"
|
||
|
#include <vgui/IVGui.h>
|
||
|
#include <vgui/IScheme.h>
|
||
|
#include "item_model_panel.h"
|
||
|
#include "iclientmode.h"
|
||
|
#include "baseviewport.h"
|
||
|
#include "econ_entity.h"
|
||
|
#include "gamestringpool.h"
|
||
|
#include "vgui_controls/TextImage.h"
|
||
|
#include "vgui_controls/Label.h"
|
||
|
#include "vgui_controls/Button.h"
|
||
|
#include "econ_item_system.h"
|
||
|
#include "ienginevgui.h"
|
||
|
#include "VGuiMatSurface/IMatSystemSurface.h"
|
||
|
#include "renderparm.h"
|
||
|
#include "vgui_controls/ScalableImagePanel.h"
|
||
|
#include "engine/IEngineSound.h"
|
||
|
#include "econ/tool_items/tool_items.h"
|
||
|
#include "econ_item_description.h"
|
||
|
#include "econ_item_tools.h"
|
||
|
#include "tool_items/custom_texture_cache.h"
|
||
|
#include "econ_dynamic_recipe.h"
|
||
|
#include "materialsystem/imaterialvar.h"
|
||
|
#include "materialsystem/itexturecompositor.h"
|
||
|
#include "bone_setup.h"
|
||
|
#include "animation.h"
|
||
|
#include "iconrenderreceiver.h"
|
||
|
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
#include "tf_shareddefs.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
#endif // TF_CLIENT_DLL
|
||
|
#include "KeyValues.h"
|
||
|
|
||
|
ConVar tf_time_loading_item_panels( "tf_time_loading_item_panels", "0.0005", FCVAR_ARCHIVE, "The time to spend per frame loading data for item panels" );
|
||
|
#ifdef STAGING_ONLY
|
||
|
ConVar tf_paint_kit_show_unique_icon( "tf_paint_kit_show_unique_icon", "1" );
|
||
|
ConVar tf_test_loading_panels( "tf_test_loading_panels", "0" );
|
||
|
ConVar tf_force_highres_item_image( "tf_force_highres_item_image", "0" );
|
||
|
ConVar tf_unique_icon_perf_debug( "tf_unique_icon_perf_debug", "0" );
|
||
|
#endif
|
||
|
|
||
|
const char* g_ItemModelPanelRenderTargetNames[] =
|
||
|
{
|
||
|
"_rt_ItemModelPanel0",
|
||
|
"_rt_ItemModelPanel1",
|
||
|
"_rt_ItemModelPanel2"
|
||
|
};
|
||
|
COMPILE_TIME_ASSERT( ITEM_MODEL_IMAGE_CACHE_SIZE == ARRAYSIZE( g_ItemModelPanelRenderTargetNames ) );
|
||
|
|
||
|
CItemMaterialCustomizationIconPanel::CItemMaterialCustomizationIconPanel( vgui::Panel *pParent, const char *pName )
|
||
|
: BaseClass( pParent, pName )
|
||
|
{
|
||
|
m_iPaintSplat = -1;
|
||
|
}
|
||
|
|
||
|
CItemMaterialCustomizationIconPanel::~CItemMaterialCustomizationIconPanel()
|
||
|
{
|
||
|
if ( vgui::surface() )
|
||
|
{
|
||
|
if ( m_iPaintSplat != -1 )
|
||
|
{
|
||
|
vgui::surface()->DestroyTextureID( m_iPaintSplat );
|
||
|
m_iPaintSplat = -1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Custom painting
|
||
|
void CItemMaterialCustomizationIconPanel::PaintBackground( void )
|
||
|
{
|
||
|
// Draw custom texture, if we have one
|
||
|
if ( m_hUGCId != 0 )
|
||
|
{
|
||
|
// Request it from the cache, and get filename, if it's downloaded
|
||
|
// and ready
|
||
|
int iCustomTexture = GetCustomTextureGuiHandle( m_hUGCId );
|
||
|
if ( iCustomTexture != 0 )
|
||
|
{
|
||
|
surface()->DrawSetTexture( iCustomTexture );
|
||
|
DrawQuad( 0, 1 );
|
||
|
surface()->DrawSetColor(COLOR_WHITE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for ( int i = 0; i < m_colPaintColors.Size(); i++ )
|
||
|
{
|
||
|
const Color& c = m_colPaintColors[i];
|
||
|
|
||
|
if ( m_iPaintSplat == -1 )
|
||
|
{
|
||
|
m_iPaintSplat = surface()->CreateNewTextureID();
|
||
|
surface()->DrawSetTextureFile( m_iPaintSplat, "vgui/backpack_jewel_paint_splatter", true, false);
|
||
|
}
|
||
|
surface()->DrawSetTexture( m_iPaintSplat );
|
||
|
surface()->DrawSetColor( c.r(), c.g(), c.b(), GetAlpha() );
|
||
|
DrawQuad( i, m_colPaintColors.Size() );
|
||
|
surface()->DrawSetColor(COLOR_WHITE);
|
||
|
}
|
||
|
|
||
|
// Clean up
|
||
|
vgui::surface()->DrawSetTexture(0);
|
||
|
}
|
||
|
|
||
|
// Draw a quad that fills our extents
|
||
|
void CItemMaterialCustomizationIconPanel::DrawQuad( int iSubtileIndex, int iSubtileCount )
|
||
|
{
|
||
|
int iWide, iTall;
|
||
|
GetSize( iWide, iTall );
|
||
|
|
||
|
// All of this math is to accomplish the following: allow us to split our single "icon"
|
||
|
// into some number of equivalent columns. Then take each column and angle the divider so
|
||
|
// it goes from the left image to the right image:
|
||
|
//
|
||
|
// +-----+-----+ +------+----+
|
||
|
// | | | | / |
|
||
|
// | | | | | |
|
||
|
// | | | | / |
|
||
|
// +-----+-----+ +--- +------+
|
||
|
//
|
||
|
// ...because the angle is prettier than a straight vertical cut.
|
||
|
//
|
||
|
// My hope is that this code is so awful I'm never allowed to write UI code again.
|
||
|
float fXScale = 1.0f / (float)iSubtileCount,
|
||
|
fXOffsetL = (float)iSubtileIndex * fXScale,
|
||
|
fXOffsetR = (float)(iSubtileIndex + 1) * fXScale,
|
||
|
fXUpperLowerOffset = fXScale * 0.65f;
|
||
|
|
||
|
// We shift our coordinates on the top slightly to the right (by fXUpperLowerOffset) and on
|
||
|
// the bottom slightly to the left (also by fXUpperLowerOffset). The far left side can't move
|
||
|
// away from 0 and the far right side can't move away from 1, so the edge case handling makes
|
||
|
// this look uglier than it really is.
|
||
|
float fXUL = iSubtileIndex == 0 ? fXOffsetL : fXOffsetL + fXUpperLowerOffset,
|
||
|
fXUR = iSubtileIndex == iSubtileCount - 1 ? fXOffsetR : fXOffsetR + fXUpperLowerOffset,
|
||
|
fXBL = iSubtileIndex == 0 ? fXOffsetL : fXOffsetL - fXUpperLowerOffset,
|
||
|
fXBR = iSubtileIndex == iSubtileCount - 1 ? fXOffsetR : fXOffsetR - fXUpperLowerOffset;
|
||
|
|
||
|
Vector2D uv11( fXUL, 0.0f );
|
||
|
Vector2D uv21( fXUR, 0.0f );
|
||
|
Vector2D uv22( fXBR, 1.0f );
|
||
|
Vector2D uv12( fXBL, 1.0f );
|
||
|
|
||
|
vgui::Vertex_t verts[4];
|
||
|
verts[0].Init( Vector2D( iWide * fXUL, 0 ), uv11 );
|
||
|
verts[1].Init( Vector2D( iWide * fXUR, 0 ), uv21 );
|
||
|
verts[2].Init( Vector2D( iWide * fXBR, iTall ), uv22 );
|
||
|
verts[3].Init( Vector2D( iWide * fXBL, iTall ), uv12 );
|
||
|
|
||
|
vgui::surface()->DrawTexturedPolygon( 4, verts );
|
||
|
}
|
||
|
|
||
|
DECLARE_BUILD_FACTORY( CItemModelPanel );
|
||
|
DECLARE_BUILD_FACTORY( CEmbeddedItemModelPanel );
|
||
|
DECLARE_BUILD_FACTORY( CItemMaterialCustomizationIconPanel );
|
||
|
|
||
|
item_model_cache_t g_ItemModelImageCache[ITEM_MODEL_IMAGE_CACHE_SIZE];
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CEmbeddedItemModelPanel::CEmbeddedItemModelPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
|
||
|
{
|
||
|
m_bUseItemRenderTarget = false;
|
||
|
m_bForceUseModel = false;
|
||
|
m_pItem = NULL;
|
||
|
m_pszToolTargetItemImage = NULL;
|
||
|
m_iTextureID = -1;
|
||
|
m_iToolTargetItemTextureID = -1;
|
||
|
m_iOverlayTextureIDs.SetLessFunc( DefLessFunc(int) );
|
||
|
m_iOverlayTextureIDs.Purge();
|
||
|
m_bImageNotLoaded = false;
|
||
|
m_bGreyedOut = false;
|
||
|
m_bModelIsHidden = false;
|
||
|
m_bUseRenderTargetAsIcon = false;
|
||
|
|
||
|
m_bWeaponAllowInspect = false;
|
||
|
m_pCachedWeaponIcon = NULL;
|
||
|
m_pCachedWeaponMaterial = NULL;
|
||
|
m_iCachedTextureID = -1;
|
||
|
|
||
|
m_flModelRotateYawSpeed = 0;
|
||
|
|
||
|
m_bUsePedestal = false;
|
||
|
m_bOfflineIconGeneration = false;
|
||
|
|
||
|
m_pItemParticle = NULL;
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
m_flStartUpdateTime = 0.0;
|
||
|
#endif // STAGING_ONLY
|
||
|
}
|
||
|
|
||
|
|
||
|
CEmbeddedItemModelPanel::~CEmbeddedItemModelPanel()
|
||
|
{
|
||
|
CleanUpCachedWeaponIcon();
|
||
|
|
||
|
SafeDeleteParticleData( &m_pItemParticle );
|
||
|
}
|
||
|
|
||
|
|
||
|
void CEmbeddedItemModelPanel::CleanUpCachedWeaponIcon()
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
|
||
|
SafeRelease( &m_pCachedWeaponIcon );
|
||
|
SafeRelease( &m_pCachedWeaponMaterial );
|
||
|
|
||
|
if ( m_iCachedTextureID != -1 )
|
||
|
{
|
||
|
surface()->DeleteTextureByID( m_iCachedTextureID );
|
||
|
m_iCachedTextureID = -1;
|
||
|
}
|
||
|
|
||
|
// If we match a cache here, clear it so we redraw once when we appear.
|
||
|
for ( int i = 0; i < ITEM_MODEL_IMAGE_CACHE_SIZE; i++ )
|
||
|
{
|
||
|
bool bMatch = g_ItemModelImageCache[i].m_hModelPanelLock.Get() == this;
|
||
|
if ( bMatch )
|
||
|
{
|
||
|
g_ItemModelImageCache[i].Clear();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CEmbeddedItemModelPanel::UpdateCameraForIcon()
|
||
|
{
|
||
|
if ( m_iCameraAttachment == -1 )
|
||
|
return;
|
||
|
|
||
|
studiohdr_t *pItemStudioHdr = m_RootMDL.m_MDL.GetStudioHdr();
|
||
|
if ( pItemStudioHdr )
|
||
|
{
|
||
|
matrix3x4_t matBoneToWorld[MAXSTUDIOBONES];
|
||
|
m_RootMDL.m_MDL.SetUpBones( m_RootMDL.m_MDLToWorld, MAXSTUDIOBONES, matBoneToWorld );
|
||
|
|
||
|
// Get attachment transform
|
||
|
mstudioattachment_t attach = pItemStudioHdr->pAttachment( m_iCameraAttachment );
|
||
|
matrix3x4_t matLocalToWorld;
|
||
|
ConcatTransforms( matBoneToWorld[ attach.localbone ], attach.local, matLocalToWorld );
|
||
|
|
||
|
QAngle angCameraAngles;
|
||
|
Vector vecCameraPos;
|
||
|
MatrixAngles( matLocalToWorld, angCameraAngles, vecCameraPos );
|
||
|
SetCameraOffset( vec3_origin );
|
||
|
SetCameraPositionAndAngles( vecCameraPos, angCameraAngles );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CEmbeddedItemModelPanel::SetItem( CEconItemView *pItem )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
|
||
|
m_iTextureID = -1;
|
||
|
m_iToolTargetItemTextureID = -1;
|
||
|
m_iOverlayTextureIDs.Purge();
|
||
|
CleanUpCachedWeaponIcon();
|
||
|
SafeDeleteParticleData( &m_pItemParticle );
|
||
|
|
||
|
// reset all models
|
||
|
SetMDL( MDLHANDLE_INVALID );
|
||
|
m_ItemModel.m_bDisabled = true;
|
||
|
m_ItemModel.m_MDL.SetMDL( MDLHANDLE_INVALID );
|
||
|
m_StatTrackModel.m_bDisabled = true;
|
||
|
m_StatTrackModel.m_MDL.SetMDL( MDLHANDLE_INVALID );
|
||
|
|
||
|
m_AttachedModels.Purge();
|
||
|
|
||
|
m_iCameraAttachment = -1;
|
||
|
|
||
|
m_pItem = pItem;
|
||
|
|
||
|
if ( !m_pItem )
|
||
|
return;
|
||
|
|
||
|
const char* pszInventoryImage = m_pItem->IsValid() ? m_pItem->GetInventoryImage() : NULL;
|
||
|
if ( ( pszInventoryImage && pszInventoryImage[0] && !g_pMaterialSystem->IsMaterialLoaded( pszInventoryImage ) )
|
||
|
#ifdef STAGING_ONLY
|
||
|
|| tf_test_loading_panels.GetBool()
|
||
|
#endif
|
||
|
)
|
||
|
{
|
||
|
m_bImageNotLoaded = true;
|
||
|
}
|
||
|
|
||
|
if ( !m_pItem->IsValid() )
|
||
|
return;
|
||
|
|
||
|
float flValue;
|
||
|
static CSchemaAttributeDefHandle pAttrib_ToolTarget( "tool target item" );
|
||
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( m_pItem, pAttrib_ToolTarget, &flValue ) )
|
||
|
{
|
||
|
const CEconItemDefinition *pTargetDef = GetItemSchema()->GetItemDefinition( flValue );
|
||
|
|
||
|
m_pszToolTargetItemImage = pTargetDef->GetInventoryImage();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pszToolTargetItemImage = NULL;
|
||
|
}
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
if ( tf_paint_kit_show_unique_icon.GetBool() )
|
||
|
#endif // STAGING_ONLY
|
||
|
{
|
||
|
float flInspect = 0;
|
||
|
static CSchemaAttributeDefHandle pAttrib_WeaponAllowInspect( "weapon_allow_inspect" );
|
||
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( m_pItem, pAttrib_WeaponAllowInspect, &flInspect ) )
|
||
|
{
|
||
|
m_bWeaponAllowInspect = flInspect != 0;
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
if ( m_flStartUpdateTime == 0 )
|
||
|
m_flStartUpdateTime = Plat_FloatTime();
|
||
|
#endif // STAGING_ONLY
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_bWeaponAllowInspect = false;
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
m_flStartUpdateTime = 0.0;
|
||
|
#endif // STAGING_ONLY
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float flUseCacheIcon = 0.f;
|
||
|
static CSchemaAttributeDefHandle pAttrib_UseModelCacheIcon( "use_model_cache_icon" );
|
||
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( m_pItem, pAttrib_UseModelCacheIcon, &flUseCacheIcon ) && flUseCacheIcon != 0.f )
|
||
|
{
|
||
|
m_bUseRenderTargetAsIcon = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_bUseRenderTargetAsIcon = false;
|
||
|
}
|
||
|
|
||
|
if ( !m_bModelIsHidden )
|
||
|
{
|
||
|
if ( !m_pItem->GetInventoryImage() || IsForcingModelUsage() || m_bWeaponAllowInspect || UseRenderTargetAsIcon() )
|
||
|
{
|
||
|
const char *pszModelName = m_pItem->GetPlayerDisplayModel( 0, 0 );
|
||
|
if ( pszModelName )
|
||
|
{
|
||
|
CMDL *pMDL = NULL;
|
||
|
#ifndef PORTAL2 // DOTA COME BACK
|
||
|
if ( m_bUsePedestal )
|
||
|
{
|
||
|
MDLHandle_t hPedestalMDL = mdlcache->FindMDL( "models/weapons/pedestal/pedestal.mdl" );
|
||
|
SetMDL( hPedestalMDL, NULL );
|
||
|
mdlcache->Release( hPedestalMDL ); // counterbalance addref from within FindMDL
|
||
|
|
||
|
MDLHandle_t hItemMDL = mdlcache->FindMDL( pszModelName );
|
||
|
if ( mdlcache->IsErrorModel( hItemMDL ) )
|
||
|
{
|
||
|
hItemMDL = MDLHANDLE_INVALID;
|
||
|
}
|
||
|
m_ItemModel.m_MDL.SetMDL( hItemMDL );
|
||
|
mdlcache->Release( hItemMDL ); // counterbalance addref from within FindMDL
|
||
|
|
||
|
pMDL = &m_ItemModel.m_MDL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MDLHandle_t hMDL = mdlcache->FindMDL( pszModelName );
|
||
|
SetMDL( hMDL, static_cast<IClientRenderable*>( m_pItem ) );
|
||
|
mdlcache->Release( hMDL ); // counterbalance addref from within FindMDL
|
||
|
|
||
|
pMDL = &m_RootMDL.m_MDL;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if ( pMDL )
|
||
|
{
|
||
|
studiohdr_t *pItemStudioHdr = pMDL->GetStudioHdr();
|
||
|
if ( pItemStudioHdr )
|
||
|
{
|
||
|
// Get the appropriate attachment
|
||
|
CStudioHdr HDR( pItemStudioHdr, g_pMDLCache );
|
||
|
if ( m_bUsePedestal )
|
||
|
{
|
||
|
m_iPedestalAttachment = Studio_FindAttachment( &HDR, "pedestal_0" );
|
||
|
if ( m_iPedestalAttachment != -1 )
|
||
|
{
|
||
|
m_ItemModel.m_MDL.m_pProxyData = static_cast<IClientRenderable*>(m_pItem);
|
||
|
m_ItemModel.m_bDisabled = false;
|
||
|
m_ItemModel.m_MDL.m_nSequence = ACT_IDLE;
|
||
|
SetIdentityMatrix( m_ItemModel.m_MDLToWorld );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_iCameraAttachment = Studio_FindAttachment( &HDR, "icon_camera" );
|
||
|
UpdateCameraForIcon();
|
||
|
}
|
||
|
|
||
|
// should we override this model bodygroup
|
||
|
const CEconStyleInfo *pStyle = m_pItem->GetItemDefinition()->GetStyleInfo( m_pItem->GetStyle() );
|
||
|
if ( pStyle && pStyle->GetBodygroupName() != NULL )
|
||
|
{
|
||
|
int iBodyGroup = ::FindBodygroupByName( &HDR, pStyle->GetBodygroupName() );
|
||
|
if ( iBodyGroup != -1 )
|
||
|
{
|
||
|
::SetBodygroup( &HDR, pMDL->m_nBody, iBodyGroup, pStyle->GetBodygroupSubmodelIndex() );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Attach Models
|
||
|
// Attach the models for the item
|
||
|
{
|
||
|
int iTeam = m_pItem->GetItemDefinition()->GetBestVisualTeamData( m_pItem->GetTeamNumber() );
|
||
|
{
|
||
|
// Set attached models if viewable third-person.
|
||
|
const int iNumAttachedModels = m_pItem->GetItemDefinition()->GetNumAttachedModels( iTeam );
|
||
|
for ( int i = 0; i < iNumAttachedModels; ++i )
|
||
|
{
|
||
|
attachedmodel_t *pModel = m_pItem->GetItemDefinition()->GetAttachedModelData( iTeam, i );
|
||
|
LoadAttachedModel( pModel );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Festive
|
||
|
static CSchemaAttributeDefHandle pAttr_is_festivized( "is_festivized" );
|
||
|
if ( pAttr_is_festivized && m_pItem->FindAttribute( pAttr_is_festivized ) )
|
||
|
{
|
||
|
const int iNumAttachedModels = m_pItem->GetItemDefinition()->GetNumAttachedModelsFestivized( iTeam );
|
||
|
for ( int i = 0; i < iNumAttachedModels; ++i )
|
||
|
{
|
||
|
attachedmodel_t *pModel = m_pItem->GetItemDefinition()->GetAttachedModelDataFestivized( iTeam, i );
|
||
|
LoadAttachedModel( pModel );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Stattrak
|
||
|
CAttribute_String attrModule;
|
||
|
static CSchemaAttributeDefHandle pAttr_module( "weapon_uses_stattrak_module" );
|
||
|
if ( m_pItem->FindAttribute( pAttr_module, &attrModule ) && attrModule.has_value() )
|
||
|
{
|
||
|
// Allow for already strange items
|
||
|
bool bIsStrange = false;
|
||
|
if ( m_pItem->GetQuality() == AE_STRANGE )
|
||
|
{
|
||
|
bIsStrange = true;
|
||
|
}
|
||
|
|
||
|
if ( !bIsStrange )
|
||
|
{
|
||
|
// Go over the attributes of the item, if it has any strange attributes the item is strange and don't apply
|
||
|
for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
|
||
|
{
|
||
|
if ( m_pItem->FindAttribute( GetKillEaterAttr_Score( i ) ) )
|
||
|
{
|
||
|
bIsStrange = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( bIsStrange )
|
||
|
{
|
||
|
static CSchemaAttributeDefHandle pAttr_moduleScale( "weapon_stattrak_module_scale" );
|
||
|
// Does it have a stat track module
|
||
|
m_flStatTrackScale = 1.0f;
|
||
|
uint32 unFloatAsUint32 = 1;
|
||
|
if ( m_pItem->FindAttribute( pAttr_moduleScale, &unFloatAsUint32 ) )
|
||
|
{
|
||
|
m_flStatTrackScale = (float&)unFloatAsUint32;
|
||
|
}
|
||
|
|
||
|
MDLHandle_t hStatTrackMDL = mdlcache->FindMDL( "models/weapons/c_models/stattrack.mdl" );
|
||
|
if ( mdlcache->IsErrorModel( hStatTrackMDL ) )
|
||
|
{
|
||
|
hStatTrackMDL = MDLHANDLE_INVALID;
|
||
|
}
|
||
|
m_StatTrackModel.m_MDL.SetMDL( hStatTrackMDL );
|
||
|
mdlcache->Release( hStatTrackMDL ); // counterbalance addref from within FindMDL
|
||
|
|
||
|
m_StatTrackModel.m_MDL.m_pProxyData = static_cast<IClientRenderable*>(pItem);
|
||
|
m_StatTrackModel.m_bDisabled = false;
|
||
|
m_StatTrackModel.m_MDL.m_nSequence = ACT_IDLE;
|
||
|
SetIdentityMatrix( m_StatTrackModel.m_MDLToWorld );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int iTeam = GetLocalPlayerTeam(),
|
||
|
iSkin = iTeam;
|
||
|
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
// If we aren't in a game we default to previewing the red team skin.
|
||
|
if ( iTeam == TEAM_UNASSIGNED )
|
||
|
{
|
||
|
iTeam = TF_TEAM_RED;
|
||
|
}
|
||
|
#endif // TF_CLIENT_DLL
|
||
|
|
||
|
if ( iSkin != TEAM_UNASSIGNED )
|
||
|
{
|
||
|
// Use the first skin for the first team, and the second skin for the other (but default to 0)
|
||
|
iSkin = (iSkin == (FIRST_GAME_TEAM+1)) ? 1 : 0;
|
||
|
}
|
||
|
|
||
|
// Handle styles/visuals overriding the skin.
|
||
|
int iOverrideSkin = m_pItem->GetSkin( iTeam );
|
||
|
if ( iOverrideSkin != -1 )
|
||
|
{
|
||
|
iSkin = iOverrideSkin;
|
||
|
}
|
||
|
|
||
|
SetSkin( iSkin );
|
||
|
|
||
|
if ( m_bUsePedestal )
|
||
|
{
|
||
|
m_ItemModel.m_MDL.m_nSkin = iSkin;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CEmbeddedItemModelPanel::LoadAttachedModel( attachedmodel_t *pModel )
|
||
|
{
|
||
|
if ( !( pModel->m_iModelDisplayFlags & kAttachedModelDisplayFlag_WorldModel ) )
|
||
|
return;
|
||
|
|
||
|
if ( !pModel->m_pszModelName )
|
||
|
{
|
||
|
Warning( "econ item definition '%s' attachment has no model\n", m_pItem->GetItemDefinition()->GetDefinitionName() );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int iIndex = m_AttachedModels.AddToTail();
|
||
|
MDLHandle_t hMDL = mdlcache->FindMDL( pModel->m_pszModelName );
|
||
|
if ( mdlcache->IsErrorModel( hMDL ) )
|
||
|
{
|
||
|
hMDL = MDLHANDLE_INVALID;
|
||
|
}
|
||
|
m_AttachedModels[iIndex].m_MDL.SetMDL( hMDL );
|
||
|
mdlcache->Release( hMDL ); // counterbalance addref from within FindMDL
|
||
|
|
||
|
m_AttachedModels[iIndex].m_MDL.m_pProxyData = static_cast<IClientRenderable*>( m_pItem );
|
||
|
m_AttachedModels[iIndex].m_bDisabled = false;
|
||
|
m_AttachedModels[iIndex].m_MDL.m_nSequence = ACT_IDLE;
|
||
|
SetIdentityMatrix( m_AttachedModels[iIndex].m_MDLToWorld );
|
||
|
}
|
||
|
|
||
|
bool CEmbeddedItemModelPanel::IsLoadingWeaponSkin( void ) const
|
||
|
{
|
||
|
static ConVarRef mat_dxlevel( "mat_dxlevel" );
|
||
|
if ( mat_dxlevel.GetInt() < 90 )
|
||
|
return false;
|
||
|
|
||
|
if ( m_bForceUseModel )
|
||
|
return false;
|
||
|
|
||
|
if ( m_pItem && m_pItem->IsValid() )
|
||
|
{
|
||
|
if ( m_bWeaponAllowInspect && m_pItem->GetCustomPainkKitDefinition() )
|
||
|
{
|
||
|
return m_pItem->GetWeaponSkinBaseCompositor() != NULL || !m_pCachedWeaponIcon || !m_pCachedWeaponIcon->GetTexture();
|
||
|
}
|
||
|
else if ( UseRenderTargetAsIcon() )
|
||
|
{
|
||
|
return !m_pCachedWeaponIcon || !m_pCachedWeaponIcon->GetTexture();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool CEmbeddedItemModelPanel::IsImageNotLoaded( void ) const
|
||
|
{
|
||
|
if ( m_bForceUseModel )
|
||
|
return false;
|
||
|
|
||
|
if ( m_bImageNotLoaded && m_pItem && m_pItem->IsValid() )
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
IMaterial* GetMaterialForImage( CEmbeddedItemModelPanel::InventoryImageType_t eImageType, const char* pszBaseName )
|
||
|
{
|
||
|
IMaterial *pMaterial = NULL;
|
||
|
|
||
|
Assert( pszBaseName );
|
||
|
if ( !pszBaseName )
|
||
|
return NULL;
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
if ( eImageType == CEmbeddedItemModelPanel::IMAGETYPE_SMALL && tf_force_highres_item_image.GetBool() )
|
||
|
{
|
||
|
eImageType = CEmbeddedItemModelPanel::IMAGETYPE_LARGE;
|
||
|
}
|
||
|
#endif // STAGING_ONLY
|
||
|
|
||
|
switch ( eImageType )
|
||
|
{
|
||
|
case CEmbeddedItemModelPanel::IMAGETYPE_SMALL:
|
||
|
pMaterial = g_pMaterialSystem->FindMaterial( pszBaseName, TEXTURE_GROUP_VGUI );
|
||
|
break;
|
||
|
case CEmbeddedItemModelPanel::IMAGETYPE_DETAILED:
|
||
|
pMaterial = g_pMaterialSystem->FindMaterial( CFmtStr("%s_detail",pszBaseName).Access(), TEXTURE_GROUP_VGUI, false );
|
||
|
break;
|
||
|
case CEmbeddedItemModelPanel::IMAGETYPE_LARGE:
|
||
|
pMaterial = g_pMaterialSystem->FindMaterial( CFmtStr("%s_large",pszBaseName).Access(), TEXTURE_GROUP_VGUI );
|
||
|
break;
|
||
|
default:
|
||
|
Assert(0);
|
||
|
}
|
||
|
|
||
|
Assert( pMaterial && !IsErrorMaterial( pMaterial ) );
|
||
|
|
||
|
return pMaterial;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CEmbeddedItemModelPanel::LoadInventoryImage()
|
||
|
{
|
||
|
InventoryImageType_t type = (InventoryImageType_t)m_iInventoryImageType;
|
||
|
if ( m_iInventoryImageType == IMAGETYPE_DETAILED && !m_pItem->GetStaticData()->HasDetailedIcon() )
|
||
|
{
|
||
|
type = IMAGETYPE_LARGE;
|
||
|
}
|
||
|
GetMaterialForImage( type, m_pItem->GetInventoryImage() );
|
||
|
m_bImageNotLoaded = false;
|
||
|
m_iTextureID = -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CEmbeddedItemModelPanel::PerformLayout( void )
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
CleanUpCachedWeaponIcon();
|
||
|
|
||
|
// Nive the "player pos" to the defined distance
|
||
|
if ( m_pItem && m_pItem->IsValid() )
|
||
|
{
|
||
|
if ( m_bUsePedestal )
|
||
|
{
|
||
|
Vector vecOffset = m_BMPResData.m_vecOriginOffset;
|
||
|
vecOffset.x = m_pItem->GetItemDefinition()->GetInspectPanelDistance();
|
||
|
// reset model angle and pos to initial values
|
||
|
SetModelAnglesAndPosition( m_BMPResData.m_angModelPoseRot, vecOffset );
|
||
|
}
|
||
|
else if ( m_iCameraAttachment != -1 )
|
||
|
{
|
||
|
UpdateCameraForIcon();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
static double s_min_time = FLT_MAX;
|
||
|
static double s_max_time = 0.f;
|
||
|
static double s_total_time = 0.f;
|
||
|
#endif // STAGING_ONLY
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CEmbeddedItemModelPanel::Paint( void )
|
||
|
{
|
||
|
if ( !m_pItem || !m_pItem->IsValid() )
|
||
|
return;
|
||
|
|
||
|
if ( m_bModelIsHidden )
|
||
|
{
|
||
|
BaseClass::Paint();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Don't even try to render backpack icon if we're not loaded
|
||
|
if ( m_bImageNotLoaded && !m_bWeaponAllowInspect && !UseRenderTargetAsIcon() )
|
||
|
return;
|
||
|
|
||
|
const char *pszInventoryImage = m_pItem->GetInventoryImage();
|
||
|
|
||
|
CMatRenderContextPtr pRenderContext( materials );
|
||
|
|
||
|
int iWidth = GetWide();
|
||
|
int iHeight = GetTall();
|
||
|
float flTexW = 1.0;
|
||
|
float flTexH = 1.0;
|
||
|
float flTexX = 0.0;
|
||
|
float flTexY = 0.0;
|
||
|
int x = 0;
|
||
|
int y = 0;
|
||
|
|
||
|
// First, try and use the inventory image instead of the model.
|
||
|
bool bIsLoadingWeaponSkin = IsLoadingWeaponSkin();
|
||
|
|
||
|
int iTexture = -1;
|
||
|
if ( !bIsLoadingWeaponSkin && !m_bForceUseModel )
|
||
|
{
|
||
|
// should we override material with cache texture
|
||
|
if ( m_pCachedWeaponIcon && m_pCachedWeaponIcon->GetTexture() )
|
||
|
{
|
||
|
// Clear out the composited texture--we're finished with it.
|
||
|
m_pItem->SetWeaponSkinBase( NULL );
|
||
|
// The compositor should have been cleaned up by the material proxy.
|
||
|
Assert( m_pItem->GetWeaponSkinBaseCompositor() == NULL );
|
||
|
|
||
|
if ( !m_pCachedWeaponMaterial && g_pMaterialSystem )
|
||
|
{
|
||
|
const char *pszTextureName = m_pCachedWeaponIcon->GetTexture()->GetName();
|
||
|
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
|
||
|
pVMTKeyValues->SetString( "$basetexture", pszTextureName );
|
||
|
pVMTKeyValues->SetInt( "$translucent", 1 );
|
||
|
pVMTKeyValues->SetInt( "$vertexcolor", 1 );
|
||
|
IMaterial *pMaterial = g_pMaterialSystem->FindProceduralMaterial( pszTextureName, TEXTURE_GROUP_VGUI, pVMTKeyValues );
|
||
|
SafeAssign( &m_pCachedWeaponMaterial, pMaterial );
|
||
|
|
||
|
bool bFound = false;
|
||
|
IMaterialVar *pVar = m_pCachedWeaponMaterial->FindVar( "$basetexture", &bFound );
|
||
|
if ( bFound && pVar )
|
||
|
{
|
||
|
pVar->SetTextureValue( m_pCachedWeaponIcon->GetTexture() );
|
||
|
m_pCachedWeaponMaterial->RefreshPreservingMaterialVars();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_iCachedTextureID == -1 )
|
||
|
{
|
||
|
//m_pCachedWeaponIcon->GetTexture()->SaveToFile( CFmtStr( "%d_weapon_skin_cache.tga", m_pItem->GetItemDefIndex() ) );
|
||
|
m_iCachedTextureID = g_pMatSystemSurface->DrawGetTextureId( m_pCachedWeaponIcon->GetTexture() );
|
||
|
g_pMatSystemSurface->DrawSetTextureMaterial( m_iCachedTextureID, m_pCachedWeaponMaterial );
|
||
|
}
|
||
|
iTexture = m_iCachedTextureID;
|
||
|
x = 0;
|
||
|
y = 0;
|
||
|
flTexX = flTexY = 0.f;
|
||
|
|
||
|
int iMappingWidth = m_pCachedWeaponMaterial->GetMappingWidth();
|
||
|
int iMappingHeight = m_pCachedWeaponMaterial->GetMappingHeight();
|
||
|
if ( iWidth > iMappingWidth || iHeight > iMappingHeight )
|
||
|
{
|
||
|
flTexW = 1.f;
|
||
|
flTexH = 1.f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
flTexW = (float)iWidth / iMappingWidth;
|
||
|
flTexH = (float)iHeight / iMappingHeight;
|
||
|
}
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
if ( tf_unique_icon_perf_debug.GetBool() && m_flStartUpdateTime != 0 )
|
||
|
{
|
||
|
double flTimeTaken = Plat_FloatTime() - m_flStartUpdateTime;
|
||
|
m_flStartUpdateTime = 0.0;
|
||
|
s_min_time = MIN( s_min_time, flTimeTaken );
|
||
|
s_max_time = MAX( s_max_time, flTimeTaken );
|
||
|
s_total_time += flTimeTaken;
|
||
|
DevMsg( "took %.3f with min %.3f max %.3f with total %.3f\n", flTimeTaken, s_min_time, s_max_time, s_total_time );
|
||
|
}
|
||
|
#endif // STAGING_ONLY
|
||
|
}
|
||
|
else if ( pszInventoryImage )
|
||
|
{
|
||
|
// Look up the material (use the large one if we've been told to)
|
||
|
IMaterial *pMaterial = GetMaterialForImage( (CEmbeddedItemModelPanel::InventoryImageType_t)m_iInventoryImageType, pszInventoryImage );
|
||
|
|
||
|
int iCenter[2];
|
||
|
iCenter[0] = x + (iWidth * 0.5);
|
||
|
iCenter[1] = y + (iHeight * 0.5);
|
||
|
|
||
|
// Maintain image aspect ratios. Fit to height.
|
||
|
int iPosition[2] = {0,0};
|
||
|
int iSize[2] = {0,0};
|
||
|
m_pItem->GetInventoryImageData( iPosition, iSize );
|
||
|
|
||
|
if ( m_bForceSquareImage )
|
||
|
{
|
||
|
iSize[0] = MAX( iSize[0], iSize[1] );
|
||
|
iSize[1] = iSize[0];
|
||
|
}
|
||
|
if ( !iSize[0] && !iSize[1] )
|
||
|
{
|
||
|
iSize[0] = pMaterial->GetMappingWidth();
|
||
|
iSize[1] = pMaterial->GetMappingHeight();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bool bForceHighRes = false;
|
||
|
#ifdef STAGING_ONLY
|
||
|
bForceHighRes = tf_force_highres_item_image.GetBool();
|
||
|
#endif // STAGING_ONLY
|
||
|
if ( m_iInventoryImageType != IMAGETYPE_SMALL || bForceHighRes )
|
||
|
{
|
||
|
// Normal is 128*128, large is 512x512
|
||
|
iSize[0] *= 4;
|
||
|
iSize[1] *= 4;
|
||
|
}
|
||
|
|
||
|
flTexW = ((float)iSize[0] / (float)pMaterial->GetMappingWidth());
|
||
|
flTexH = ((float)iSize[1] / (float)pMaterial->GetMappingHeight());
|
||
|
flTexX = ( 1.0 - flTexW ) * 0.5;
|
||
|
flTexY = ( 1.0 - flTexH ) * 0.5;
|
||
|
}
|
||
|
if ( iPosition[0] || iPosition[1] )
|
||
|
{
|
||
|
x += XRES(iPosition[0]);
|
||
|
y += YRES(iPosition[1]);
|
||
|
}
|
||
|
|
||
|
float flRatio = ((float)iSize[0] / (float)iSize[1]);
|
||
|
if ( flRatio != ((float)iWidth / (float)iHeight) )
|
||
|
{
|
||
|
// Fit to the height
|
||
|
int iCenterX = x + (iWidth * 0.5);
|
||
|
iWidth = iHeight * flRatio;
|
||
|
x = iCenterX - (iWidth * 0.5);
|
||
|
}
|
||
|
|
||
|
// Reload our texture, if we need to
|
||
|
if ( m_iTextureID == -1 )
|
||
|
{
|
||
|
m_iTextureID = vgui::surface()->DrawGetTextureId( pMaterial->GetName() );
|
||
|
|
||
|
// If we didn't find it, create a new one
|
||
|
if ( m_iTextureID == -1 )
|
||
|
{
|
||
|
m_iTextureID = vgui::surface()->CreateNewTextureID();
|
||
|
g_pMatSystemSurface->DrawSetTextureMaterial( m_iTextureID, pMaterial );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
iTexture = m_iTextureID;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// draw texture if we have a valid texture
|
||
|
if ( iTexture != -1 )
|
||
|
{
|
||
|
surface()->DrawSetTexture( iTexture );
|
||
|
|
||
|
if ( m_bGreyedOut )
|
||
|
{
|
||
|
surface()->DrawSetColor( 96, 96, 96, 255 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
surface()->DrawSetColor( 255, 255, 255, 255 );
|
||
|
}
|
||
|
surface()->DrawTexturedSubRect( x, y, x + iWidth, y + iHeight, flTexX, flTexY, flTexX + flTexW, flTexY + flTexH );
|
||
|
|
||
|
// Draw the overlay image now, and tint it by the tint attribute (if we have one)
|
||
|
for ( int i=0; i<m_pItem->GetInventoryOverlayImageCount(); i++ )
|
||
|
{
|
||
|
const char *pszInventoryOverlayImage = m_pItem->GetInventoryOverlayImage( i );
|
||
|
IMaterial *pOverlayMaterial = GetMaterialForImage( (CEmbeddedItemModelPanel::InventoryImageType_t)m_iInventoryImageType, pszInventoryOverlayImage );
|
||
|
|
||
|
if ( !pOverlayMaterial )
|
||
|
continue;
|
||
|
|
||
|
int iTextureIDIdx = m_iOverlayTextureIDs.Find(i);
|
||
|
if ( (iTextureIDIdx == m_iOverlayTextureIDs.InvalidIndex()
|
||
|
|| m_iOverlayTextureIDs[iTextureIDIdx] == -1 ) )
|
||
|
{
|
||
|
int iTextureID = vgui::surface()->DrawGetTextureId( pOverlayMaterial->GetName() );
|
||
|
|
||
|
// If we didn't find it, create a new one
|
||
|
if ( iTextureID == -1 )
|
||
|
{
|
||
|
iTextureID = vgui::surface()->CreateNewTextureID();
|
||
|
g_pMatSystemSurface->DrawSetTextureMaterial( iTextureID, pOverlayMaterial );
|
||
|
}
|
||
|
|
||
|
m_iOverlayTextureIDs.Insert( i, iTextureID );
|
||
|
}
|
||
|
|
||
|
surface()->DrawSetTexture( m_iOverlayTextureIDs[m_iOverlayTextureIDs.Find( i )] );
|
||
|
|
||
|
int iRGB = m_pItem->GetModifiedRGBValue( i == 0 );
|
||
|
Color col;
|
||
|
col.SetColor( clamp( (iRGB & 0xFF0000) >> 16, 0, 255 ), clamp( (iRGB & 0xFF00) >> 8, 0, 255 ), clamp( (iRGB & 0xFF), 0, 255 ), 255 );
|
||
|
// Dim this color if the item is currently greyed out
|
||
|
float flColorScale = m_bGreyedOut ? 96.f / 255.f : 1.f;
|
||
|
col.SetColor( col.r() * flColorScale, col.g() * flColorScale, col.b() * flColorScale, col.a() );
|
||
|
|
||
|
surface()->DrawSetColor( col );
|
||
|
|
||
|
surface()->DrawTexturedSubRect( x, y, x + iWidth, y + iHeight, flTexX, flTexY, flTexX + flTexW, flTexY + flTexH );
|
||
|
}
|
||
|
|
||
|
// Draw strangifier item on top of strangifier bottles
|
||
|
if ( m_pszToolTargetItemImage && m_pszToolTargetItemImage[0] )
|
||
|
{
|
||
|
IMaterial* pToolTargetItemMaterial = GetMaterialForImage( (CEmbeddedItemModelPanel::InventoryImageType_t)m_iInventoryImageType, m_pszToolTargetItemImage );
|
||
|
|
||
|
if ( m_iToolTargetItemTextureID == -1 )
|
||
|
{
|
||
|
m_iToolTargetItemTextureID = vgui::surface()->DrawGetTextureId( pToolTargetItemMaterial->GetName() );
|
||
|
|
||
|
// If we didn't find it, create a new one
|
||
|
if ( m_iToolTargetItemTextureID == -1 )
|
||
|
{
|
||
|
m_iToolTargetItemTextureID = vgui::surface()->CreateNewTextureID();
|
||
|
g_pMatSystemSurface->DrawSetTextureMaterial( m_iToolTargetItemTextureID, pToolTargetItemMaterial );
|
||
|
}
|
||
|
|
||
|
CAttribute_String attrToolTargetItemIconOffset;
|
||
|
static CSchemaAttributeDefHandle pAttrDef_ToolTargetItemIconOffset( "tool_target_item_icon_offset" );
|
||
|
if ( m_pItem->FindAttribute( pAttrDef_ToolTargetItemIconOffset, &attrToolTargetItemIconOffset ) && attrToolTargetItemIconOffset.has_value() )
|
||
|
{
|
||
|
UTIL_StringToVector( m_vecToolTargetItemImageOffset.Base(), attrToolTargetItemIconOffset.value().c_str() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
surface()->DrawSetTexture( m_iToolTargetItemTextureID );
|
||
|
|
||
|
int iStrangeX = x + ( iWidth * m_vecToolTargetItemImageOffset.x );
|
||
|
int iStrangeY = y + ( iHeight * m_vecToolTargetItemImageOffset.y );
|
||
|
float flScale = m_vecToolTargetItemImageOffset.z;
|
||
|
|
||
|
surface()->DrawTexturedSubRect( iStrangeX,
|
||
|
iStrangeY,
|
||
|
iStrangeX + (iWidth * flScale),
|
||
|
iStrangeY + (iHeight * flScale),
|
||
|
flTexX,
|
||
|
flTexY,
|
||
|
flTexX + (flTexW ),
|
||
|
flTexY + (flTexH ) );
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
item_model_cache_t *pCacheRenderTarget = NULL;
|
||
|
const char *pszCacheRenderTargetName = NULL;
|
||
|
// find available render target
|
||
|
for ( int i=0; i<ITEM_MODEL_IMAGE_CACHE_SIZE; ++i )
|
||
|
{
|
||
|
CEmbeddedItemModelPanel *pLockPanel = g_ItemModelImageCache[i].m_hModelPanelLock.Get();
|
||
|
|
||
|
// found available render target?
|
||
|
if ( pLockPanel == NULL )
|
||
|
{
|
||
|
pszCacheRenderTargetName = m_bOfflineIconGeneration ? "offline_icon_generation" : g_ItemModelPanelRenderTargetNames[i];
|
||
|
pCacheRenderTarget = &g_ItemModelImageCache[i];
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// waiting for async copy to finish
|
||
|
if ( pLockPanel->m_pCachedWeaponIcon && pLockPanel->m_pCachedWeaponIcon->GetTexture() )
|
||
|
{
|
||
|
g_ItemModelImageCache[i].Clear();
|
||
|
|
||
|
pszCacheRenderTargetName = m_bOfflineIconGeneration ? "offline_icon_generation" : g_ItemModelPanelRenderTargetNames[i];
|
||
|
pCacheRenderTarget = &g_ItemModelImageCache[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// can't find available cache render target, don't do anything
|
||
|
if ( !pszCacheRenderTargetName || !pCacheRenderTarget )
|
||
|
{
|
||
|
BaseClass::Paint();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Turn off depth-write to dest alpha so that we get white there instead. The code that uses
|
||
|
// the render target needs a mask of where stuff was rendered.
|
||
|
pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA, false );
|
||
|
|
||
|
bool bUseRenderTarget = !m_bForceUseModel && ( UseRenderTargetAsIcon() || bIsLoadingWeaponSkin );
|
||
|
bool bRenderToTexture = m_bRenderToTexture;
|
||
|
if ( bUseRenderTarget )
|
||
|
{
|
||
|
g_pMatSystemSurface->Set3DPaintTempRenderTarget( pszCacheRenderTargetName );
|
||
|
}
|
||
|
else if ( m_bUseParticle )
|
||
|
{
|
||
|
// we want to render particle with this model. don't render to texture
|
||
|
m_bRenderToTexture = false;
|
||
|
}
|
||
|
|
||
|
// make sure the weapon skin is ready before we render the model
|
||
|
bool bDrawWeaponWithSkin = bIsLoadingWeaponSkin && m_pCachedWeaponIcon == NULL && m_pItem->GetWeaponSkinBase();
|
||
|
|
||
|
m_pItem->SetWeaponSkinBaseCreateFlags( TEX_COMPOSITE_CREATE_FLAGS_NO_COMPRESSION | TEX_COMPOSITE_CREATE_FLAGS_NO_MIPMAPS );
|
||
|
|
||
|
BaseClass::Paint();
|
||
|
|
||
|
m_bRenderToTexture = bRenderToTexture;
|
||
|
|
||
|
// copy the rendered weapon skin from the render target
|
||
|
if ( !m_bForceUseModel && ( UseRenderTargetAsIcon() || bDrawWeaponWithSkin ) && !m_pCachedWeaponIcon )
|
||
|
{
|
||
|
char buffer[_MAX_PATH];
|
||
|
V_sprintf_safe( buffer, "proc/icon/item%d_id%lld_w%d_h%d", m_pItem->GetItemDefIndex(), m_pItem->GetID(), iWidth, iHeight );
|
||
|
SafeAssign( &m_pCachedWeaponIcon, new CIconRenderReceiver() );
|
||
|
|
||
|
// If the icon still exists in the material system, don't bother regenerating it.
|
||
|
if ( materials->IsTextureLoaded( buffer ) )
|
||
|
{
|
||
|
ITexture* resTexture = materials->FindTexture( buffer, TEXTURE_GROUP_RUNTIME_COMPOSITE, false, 0 );
|
||
|
if ( resTexture && resTexture->IsError() == false )
|
||
|
{
|
||
|
m_pCachedWeaponIcon->OnAsyncCreateComplete( resTexture, NULL );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No icon available yet, need to create it.
|
||
|
ITexture *pRenderTarget = g_pMaterialSystem->FindTexture( pszCacheRenderTargetName, TEXTURE_GROUP_RENDER_TARGET );
|
||
|
if ( pRenderTarget )
|
||
|
{
|
||
|
pRenderContext->AsyncCreateTextureFromRenderTarget( pRenderTarget, buffer, IMAGE_FORMAT_RGBA8888, false, 0, m_pCachedWeaponIcon, NULL );
|
||
|
|
||
|
pCacheRenderTarget->iItemID = m_pItem->GetItemID();
|
||
|
pCacheRenderTarget->iItemDefinitionIndex = m_pItem->GetItemDefIndex();
|
||
|
pCacheRenderTarget->iWidth = iWidth;
|
||
|
pCacheRenderTarget->iHeight = iHeight;
|
||
|
pCacheRenderTarget->m_hModelPanelLock = this;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( bUseRenderTarget )
|
||
|
{
|
||
|
g_pMatSystemSurface->Reset3DPaintTempRenderTarget();
|
||
|
}
|
||
|
|
||
|
if ( m_flModelRotateYawSpeed != 0 )
|
||
|
{
|
||
|
m_angPlayer[YAW] += m_flModelRotateYawSpeed * gpGlobals->frametime;
|
||
|
SetModelAnglesAndPosition( m_angPlayer, m_vecPlayerPos );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
ITexture *CEmbeddedItemModelPanel::GetCachedGeneratedIcon()
|
||
|
{
|
||
|
return m_pCachedWeaponIcon ? m_pCachedWeaponIcon->GetTexture() : NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CEmbeddedItemModelPanel::UpdateParticle(
|
||
|
IMatRenderContext *pRenderContext,
|
||
|
CStudioHdr *pStudioHdr,
|
||
|
MDLHandle_t mdlHandle,
|
||
|
matrix3x4_t *pWorldMatrix
|
||
|
)
|
||
|
{
|
||
|
if ( !m_bUseParticle )
|
||
|
return false;
|
||
|
|
||
|
if ( m_pItemParticle && m_pItemParticle->m_bIsUpdateToDate )
|
||
|
return false;
|
||
|
|
||
|
if ( !m_pItem || !m_pItem->IsValid() )
|
||
|
return false;
|
||
|
|
||
|
attachedparticlesystem_t *pParticleSystem = NULL;
|
||
|
|
||
|
// do community_sparkle effect if this is a community item?
|
||
|
const int iQualityParticleType = m_pItem->GetQualityParticleType();
|
||
|
if ( iQualityParticleType > 0 )
|
||
|
{
|
||
|
pParticleSystem = GetItemSchema()->GetAttributeControlledParticleSystem( iQualityParticleType );
|
||
|
}
|
||
|
|
||
|
if ( !pParticleSystem )
|
||
|
{
|
||
|
// does this hat even have a particle effect
|
||
|
static CSchemaAttributeDefHandle pAttrDef_AttachParticleEffect( "attach particle effect" );
|
||
|
uint32 iValue = 0;
|
||
|
if ( !m_pItem->FindAttribute( pAttrDef_AttachParticleEffect, &iValue ) )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const float& value_as_float = (float&)iValue;
|
||
|
pParticleSystem = GetItemSchema()->GetAttributeControlledParticleSystem( value_as_float );
|
||
|
}
|
||
|
|
||
|
// failed to find any particle effect
|
||
|
if ( !pParticleSystem )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Team Color
|
||
|
if ( m_pItem->GetTeamNumber() == TF_TEAM_BLUE && V_stristr( pParticleSystem->pszSystemName, "_teamcolor_red" ))
|
||
|
{
|
||
|
static char pBlue[256];
|
||
|
V_StrSubst( pParticleSystem->pszSystemName, "_teamcolor_red", "_teamcolor_blue", pBlue, 256 );
|
||
|
pParticleSystem = GetItemSchema()->FindAttributeControlledParticleSystem( pBlue );
|
||
|
if ( !pParticleSystem )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if this thing has a bip_head or prp_helmet (aka a hat)
|
||
|
int iBone = Studio_BoneIndexByName( pStudioHdr, "bip_head" );
|
||
|
if ( iBone < 0 )
|
||
|
{
|
||
|
iBone = Studio_BoneIndexByName( pStudioHdr, "prp_helmet" );
|
||
|
if ( iBone < 0 )
|
||
|
{
|
||
|
iBone = Studio_BoneIndexByName( pStudioHdr, "prp_hat" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default to root
|
||
|
if ( iBone < 0 )
|
||
|
{
|
||
|
iBone = 0;
|
||
|
}
|
||
|
|
||
|
// Get Use Head Origin
|
||
|
CUtlVector< int > vecAttachments;
|
||
|
static CSchemaAttributeDefHandle pAttrDef_UseHead( "particle effect use head origin" );
|
||
|
uint32 iUseHead = 0;
|
||
|
if ( !m_pItem->FindAttribute( pAttrDef_UseHead, &iUseHead ) || !iUseHead == 0 )
|
||
|
{
|
||
|
// not using head? try searching for attachment points
|
||
|
for ( int i=0; i<ARRAYSIZE( pParticleSystem->pszControlPoints ); ++i )
|
||
|
{
|
||
|
const char *pszAttachmentName = pParticleSystem->pszControlPoints[i];
|
||
|
if ( pszAttachmentName && pszAttachmentName[0] )
|
||
|
{
|
||
|
int iAttachment = Studio_FindAttachment( pStudioHdr, pszAttachmentName );
|
||
|
if ( iAttachment < 0 )
|
||
|
continue;
|
||
|
|
||
|
vecAttachments.AddToTail( iAttachment );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static char pszFullname[256];
|
||
|
const char* pszSystemName = pParticleSystem->pszSystemName;
|
||
|
// Weapon Remap for a Base Effect to be used on a specific weapon
|
||
|
if ( pParticleSystem->bUseSuffixName && m_pItem && m_pItem->GetItemDefinition()->GetParticleSuffix() )
|
||
|
{
|
||
|
V_strcpy_safe( pszFullname, pParticleSystem->pszSystemName );
|
||
|
V_strcat_safe( pszFullname, "_" );
|
||
|
V_strcat_safe( pszFullname, m_pItem->GetItemDefinition()->GetParticleSuffix() );
|
||
|
pszSystemName = pszFullname;
|
||
|
}
|
||
|
|
||
|
// Update the Particles and render them
|
||
|
if ( m_pItemParticle )
|
||
|
{
|
||
|
// Check if its a new particle system
|
||
|
if ( V_strcmp( m_pItemParticle->m_pParticleSystem->GetName(), pszSystemName ) )
|
||
|
{
|
||
|
SafeDeleteParticleData( &m_pItemParticle );
|
||
|
m_pItemParticle = CreateParticleData( pszSystemName );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// create
|
||
|
m_pItemParticle = CreateParticleData( pszSystemName );
|
||
|
}
|
||
|
|
||
|
// Particle system does not exist
|
||
|
if ( !m_pItemParticle )
|
||
|
return false;
|
||
|
|
||
|
// Get offset if it exists (and if we're using head offset)
|
||
|
static CSchemaAttributeDefHandle pAttrDef_VerticalOffset( "particle effect vertical offset" );
|
||
|
uint32 iOffset = 0;
|
||
|
Vector vecParticleOffset( 0, 0, 0 );
|
||
|
if ( iUseHead > 0 && m_pItem->FindAttribute( pAttrDef_VerticalOffset, &iOffset ) )
|
||
|
{
|
||
|
vecParticleOffset.z = (float&)iOffset;
|
||
|
}
|
||
|
|
||
|
m_pItemParticle->UpdateControlPoints( pStudioHdr, pWorldMatrix, vecAttachments, 0, vecParticleOffset );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CEmbeddedItemModelPanel::RenderStatTrack( CStudioHdr *pStudioHdr, matrix3x4_t *pWorldMatrix )
|
||
|
{
|
||
|
// Draw the merge MDLs.
|
||
|
if ( !m_StatTrackModel.m_bDisabled )
|
||
|
{
|
||
|
matrix3x4_t matMergeBoneToWorld[MAXSTUDIOBONES];
|
||
|
|
||
|
// Get the merge studio header.
|
||
|
studiohdr_t *pStatTrackStudioHdr = m_StatTrackModel.m_MDL.GetStudioHdr();
|
||
|
matrix3x4_t *pMergeBoneToWorld = &matMergeBoneToWorld[0];
|
||
|
|
||
|
// If we have a valid mesh, bonemerge it. If we have an invalid mesh we can't bonemerge because
|
||
|
// it'll crash trying to pull data from the missing header.
|
||
|
if ( pStatTrackStudioHdr != NULL )
|
||
|
{
|
||
|
CStudioHdr mergeHdr( pStatTrackStudioHdr, g_pMDLCache );
|
||
|
m_StatTrackModel.m_MDL.SetupBonesWithBoneMerge( &mergeHdr, pMergeBoneToWorld, pStudioHdr, pWorldMatrix, m_StatTrackModel.m_MDLToWorld );
|
||
|
for ( int i=0; i<mergeHdr.numbones(); ++i )
|
||
|
{
|
||
|
MatrixScaleBy( m_flStatTrackScale, pMergeBoneToWorld[i] );
|
||
|
}
|
||
|
m_StatTrackModel.m_MDL.Draw( m_StatTrackModel.m_MDLToWorld, pMergeBoneToWorld );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool CEmbeddedItemModelPanel::RenderAttachedModels( CStudioHdr *pStudioHdr, matrix3x4_t *pWorldMatrix )
|
||
|
{
|
||
|
// Draw the merge MDLs.
|
||
|
FOR_EACH_VEC( m_AttachedModels, iModel )
|
||
|
{
|
||
|
matrix3x4_t matMergeBoneToWorld[MAXSTUDIOBONES];
|
||
|
|
||
|
// Get the merge studio header.
|
||
|
studiohdr_t *pAttachedStudioHdr = m_AttachedModels[iModel].m_MDL.GetStudioHdr();
|
||
|
matrix3x4_t *pMergeBoneToWorld = &matMergeBoneToWorld[0];
|
||
|
|
||
|
// If we have a valid mesh, bonemerge it. If we have an invalid mesh we can't bonemerge because
|
||
|
// it'll crash trying to pull data from the missing header.
|
||
|
if ( pAttachedStudioHdr != NULL )
|
||
|
{
|
||
|
CStudioHdr mergeHdr( pAttachedStudioHdr, g_pMDLCache );
|
||
|
m_AttachedModels[iModel].m_MDL.SetupBonesWithBoneMerge( &mergeHdr, pMergeBoneToWorld, pStudioHdr, pWorldMatrix, m_AttachedModels[iModel].m_MDLToWorld );
|
||
|
m_AttachedModels[iModel].m_MDL.Draw( m_AttachedModels[iModel].m_MDLToWorld, pMergeBoneToWorld );
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CEmbeddedItemModelPanel::RenderingRootModel( IMatRenderContext *pRenderContext, CStudioHdr *pStudioHdr, MDLHandle_t mdlHandle, matrix3x4_t *pWorldMatrix )
|
||
|
{
|
||
|
// No model? Bail
|
||
|
if ( m_ItemModel.m_bDisabled )
|
||
|
{
|
||
|
// no model means not using pedestal. just use pStudioHdr to find the attachment points
|
||
|
UpdateParticle( pRenderContext, pStudioHdr, mdlHandle, pWorldMatrix );
|
||
|
RenderStatTrack( pStudioHdr, pWorldMatrix );
|
||
|
RenderAttachedModels( pStudioHdr, pWorldMatrix );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
studiohdr_t *pItemStudioHdr = m_ItemModel.m_MDL.GetStudioHdr();
|
||
|
|
||
|
if ( pItemStudioHdr != NULL )
|
||
|
{
|
||
|
matrix3x4_t matIdentity;
|
||
|
SetIdentityMatrix( matIdentity );
|
||
|
|
||
|
matrix3x4_t *pBoneToWorld = g_pStudioRender->LockBoneMatrices( pItemStudioHdr->numbones );
|
||
|
m_ItemModel.m_MDL.SetUpBones( matIdentity, pItemStudioHdr->numbones, pBoneToWorld );
|
||
|
|
||
|
// Get attachment transform
|
||
|
mstudioattachment_t attach = pItemStudioHdr->pAttachment( m_iPedestalAttachment );
|
||
|
matrix3x4_t matLocalToWorld;
|
||
|
matrix3x4_t matWorldToLocal;
|
||
|
matrix3x4_t matTransform;
|
||
|
|
||
|
ConcatTransforms( pBoneToWorld[ attach.localbone ], attach.local, matLocalToWorld );
|
||
|
MatrixInvert( matLocalToWorld, matWorldToLocal );
|
||
|
ConcatTransforms( m_RootMDL.m_MDLToWorld, matWorldToLocal, matTransform );
|
||
|
|
||
|
m_ItemModel.m_MDL.SetUpBones( matTransform, pItemStudioHdr->numbones, pBoneToWorld );
|
||
|
|
||
|
g_pStudioRender->UnlockBoneMatrices();
|
||
|
|
||
|
IMaterial* pOverrideMaterial = GetOverrideMaterial( m_ItemModel.m_MDL.GetMDL() );
|
||
|
if ( pOverrideMaterial != NULL )
|
||
|
g_pStudioRender->ForcedMaterialOverride( pOverrideMaterial );
|
||
|
|
||
|
m_ItemModel.m_MDL.Draw( m_ItemModel.m_MDLToWorld, pBoneToWorld );
|
||
|
|
||
|
if ( pOverrideMaterial != NULL )
|
||
|
g_pStudioRender->ForcedMaterialOverride( NULL );
|
||
|
|
||
|
CStudioHdr HDR( pItemStudioHdr, g_pMDLCache );
|
||
|
|
||
|
// update particle with the actual item model pItemStudioHdr
|
||
|
UpdateParticle( pRenderContext, &HDR, mdlHandle, pBoneToWorld );
|
||
|
RenderStatTrack( &HDR, pBoneToWorld );
|
||
|
RenderAttachedModels( &HDR, pBoneToWorld );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
IMaterial *CEmbeddedItemModelPanel::GetOverrideMaterial( MDLHandle_t mdlHandle )
|
||
|
{
|
||
|
// This matches the check in RenderingRootModel, if we're not on a pedestal
|
||
|
// then we expect mdlHandle to not match m_ItemModel and that's fine--we should
|
||
|
// just get the override from the m_pItem
|
||
|
if ( !m_ItemModel.m_bDisabled && m_ItemModel.m_MDL.GetMDL() != mdlHandle )
|
||
|
return NULL;
|
||
|
|
||
|
if ( !m_pItem )
|
||
|
return NULL;
|
||
|
|
||
|
int iTeam = GetLocalPlayerTeam();
|
||
|
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
// If we aren't in a game we default to previewing the red team skin.
|
||
|
if ( iTeam == TEAM_UNASSIGNED )
|
||
|
{
|
||
|
iTeam = TF_TEAM_RED;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return m_pItem->GetMaterialOverride( iTeam );
|
||
|
}
|
||
|
|
||
|
|
||
|
float CItemModelPanel::sm_flLoadingTimeThisFrame = 0.0f;
|
||
|
int CItemModelPanel::sm_nCurrentDecriptionUpdateFrame = 0;
|
||
|
CItemModelPanel::eLoadingType_t CItemModelPanel::se_CurrentLoadingTask = LOADING_ICONS;
|
||
|
int CItemModelPanel::sai_NumLoadingRequests[NUM_LOADING_TYPES] = {0,0,0};
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CItemModelPanel::CItemModelPanel( vgui::Panel *parent, const char *name ) : vgui::EditablePanel( parent, name )
|
||
|
{
|
||
|
m_pModelPanel = NULL;
|
||
|
m_pItemNameLabel = NULL;
|
||
|
m_pPaintIcon = NULL;
|
||
|
m_pTF2Icon = NULL;
|
||
|
m_pItemAttribLabel = NULL;
|
||
|
m_pItemCollectionNameLabel = NULL;
|
||
|
m_pItemCollectionListLabel = NULL;
|
||
|
m_pItemCollectionHighlight = NULL;
|
||
|
m_pItemEquippedLabel = NULL;
|
||
|
m_pItemQuantityLabel = NULL;
|
||
|
m_pVisionRestrictionImage = NULL;
|
||
|
m_pIsStrangeImage = NULL;
|
||
|
m_pIsUnusualImage = NULL;
|
||
|
m_pIsLoanerImage = NULL;
|
||
|
m_pSeriesLabel = NULL;
|
||
|
m_pMainContentContainer = NULL;
|
||
|
m_pLoadingSpinner = NULL;
|
||
|
// m_ItemData = NULL;
|
||
|
m_nCollectionItemLoaded = LOADED_COLLECTION_NONE;
|
||
|
m_pFontNameSmallest = vgui::INVALID_FONT;
|
||
|
m_pFontNameSmall = vgui::INVALID_FONT;
|
||
|
m_pFontNameLarge = vgui::INVALID_FONT;
|
||
|
m_pFontAttribSmallest = vgui::INVALID_FONT;
|
||
|
m_pFontAttribSmall = vgui::INVALID_FONT;
|
||
|
m_pFontAttribLarge = vgui::INVALID_FONT;
|
||
|
|
||
|
m_pszNoItemText = NULL;
|
||
|
m_pwcNoItemText = NULL;
|
||
|
m_pwcNoItemAttrib = NULL;
|
||
|
REGISTER_COLOR_AS_OVERRIDABLE( m_NoItemTextColor, "noitem_textcolor" );
|
||
|
|
||
|
m_bClickable = false;
|
||
|
m_bMouseOver = false;
|
||
|
m_bSelected = false;
|
||
|
m_bShowEquipped = false;
|
||
|
m_bForceShowEquipped = false;
|
||
|
m_bShowQuantity = false;
|
||
|
m_pszGreyedOutReason = NULL;
|
||
|
m_bShowGreyedOutTooltip = false;
|
||
|
m_bShouldSendPanelEnterExits = false;
|
||
|
m_bContainedItem = false;
|
||
|
m_bShowOthersGiftWrappedItems = false;
|
||
|
m_bDescriptionDirty = false;
|
||
|
m_nRecipeMatchingIndex = 0;
|
||
|
|
||
|
m_pContainedItemPanel = NULL;
|
||
|
|
||
|
m_bFakeButton = false;
|
||
|
|
||
|
m_mapMatchingAttributes.SetLessFunc( DefLessFunc( attrib_definition_index_t ) );
|
||
|
|
||
|
SetActAsButton( false, false );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CItemModelPanel::~CItemModelPanel( void )
|
||
|
{
|
||
|
CleanupNoItemWChars();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
// These pointers must be zeroed here because their memory may be freed
|
||
|
// by LoadControlSettings *and* if they remain non-zero they may be dereferenced
|
||
|
// before LoadControlSettings returns. This causes reliable crashes if you
|
||
|
// go to the store, shop, change resolutions, then return to the store -- and
|
||
|
// if you use pageheap/AppVerifier.
|
||
|
// This set of pointers is simply the set of pointers that are initialized after
|
||
|
// LoadControlSettings.
|
||
|
m_pModelPanel = NULL;
|
||
|
m_pItemNameLabel = NULL;
|
||
|
m_pItemAttribLabel = NULL;
|
||
|
m_pItemCollectionNameLabel = NULL;
|
||
|
m_pItemCollectionListLabel = NULL;
|
||
|
m_pItemEquippedLabel = NULL;
|
||
|
m_pItemQuantityLabel = NULL;
|
||
|
m_pVisionRestrictionImage = NULL;
|
||
|
m_pIsStrangeImage = NULL;
|
||
|
m_pIsUnusualImage = NULL;
|
||
|
m_pIsLoanerImage = NULL;
|
||
|
m_pSeriesLabel = NULL;
|
||
|
m_pMatchesLabel = NULL;
|
||
|
m_pPaintIcon = NULL;
|
||
|
m_pTF2Icon = NULL;
|
||
|
m_pFontNameSmallest = NULL;
|
||
|
m_pFontNameSmall = NULL;
|
||
|
m_pFontNameLarge = NULL;
|
||
|
m_pFontNameLarger = NULL;
|
||
|
m_pFontAttribSmallest = NULL;
|
||
|
m_pFontAttribSmall = NULL;
|
||
|
m_pFontAttribLarge = NULL;
|
||
|
m_pFontAttribLarger = NULL;
|
||
|
m_pContainedItemPanel = NULL;
|
||
|
m_pMainContentContainer = NULL;
|
||
|
m_pLoadingSpinner = NULL;
|
||
|
m_nCollectionItemLoaded = LOADED_COLLECTION_NONE;
|
||
|
LoadResFileForCurrentItem( true );
|
||
|
|
||
|
m_pFontNameSmallest = pScheme->GetFont( "ItemFontNameSmallest", true );
|
||
|
m_pFontNameSmall = pScheme->GetFont( "ItemFontNameSmall", true );
|
||
|
m_pFontNameLarge = pScheme->GetFont( "ItemFontNameLarge", true );
|
||
|
m_pFontNameLarger = pScheme->GetFont( "ItemFontNameLarger", true );
|
||
|
m_pFontAttribSmallest = pScheme->GetFont( "ItemFontAttribSmallest", true );
|
||
|
m_pFontAttribSmall = pScheme->GetFont( "ItemFontAttribSmallv2", true );
|
||
|
m_pFontAttribLarge = pScheme->GetFont( "ItemFontAttribLarge", true );
|
||
|
m_pFontAttribLarger = pScheme->GetFont( "ItemFontAttribLarger", true );
|
||
|
|
||
|
if ( m_bContainedItem )
|
||
|
{
|
||
|
// SetBorder( pScheme->GetBorder("TFThinLineBorder") );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetBorder( pScheme->GetBorder( "TFFatLineBorder" ) );
|
||
|
}
|
||
|
|
||
|
if ( m_pModelPanel )
|
||
|
{
|
||
|
m_pModelPanel->SetBorder( pScheme->GetBorder( "TFFatLineBorder" ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
if ( !inResourceData )
|
||
|
return;
|
||
|
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
|
||
|
// Pass the itemmodelpanel KVs to the actual model panel
|
||
|
KeyValues* pItemModelPanelKVs = inResourceData->FindKey( "itemmodelpanel" );
|
||
|
if ( m_pModelPanel && pItemModelPanelKVs )
|
||
|
{
|
||
|
m_pModelPanel->ApplySettings( pItemModelPanelKVs );
|
||
|
}
|
||
|
|
||
|
// We can get our settings applied AFTER we've already setup our
|
||
|
// panel, so re-update.
|
||
|
UpdatePanels();
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::LoadResFileForCurrentItem( bool bForceLoad )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
bool bCollectionMouseover = ( m_bIsMouseOverPanel && GetItem() && GetItem()->GetItemDefinition()->GetItemCollectionDefinition() );
|
||
|
if ( bCollectionMouseover )
|
||
|
{
|
||
|
float flInspect = 0;
|
||
|
static CSchemaAttributeDefHandle pAttrib_WeaponAllowInspect( "weapon_allow_inspect" );
|
||
|
if ( FindAttribute_UnsafeBitwiseCast<attrib_value_t>( GetItem(), pAttrib_WeaponAllowInspect, &flInspect ) && flInspect != 0.f )
|
||
|
{
|
||
|
if ( bForceLoad || m_nCollectionItemLoaded != LOADED_COLLECTION_WEAPON )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s ItemModelPanelCollectionItem", __FUNCTION__ );
|
||
|
LoadControlSettings( "Resource/UI/econ/ItemModelPanelCollectionItem.res" );
|
||
|
m_nCollectionItemLoaded = LOADED_COLLECTION_WEAPON;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( bForceLoad || m_nCollectionItemLoaded != LOADED_COLLECTION_COSMETIC )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s ItemModelPanelCollectionCosmeticItem", __FUNCTION__ );
|
||
|
LoadControlSettings( "Resource/UI/econ/ItemModelPanelCollectionCosmeticItem.res" );
|
||
|
m_nCollectionItemLoaded = LOADED_COLLECTION_COSMETIC;
|
||
|
}
|
||
|
}
|
||
|
m_bHideModel = false; // Hack
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( bForceLoad || m_nCollectionItemLoaded != LOADED_COLLECTION_NONE )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s ItemModelPanel", __FUNCTION__ );
|
||
|
LoadControlSettings( "Resource/UI/econ/ItemModelPanel.res" );
|
||
|
}
|
||
|
m_bHideModel = m_bHideModelDefault;
|
||
|
m_nCollectionItemLoaded = LOADED_COLLECTION_NONE;
|
||
|
}
|
||
|
|
||
|
m_pModelPanel = dynamic_cast<CEmbeddedItemModelPanel*>( FindChildByName( "itemmodelpanel", true ) );
|
||
|
SetModelIsHidden( m_bHideModel );
|
||
|
if ( m_bIsMouseOverPanel && m_pModelPanel )
|
||
|
{
|
||
|
m_pModelPanel->SetInventoryImageType( CEmbeddedItemModelPanel::IMAGETYPE_LARGE );
|
||
|
}
|
||
|
|
||
|
m_pItemNameLabel = dynamic_cast<CExLabel*>( FindChildByName( "namelabel", true ) );
|
||
|
m_pItemAttribLabel = dynamic_cast<vgui::Label*>( FindChildByName( "attriblabel", true ) );
|
||
|
m_pItemCollectionNameLabel = dynamic_cast<CExLabel*>( FindChildByName( "collectionnamelabel", true ) );
|
||
|
m_pItemCollectionListLabel = dynamic_cast<vgui::Label*>( FindChildByName( "collectionlistlabel", true ) );
|
||
|
m_pItemCollectionHighlight = dynamic_cast<vgui::EditablePanel*>( FindChildByName( "collectionhighlight", true ) );
|
||
|
m_pItemEquippedLabel = dynamic_cast<vgui::Label*>( FindChildByName( "equippedlabel", true ) );
|
||
|
m_pItemQuantityLabel = dynamic_cast<vgui::Label*>( FindChildByName( "quantitylabel", true ) );
|
||
|
m_pVisionRestrictionImage = dynamic_cast<vgui::ImagePanel*>( FindChildByName( "vision_restriction_icon", true ) );
|
||
|
|
||
|
m_pIsStrangeImage = dynamic_cast<vgui::ImagePanel*>( FindChildByName( "is_strange_icon", true ) );
|
||
|
m_pIsUnusualImage = dynamic_cast<vgui::ImagePanel*>( FindChildByName( "is_unusual_icon", true ) );
|
||
|
m_pIsLoanerImage = dynamic_cast<vgui::ImagePanel*>( FindChildByName( "is_loaner_icon", true ) );
|
||
|
|
||
|
m_pSeriesLabel = dynamic_cast<vgui::Label*>( FindChildByName( "serieslabel", true ) );
|
||
|
m_pMatchesLabel = dynamic_cast<vgui::Label*>( FindChildByName( "matcheslabel", true ) );
|
||
|
m_pMainContentContainer = dynamic_cast<vgui::EditablePanel*>( FindChildByName( "MainContentsContainer" ) );
|
||
|
m_pLoadingSpinner = dynamic_cast<vgui::ImagePanel*>( FindChildByName( "LoadingSpinner" ) );
|
||
|
|
||
|
if ( m_pItemEquippedLabel )
|
||
|
{
|
||
|
m_pItemEquippedLabel->SetKeyBoardInputEnabled( false );
|
||
|
m_pItemEquippedLabel->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
if ( m_pItemQuantityLabel )
|
||
|
{
|
||
|
m_pItemQuantityLabel->SetKeyBoardInputEnabled( false );
|
||
|
m_pItemQuantityLabel->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
if ( m_pVisionRestrictionImage )
|
||
|
{
|
||
|
m_pVisionRestrictionImage->SetKeyBoardInputEnabled( false );
|
||
|
m_pVisionRestrictionImage->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
if ( m_pIsStrangeImage )
|
||
|
{
|
||
|
m_pIsStrangeImage->SetKeyBoardInputEnabled( false );
|
||
|
m_pIsStrangeImage->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
if ( m_pIsUnusualImage )
|
||
|
{
|
||
|
m_pIsUnusualImage->SetKeyBoardInputEnabled( false );
|
||
|
m_pIsUnusualImage->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
if ( m_pIsLoanerImage )
|
||
|
{
|
||
|
m_pIsLoanerImage->SetKeyBoardInputEnabled( false );
|
||
|
m_pIsLoanerImage->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
|
||
|
if ( m_pSeriesLabel )
|
||
|
{
|
||
|
m_pSeriesLabel->SetKeyBoardInputEnabled( false );
|
||
|
m_pSeriesLabel->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
if ( m_pMatchesLabel )
|
||
|
{
|
||
|
m_pMatchesLabel->SetKeyBoardInputEnabled( false );
|
||
|
m_pMatchesLabel->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
|
||
|
m_pPaintIcon = dynamic_cast<CItemMaterialCustomizationIconPanel*>( FindChildByName( "paint_icon", true ) );
|
||
|
if ( m_pPaintIcon )
|
||
|
{
|
||
|
m_pPaintIcon->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
m_pTF2Icon = dynamic_cast<vgui::ScalableImagePanel*>( FindChildByName( "tf2_icon", true ) );
|
||
|
if ( m_pTF2Icon )
|
||
|
{
|
||
|
m_pTF2Icon->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
|
||
|
if ( m_bContainedItem )
|
||
|
{
|
||
|
SetPaintBackgroundEnabled( true );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetPaintBackgroundEnabled( false );
|
||
|
}
|
||
|
|
||
|
if ( m_pModelPanel )
|
||
|
{
|
||
|
m_pModelPanel->SetBgColor( Color( 0, 0, 0, 255 ) );
|
||
|
m_pModelPanel->AddActionSignalTarget( this );
|
||
|
m_pModelPanel->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
|
||
|
if ( m_pItemNameLabel )
|
||
|
{
|
||
|
m_OrgItemTextColor = m_pItemNameLabel->GetFgColor();
|
||
|
m_pItemNameLabel->SetMouseInputEnabled( false );
|
||
|
m_pItemNameLabel->AddActionSignalTarget( this );
|
||
|
m_pItemNameLabel->InvalidateLayout( true, true );
|
||
|
}
|
||
|
|
||
|
if ( m_pItemAttribLabel )
|
||
|
{
|
||
|
m_pItemAttribLabel->SetMouseInputEnabled( false );
|
||
|
m_pItemAttribLabel->AddActionSignalTarget( this );
|
||
|
m_pItemAttribLabel->InvalidateLayout( true, true );
|
||
|
}
|
||
|
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
{
|
||
|
m_pItemCollectionNameLabel->SetMouseInputEnabled( false );
|
||
|
m_pItemCollectionNameLabel->AddActionSignalTarget( this );
|
||
|
m_pItemCollectionNameLabel->InvalidateLayout( true, true );
|
||
|
}
|
||
|
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
{
|
||
|
m_pItemCollectionListLabel->SetMouseInputEnabled( false );
|
||
|
m_pItemCollectionListLabel->AddActionSignalTarget( this );
|
||
|
m_pItemCollectionListLabel->InvalidateLayout( true, true );
|
||
|
}
|
||
|
|
||
|
if ( m_pItemCollectionHighlight )
|
||
|
{
|
||
|
m_pItemCollectionHighlight->SetMouseInputEnabled( false );
|
||
|
m_pItemCollectionHighlight->AddActionSignalTarget( this );
|
||
|
m_pItemCollectionHighlight->InvalidateLayout( true, true );
|
||
|
}
|
||
|
|
||
|
m_pContainedItemPanel = dynamic_cast<CItemModelPanel*>( FindChildByName( "contained_item_panel", true ) );
|
||
|
|
||
|
// Dont eat mouse input
|
||
|
if ( m_pMainContentContainer )
|
||
|
{
|
||
|
m_pMainContentContainer->SetMouseInputEnabled( false );
|
||
|
}
|
||
|
|
||
|
UpdatePanels();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::PerformLayout( void )
|
||
|
{
|
||
|
int w,h;
|
||
|
GetSize( w, h );
|
||
|
w = m_iBaseWide ? m_iBaseWide : w;
|
||
|
h = m_iBaseTall ? m_iBaseTall : h;
|
||
|
|
||
|
int iTextW = GetAttribWide(w);
|
||
|
int iModelW = m_iModelWide && m_iModelWide < w ? m_iModelWide : w;
|
||
|
int iModelT = m_iModelTall && m_iModelTall < h ? m_iModelTall : h;
|
||
|
int iModelX = m_bModelCenterX ? ( ( w - iModelW ) * 0.5 ) : m_iModelXPos;
|
||
|
int iModelY = m_bModelCenterY ? ( ( h - iModelT ) * 0.5 ) : m_iModelYPos;
|
||
|
|
||
|
ResizeLabels();
|
||
|
|
||
|
if ( m_pModelPanel )
|
||
|
{
|
||
|
m_pModelPanel->SetBounds( iModelX, iModelY, iModelW, iModelT );
|
||
|
}
|
||
|
if ( m_pLoadingSpinner )
|
||
|
{
|
||
|
int nWidthHeight = Max( iModelW, iModelT );
|
||
|
int xOffset = int( w / 2.f ) - int( nWidthHeight / 2.f );
|
||
|
int yOffset = int( h / 2.f ) - int( nWidthHeight / 2.f );
|
||
|
m_pLoadingSpinner->SetBounds( xOffset, yOffset, nWidthHeight, nWidthHeight );
|
||
|
}
|
||
|
|
||
|
if ( m_bNoItemFullPanel )
|
||
|
{
|
||
|
// We want the "no item" text to use the entire panel, and hide the attribs entirely
|
||
|
if ( m_pItemNameLabel && m_pItemAttribLabel )
|
||
|
{
|
||
|
m_pItemNameLabel->SetBounds( XRES(4), 0, GetWide() - XRES(8), GetTall() );
|
||
|
}
|
||
|
}
|
||
|
else if ( m_pItemNameLabel && m_pItemAttribLabel && !m_bModelOnly )
|
||
|
{
|
||
|
// Force the labels to layout now, and get their height.
|
||
|
m_pItemNameLabel->InvalidateLayout( true );
|
||
|
m_pItemAttribLabel->InvalidateLayout( true );
|
||
|
m_pItemNameLabel->SizeToContents();
|
||
|
m_pItemAttribLabel->SizeToContents();
|
||
|
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
{
|
||
|
m_pItemCollectionNameLabel->InvalidateLayout( true );
|
||
|
m_pItemCollectionNameLabel->SizeToContents();
|
||
|
}
|
||
|
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
{
|
||
|
m_pItemCollectionListLabel->InvalidateLayout( true );
|
||
|
m_pItemCollectionListLabel->SizeToContents();
|
||
|
}
|
||
|
|
||
|
// "" strings still size themselves as one font-heighth tall, but 0 wide. If there's no
|
||
|
// text in the attribute, we want 0 tall as well, so we don't get blank lines.
|
||
|
int iCollectionTall = m_pItemCollectionListLabel ? m_pItemCollectionListLabel->GetTall() : 0;
|
||
|
int iAttribTall = (m_pItemAttribLabel->GetWide() ? m_pItemAttribLabel->GetTall() : 0);
|
||
|
iAttribTall = Max( iAttribTall, iCollectionTall );
|
||
|
|
||
|
int iNameTall = m_pItemNameLabel->GetTall();
|
||
|
|
||
|
int iCollectionNameTall = m_pItemCollectionNameLabel ? m_pItemCollectionNameLabel->GetTall() : 0;
|
||
|
|
||
|
if ( m_bAttribOnly )
|
||
|
{
|
||
|
iNameTall = 0;
|
||
|
}
|
||
|
|
||
|
if ( m_bTextCenterX )
|
||
|
{
|
||
|
m_pItemNameLabel->SetSize( iTextW, iNameTall );
|
||
|
m_pItemAttribLabel->SetSize( iTextW, iAttribTall );
|
||
|
}
|
||
|
else if ( m_iTextYPos )
|
||
|
{
|
||
|
m_pItemNameLabel->SetSize( iTextW, iNameTall );
|
||
|
m_pItemAttribLabel->SetSize( iTextW, (m_pItemAttribLabel->GetWide() ? m_pItemAttribLabel->GetTall() : 0) );
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
m_pItemCollectionNameLabel->SetSize( iTextW, iCollectionNameTall );
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
m_pItemCollectionListLabel->SetSize( iTextW, iCollectionTall );
|
||
|
}
|
||
|
else if ( m_bTextCenter )
|
||
|
{
|
||
|
m_pItemNameLabel->SetSize( iTextW, iNameTall );
|
||
|
m_pItemAttribLabel->SetSize( iTextW, iAttribTall );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pItemNameLabel->SetSize( iTextW, iNameTall );
|
||
|
m_pItemAttribLabel->SetSize( iTextW, iAttribTall );
|
||
|
}
|
||
|
|
||
|
m_pItemNameLabel->InvalidateLayout( true );
|
||
|
|
||
|
// Force attrib layout to update now in its new size.
|
||
|
m_pItemAttribLabel->InvalidateLayout( true );
|
||
|
m_pItemAttribLabel->SizeToContents();
|
||
|
|
||
|
// Reget sizes, wtf
|
||
|
iCollectionTall = m_pItemCollectionListLabel ? m_pItemCollectionListLabel->GetTall() : 0;
|
||
|
iAttribTall = ( m_pItemAttribLabel->GetWide() ? m_pItemAttribLabel->GetTall() : 0 );
|
||
|
// HACK: Now we resize it again. Sets our height properly. Ridiculous.
|
||
|
m_pItemAttribLabel->SetSize( iTextW, iAttribTall );
|
||
|
m_pItemNameLabel->SetSize( iTextW, iNameTall );
|
||
|
|
||
|
// Ignore attributes if we're only showing the name
|
||
|
if ( m_bNameOnly || (!HasItem() && m_pszNoItemText && m_pszNoItemText[0]) )
|
||
|
{
|
||
|
iAttribTall = 0;
|
||
|
}
|
||
|
|
||
|
int iLabelOffset = 0;
|
||
|
if ( m_bResizeToText )
|
||
|
{
|
||
|
h = m_iTextYPos + iNameTall + iAttribTall + m_iHPadding;
|
||
|
|
||
|
// Must be at least tall enough to fit the image (if visible)
|
||
|
if ( !m_bHideModel )
|
||
|
{
|
||
|
//h = MAX( h, (iModelT + (iModelY * 2)) );
|
||
|
h = Max( h + iModelT + iModelY, m_iTextYPos + iCollectionNameTall + iCollectionTall + m_iHPadding);
|
||
|
iLabelOffset = iModelT + iModelY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If we don't have a specific X pos, or attrib width, indent ourselves
|
||
|
int iTextXPos = (m_iTextXPos || m_iTextWide) ? m_iTextXPos : ATTRIB_LABEL_INDENT;
|
||
|
|
||
|
if ( iCollectionNameTall && iCollectionTall && m_iTextXPosCollection )
|
||
|
{
|
||
|
iTextXPos = m_iTextXPosCollection;
|
||
|
}
|
||
|
|
||
|
// Position the name label now we know where our attrib label is
|
||
|
// If we've got a Y pos, use it. Otherwise, stack up from the bottom of the panel.
|
||
|
if ( m_bTextCenterX )
|
||
|
{
|
||
|
m_pItemNameLabel->SizeToContents();
|
||
|
m_pItemAttribLabel->SizeToContents();
|
||
|
|
||
|
m_pItemNameLabel->SetPos( ( w - m_pItemNameLabel->GetWide() ) * 0.5f, m_iTextYPos + iLabelOffset );
|
||
|
m_pItemAttribLabel->SetPos( ( w - m_pItemAttribLabel->GetWide() ) * 0.5f, m_iTextYPos + iNameTall + iLabelOffset );
|
||
|
}
|
||
|
else if ( m_iTextYPos )
|
||
|
{
|
||
|
m_pItemNameLabel->SetPos( iTextXPos, m_iTextYPos + iLabelOffset );
|
||
|
m_pItemAttribLabel->SetPos( iTextXPos, m_iTextYPos + iNameTall + iLabelOffset);
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
m_pItemCollectionNameLabel->SetPos( m_iCollectionListXPos, m_iTextYPos );
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
m_pItemCollectionListLabel->SetPos( m_iCollectionListXPos, m_iTextYPos + iCollectionNameTall );
|
||
|
}
|
||
|
else if ( m_bTextCenter )
|
||
|
{
|
||
|
int iYTop = (h - (iNameTall + iAttribTall)) * 0.5;
|
||
|
if ( iYTop < 0 )
|
||
|
{
|
||
|
iYTop = 0;
|
||
|
}
|
||
|
m_pItemNameLabel->SetPos( iTextXPos, iYTop );
|
||
|
m_pItemAttribLabel->SetPos( iTextXPos, iYTop + iNameTall );
|
||
|
//m_pItemCollectionLabel->SetPos( iTextXPos + iTextW, iYTop );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int iOffsetY = (m_iTextYOffset != 0) ? m_iTextYOffset : YRES(8);
|
||
|
m_pItemNameLabel->SetPos( iTextXPos, h - iAttribTall - iNameTall - iOffsetY + m_iHPadding );
|
||
|
m_pItemAttribLabel->SetPos( iTextXPos, h - iAttribTall - iOffsetY + m_iHPadding );
|
||
|
//m_pItemCollectionLabel->SetPos( iTextXPos + iTextW, h - iAttribTall - iNameTall - iOffsetY + m_iHPadding );
|
||
|
}
|
||
|
|
||
|
if ( m_bResizeToText )
|
||
|
{
|
||
|
if ( m_bIsMouseOverPanel && GetItem() && GetItem()->GetItemDefinition()->GetItemCollectionDefinition() && !m_bHideCollectionPanel )
|
||
|
{
|
||
|
if ( m_pItemCollectionListLabel && m_pItemCollectionNameLabel && m_pItemCollectionHighlight )
|
||
|
{
|
||
|
m_pItemCollectionListLabel->SizeToContents();
|
||
|
m_pItemCollectionNameLabel->SizeToContents();
|
||
|
int iContentW = Max( m_pItemCollectionNameLabel->GetWide(), m_pItemCollectionListLabel->GetWide() );
|
||
|
w = iContentW + m_iCollectionListXPos + m_iTextXPosCollection;
|
||
|
m_pItemCollectionHighlight->SetWide( iContentW );
|
||
|
}
|
||
|
}
|
||
|
SetSize( w, h );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// pin icons to top right corner
|
||
|
int xpos = m_iBaseWide - XRES(1);
|
||
|
int ypos = YRES(1);
|
||
|
|
||
|
if ( m_pPaintIcon && m_pPaintIcon->IsVisible() )
|
||
|
{
|
||
|
m_pPaintIcon->SetPos( xpos - m_pPaintIcon->GetWide(), ypos );
|
||
|
ypos += m_pPaintIcon->GetTall() * 0.9;
|
||
|
}
|
||
|
if ( m_pTF2Icon && m_pTF2Icon->IsVisible() )
|
||
|
{
|
||
|
m_pTF2Icon->SetPos( xpos - m_pTF2Icon->GetWide() + m_iTF2IconOffsetX, ypos + m_iTF2IconOffsetY );
|
||
|
ypos += m_pTF2Icon->GetTall() * 0.9;
|
||
|
}
|
||
|
if ( m_pVisionRestrictionImage && m_pVisionRestrictionImage->IsVisible() )
|
||
|
{
|
||
|
m_pVisionRestrictionImage->SetPos( xpos - m_pVisionRestrictionImage->GetWide(), ypos );
|
||
|
ypos += m_pVisionRestrictionImage->GetTall() * 0.9;
|
||
|
}
|
||
|
if ( m_pIsUnusualImage && m_pIsUnusualImage->IsVisible() )
|
||
|
{
|
||
|
m_pIsUnusualImage->SetPos( xpos - m_pIsUnusualImage->GetWide(), ypos );
|
||
|
ypos += m_pIsUnusualImage->GetTall() * 0.9;
|
||
|
}
|
||
|
if ( m_pIsStrangeImage && m_pIsStrangeImage->IsVisible() )
|
||
|
{
|
||
|
m_pIsStrangeImage->SetPos( xpos - m_pIsStrangeImage->GetWide(), ypos );
|
||
|
ypos += m_pIsStrangeImage->GetTall() * 0.9;
|
||
|
}
|
||
|
if ( m_pIsLoanerImage && m_pIsLoanerImage->IsVisible() )
|
||
|
{
|
||
|
m_pIsLoanerImage->SetPos( xpos - m_pIsLoanerImage->GetWide(), ypos );
|
||
|
ypos += m_pIsLoanerImage->GetTall() * 0.9;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( m_pItemNameLabel )
|
||
|
{
|
||
|
//m_pItemNameLabel->SetContentAlignment( (vgui::Label::Alignment) m_iNameLabelAlignment );
|
||
|
}
|
||
|
|
||
|
if ( m_bModelOnly )
|
||
|
{
|
||
|
if ( m_pItemNameLabel )
|
||
|
{
|
||
|
m_pItemNameLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pItemAttribLabel )
|
||
|
{
|
||
|
m_pItemAttribLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
{
|
||
|
m_pItemCollectionNameLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
{
|
||
|
m_pItemCollectionListLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pItemCollectionHighlight )
|
||
|
{
|
||
|
m_pItemCollectionHighlight->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BaseClass::PerformLayout();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::PaintTraverse( bool forceRepaint, bool allowForce )
|
||
|
{
|
||
|
if ( m_bFakeButton )
|
||
|
return;
|
||
|
|
||
|
BaseClass::PaintTraverse( forceRepaint, allowForce );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::OnSizeChanged( int newWide, int newTall )
|
||
|
{
|
||
|
BaseClass::OnSizeChanged( newWide, newTall );
|
||
|
InvalidateLayout( true );
|
||
|
|
||
|
if ( m_bModelOnly )
|
||
|
return;
|
||
|
|
||
|
if ( m_pItemNameLabel && m_pItemNameLabel->GetTextImage() )
|
||
|
{
|
||
|
m_pItemNameLabel->GetTextImage()->RecalculateNewLinePositions();
|
||
|
}
|
||
|
if ( m_pItemAttribLabel && m_pItemAttribLabel->GetTextImage() )
|
||
|
{
|
||
|
m_pItemAttribLabel->GetTextImage()->RecalculateNewLinePositions();
|
||
|
}
|
||
|
if ( m_pItemCollectionNameLabel && m_pItemCollectionNameLabel->GetTextImage() )
|
||
|
{
|
||
|
m_pItemCollectionNameLabel->GetTextImage()->RecalculateNewLinePositions();
|
||
|
}
|
||
|
if ( m_pItemCollectionListLabel && m_pItemCollectionListLabel->GetTextImage() )
|
||
|
{
|
||
|
m_pItemCollectionListLabel->GetTextImage()->RecalculateNewLinePositions();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::ResizeLabels( void )
|
||
|
{
|
||
|
if ( !m_pItemNameLabel || !m_pItemAttribLabel || m_bModelOnly )
|
||
|
return;
|
||
|
|
||
|
int w,h;
|
||
|
GetSize( w, h );
|
||
|
int iTextW = GetAttribWide(w);
|
||
|
|
||
|
if ( m_iMaxTextHeight )
|
||
|
{
|
||
|
h = m_iMaxTextHeight;
|
||
|
}
|
||
|
|
||
|
// HACK to get the item model panel on the main menu to have its fonts.
|
||
|
vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
|
||
|
if ( !m_pFontNameSmallest )
|
||
|
m_pFontNameSmallest = pScheme->GetFont( "ItemFontNameSmallest", true );
|
||
|
if ( !m_pFontNameSmall )
|
||
|
m_pFontNameSmall = pScheme->GetFont( "ItemFontNameSmall", true );
|
||
|
if ( !m_pFontNameLarge )
|
||
|
m_pFontNameLarge = pScheme->GetFont( "ItemFontNameLarge", true );
|
||
|
if ( !m_pFontNameLarger )
|
||
|
m_pFontNameLarger = pScheme->GetFont( "ItemFontNameLarger", true );
|
||
|
if ( !m_pFontAttribSmallest )
|
||
|
m_pFontAttribSmallest = pScheme->GetFont( "ItemFontAttribSmallest", true );
|
||
|
if ( !m_pFontAttribSmall )
|
||
|
m_pFontAttribSmall = pScheme->GetFont( "ItemFontAttribSmallv2", true );
|
||
|
if ( !m_pFontAttribLarge )
|
||
|
m_pFontAttribLarge = pScheme->GetFont( "ItemFontAttribLarge", true );
|
||
|
if ( !m_pFontAttribLarger )
|
||
|
m_pFontAttribLarger = pScheme->GetFont( "ItemFontAttribLarger", true );
|
||
|
|
||
|
if ( m_iForceTextSize && m_iForceTextSize <= 4 )
|
||
|
{
|
||
|
// Leave center wrap on if the noitem text is getting to use the whole panel
|
||
|
if ( !m_bNoItemFullPanel )
|
||
|
{
|
||
|
m_pItemNameLabel->SetCenterWrap( false );
|
||
|
}
|
||
|
m_pItemNameLabel->InvalidateLayout( true, true );
|
||
|
m_pItemAttribLabel->InvalidateLayout( true, true );
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
m_pItemCollectionNameLabel->InvalidateLayout( true, true );
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
m_pItemCollectionListLabel->InvalidateLayout( true, true );
|
||
|
|
||
|
switch ( m_iForceTextSize )
|
||
|
{
|
||
|
case 1:
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameLarge );
|
||
|
m_pItemAttribLabel->SetFont( m_pFontAttribLarge );
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
m_pItemCollectionNameLabel->SetFont( m_pFontNameLarge );
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
m_pItemCollectionListLabel->SetFont( m_pFontAttribLarge );
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameSmall );
|
||
|
m_pItemAttribLabel->SetFont( m_pFontAttribSmall );
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
m_pItemCollectionNameLabel->SetFont( m_pFontNameSmall );
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
m_pItemCollectionListLabel->SetFont( m_pFontAttribSmall );
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameSmallest );
|
||
|
m_pItemAttribLabel->SetFont( m_pFontAttribSmallest );
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
m_pItemCollectionNameLabel->SetFont( m_pFontNameSmallest );
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
m_pItemCollectionListLabel->SetFont( m_pFontAttribSmallest );
|
||
|
break;
|
||
|
|
||
|
case 4:
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameLarger );
|
||
|
m_pItemAttribLabel->SetFont( m_pFontAttribLarger );
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
m_pItemCollectionNameLabel->SetFont( m_pFontNameLarger );
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
m_pItemCollectionListLabel->SetFont( m_pFontAttribLarger );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
m_pItemNameLabel->SizeToContents();
|
||
|
m_pItemAttribLabel->SizeToContents();
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
m_pItemCollectionNameLabel->SizeToContents();
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
m_pItemCollectionListLabel->SizeToContents();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameLarge );
|
||
|
m_pItemNameLabel->SetCenterWrap( false );
|
||
|
m_pItemNameLabel->SizeToContents();
|
||
|
m_pItemAttribLabel->SetFont( m_pFontAttribLarge );
|
||
|
m_pItemAttribLabel->SizeToContents();
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
{
|
||
|
m_pItemCollectionNameLabel->SetFont( m_pFontNameLarge );
|
||
|
m_pItemCollectionNameLabel->SetCenterWrap( false );
|
||
|
m_pItemCollectionNameLabel->SizeToContents();
|
||
|
}
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
{
|
||
|
m_pItemCollectionListLabel->SetFont( m_pFontAttribLarge );
|
||
|
m_pItemCollectionListLabel->SizeToContents();
|
||
|
}
|
||
|
|
||
|
if ( !m_bResizeToText )
|
||
|
{
|
||
|
int iAttribTall = m_pItemAttribLabel->GetWide() ? m_pItemAttribLabel->GetTall() : 0;
|
||
|
int iNameTall = m_bAttribOnly ? 0 : m_pItemNameLabel->GetTall();
|
||
|
int iTotalH = iAttribTall + iNameTall;
|
||
|
|
||
|
// If these fonts won't fit, use the smaller ones
|
||
|
if ( m_pItemNameLabel->GetWide() > iTextW || (!m_bNameOnly && m_pItemAttribLabel->GetWide() > iTextW) || (iTotalH > h) )
|
||
|
{
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameSmall );
|
||
|
m_pItemAttribLabel->SetFont( m_pFontAttribSmall );
|
||
|
|
||
|
m_pItemNameLabel->InvalidateLayout( true );
|
||
|
m_pItemNameLabel->SizeToContents();
|
||
|
|
||
|
iAttribTall = m_pItemAttribLabel->GetWide() ? m_pItemAttribLabel->GetTall() : 0;
|
||
|
iNameTall = m_pItemNameLabel->GetTall();
|
||
|
iTotalH = iAttribTall + iNameTall;
|
||
|
|
||
|
// If they don't fit, go to the smallest
|
||
|
if ( m_pItemNameLabel->GetWide() > iTextW || (!m_bNameOnly && m_pItemAttribLabel->GetWide() > iTextW) || (iTotalH > h) )
|
||
|
{
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameSmallest );
|
||
|
m_pItemAttribLabel->SetFont( m_pFontAttribSmallest );
|
||
|
|
||
|
m_pItemNameLabel->InvalidateLayout( true );
|
||
|
m_pItemNameLabel->SizeToContents();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If it still doesn't fit, turn on wrap and pray
|
||
|
if ( m_pItemNameLabel->GetWide() > iTextW )
|
||
|
{
|
||
|
m_pItemNameLabel->SetCenterWrap( true );
|
||
|
}
|
||
|
|
||
|
if ( m_pItemAttribLabel->GetWide() > iTextW )
|
||
|
{
|
||
|
m_pItemAttribLabel->SetWrap( true );
|
||
|
}
|
||
|
|
||
|
// Now restore the sizes
|
||
|
m_pItemNameLabel->SetSize( iTextW, m_pItemNameLabel->GetTall() );
|
||
|
m_pItemAttribLabel->SetSize( iTextW, m_pItemAttribLabel->GetTall() );
|
||
|
|
||
|
if ( m_pItemEquippedLabel )
|
||
|
{
|
||
|
m_pItemEquippedLabel->SetPos( GetWide() - m_pItemEquippedLabel->GetWide() - m_iEquippedInsetX, GetTall() - m_pItemEquippedLabel->GetTall() - m_iEquippedInsetY );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::SetItem( const CEconItemView *pItem )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
|
||
|
HideContainedItemPanel();
|
||
|
|
||
|
bool bMatch = false;
|
||
|
|
||
|
if ( pItem && pItem->IsValid() )
|
||
|
{
|
||
|
if ( m_ItemData.IsValid() )
|
||
|
{
|
||
|
if ( m_ItemData.GetItemID() != INVALID_ITEM_ID )
|
||
|
{
|
||
|
bool bUseIndexCompare = false;
|
||
|
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
|
||
|
{
|
||
|
if ( ( m_ItemData.GetItemID() == 1 ) && ( m_ItemData.GetItemID() == pItem->GetItemID() ) )
|
||
|
{
|
||
|
// Items the bots carry in MvM all have itemID of 1, so we need to compare the item index
|
||
|
bUseIndexCompare = true;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if ( bUseIndexCompare )
|
||
|
{
|
||
|
bMatch = m_ItemData.GetItemDefIndex() == pItem->GetItemDefIndex();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Our current item is non-base. We need to match global indices.
|
||
|
bMatch = ( m_ItemData.GetItemID() == pItem->GetItemID() );
|
||
|
}
|
||
|
}
|
||
|
else if ( pItem->GetItemID() == INVALID_ITEM_ID )
|
||
|
{
|
||
|
static CSchemaFieldHandle<CEconItemAttributeDefinition> pAttrib_ToolTarget( "tool target item" );
|
||
|
bMatch &= pItem->FindAttribute( pAttrib_ToolTarget );
|
||
|
|
||
|
// Our current item is a base item. Our new item needs to be base too, and match item indices and quality
|
||
|
bMatch &= ( m_ItemData.GetItemDefIndex() == pItem->GetItemDefIndex() ) &&
|
||
|
( m_ItemData.GetItemQuality() == pItem->GetItemQuality() ) &&
|
||
|
( m_ItemData.GetSOCData() == pItem->GetSOCData() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if we match item so far, check for strange
|
||
|
if ( bMatch )
|
||
|
{
|
||
|
// Are we tracking alternate stats as well?
|
||
|
for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
|
||
|
{
|
||
|
const CEconItemAttributeDefinition *pKillEaterAltAttrDef = GetKillEaterAttr_Score( i ),
|
||
|
*pKillEaterAltScoreTypeAttrDef = GetKillEaterAttr_Type( i );
|
||
|
if ( !pKillEaterAltAttrDef || !pKillEaterAltScoreTypeAttrDef )
|
||
|
continue;
|
||
|
|
||
|
uint32 unNewScore = 0;
|
||
|
uint32 unOldScore = 0;
|
||
|
bool bNewFoundAttr = pItem->FindAttribute( pKillEaterAltAttrDef, &unNewScore );
|
||
|
bool bOldFoundAttr = m_ItemData.FindAttribute( pKillEaterAltAttrDef, &unOldScore );
|
||
|
if ( bNewFoundAttr != bOldFoundAttr || unNewScore != unOldScore )
|
||
|
{
|
||
|
// different score
|
||
|
bMatch = false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
float flNewType = 0.f;
|
||
|
float flOldType = 0.f;
|
||
|
bNewFoundAttr = FindAttribute_UnsafeBitwiseCast<attrib_value_t>( pItem, pKillEaterAltScoreTypeAttrDef, &flNewType );
|
||
|
bOldFoundAttr = FindAttribute_UnsafeBitwiseCast<attrib_value_t>( &m_ItemData, pKillEaterAltScoreTypeAttrDef, &flOldType );
|
||
|
if ( bNewFoundAttr != bOldFoundAttr || flNewType != flOldType )
|
||
|
{
|
||
|
// different score
|
||
|
bMatch = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !bMatch )
|
||
|
{
|
||
|
// cancel weapon skin composition for old item
|
||
|
if ( m_ItemData.IsValid() )
|
||
|
{
|
||
|
m_ItemData.CancelWeaponSkinComposite();
|
||
|
}
|
||
|
|
||
|
m_ItemData = *pItem;
|
||
|
|
||
|
if ( m_bIsMouseOverPanel )
|
||
|
{
|
||
|
LoadResFileForCurrentItem( false );
|
||
|
}
|
||
|
|
||
|
// If the item hasn't built its attribute string, go ahead and do that.
|
||
|
m_ItemData.SetGrayedOutReason( GetGreyedOutReason() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// The rest of the data may match, but we still need the inventory position updates
|
||
|
m_ItemData.SetInventoryPosition( pItem->GetInventoryPosition() );
|
||
|
}
|
||
|
|
||
|
ShowContainedItemPanel( pItem );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// cancel weapon skin composition for old item
|
||
|
if ( m_ItemData.IsValid() )
|
||
|
{
|
||
|
m_ItemData.CancelWeaponSkinComposite();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bMatch = true;
|
||
|
}
|
||
|
|
||
|
m_ItemData.GetAttributeList()->DestroyAllAttributes();
|
||
|
m_ItemData.Invalidate();
|
||
|
}
|
||
|
|
||
|
// only update panels when item is not matched
|
||
|
if ( !bMatch )
|
||
|
{
|
||
|
UpdatePanels();
|
||
|
}
|
||
|
|
||
|
// TODO: Update only description for strange item in the same panel
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::Dragged( bool bDragging )
|
||
|
{
|
||
|
if ( m_pContainedItemPanel )
|
||
|
{
|
||
|
if ( bDragging )
|
||
|
{
|
||
|
m_pContainedItemPanel->SetActAsButton( false, false );
|
||
|
m_pContainedItemPanel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::ShowContainedItemPanel( const CEconItemView *pItem )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
|
||
|
// If this item contains another item, create an interior item model panel.
|
||
|
if ( pItem->GetSOCData() && pItem->GetSOCData()->GetInteriorItem() && m_pContainedItemPanel )
|
||
|
{
|
||
|
if ( !m_pContainedItemPanel->IsContainedItem() )
|
||
|
{
|
||
|
m_pContainedItemPanel->SetContainedItem( true );
|
||
|
m_pContainedItemPanel->InvalidateLayout( false, true );
|
||
|
}
|
||
|
|
||
|
CEconItem *pInteriorItem = pItem->GetSOCData()->GetInteriorItem();
|
||
|
if ( !pInteriorItem )
|
||
|
return;
|
||
|
|
||
|
const IEconTool *pEconTool = pItem->GetItemDefinition()
|
||
|
? pItem->GetItemDefinition()->GetEconTool()
|
||
|
: NULL;
|
||
|
if ( !pEconTool )
|
||
|
return;
|
||
|
|
||
|
if ( !pEconTool->ShouldShowContainedItemPanel( pItem ) )
|
||
|
{
|
||
|
// Only show this to non-local, non-wrapping players if we've been told to (usually in trading panel)
|
||
|
if ( !m_bShowOthersGiftWrappedItems )
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SetNeedsToLoad();
|
||
|
|
||
|
m_pContainedItemPanel->SetEconItem( pInteriorItem );
|
||
|
m_pContainedItemPanel->SetVisible( true );
|
||
|
m_pContainedItemPanel->SetActAsButton( false, true );
|
||
|
m_pContainedItemPanel->SetTooltip( GetTooltip(), "" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::HideContainedItemPanel()
|
||
|
{
|
||
|
if ( m_pContainedItemPanel && m_pContainedItemPanel->IsVisible() )
|
||
|
{
|
||
|
m_pContainedItemPanel->SetActAsButton( false, false );
|
||
|
m_pContainedItemPanel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::SetEconItem( CEconItem* pItem )
|
||
|
{
|
||
|
m_ItemData.SetItemDefIndex( pItem->GetDefinitionIndex() );
|
||
|
m_ItemData.SetItemQuality( pItem->GetQuality() );
|
||
|
m_ItemData.SetItemLevel( pItem->GetItemLevel() );
|
||
|
m_ItemData.SetItemID( pItem->GetItemID() );
|
||
|
m_ItemData.SetNonSOEconItem( pItem );
|
||
|
m_ItemData.SetInitialized( true );
|
||
|
|
||
|
#ifdef CLIENT_DLL
|
||
|
m_ItemData.SetIsTradeItem( false );
|
||
|
m_ItemData.SetItemQuantity( pItem->GetQuantity() );
|
||
|
#endif
|
||
|
|
||
|
m_ItemData.GetAttributeList()->DestroyAllAttributes();
|
||
|
|
||
|
if ( m_pModelPanel )
|
||
|
{
|
||
|
m_pModelPanel->SetItem( &m_ItemData );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::SetNoItemText( const char *pszText )
|
||
|
{
|
||
|
m_pszNoItemText = pszText;
|
||
|
CleanupNoItemWChars();
|
||
|
|
||
|
if ( !HasItem() )
|
||
|
{
|
||
|
UpdatePanels();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::CleanupNoItemWChars( void )
|
||
|
{
|
||
|
if ( m_pwcNoItemText )
|
||
|
{
|
||
|
delete m_pwcNoItemText;
|
||
|
m_pwcNoItemText = NULL;
|
||
|
}
|
||
|
if ( m_pwcNoItemAttrib )
|
||
|
{
|
||
|
delete m_pwcNoItemAttrib;
|
||
|
m_pwcNoItemAttrib = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CItemModelPanel::UpdateSeriesLabel()
|
||
|
{
|
||
|
// hijacking m_bShowQuantity here to indicate "show things where the quantity counter goes", in this case meaning "show crate series indicator"
|
||
|
if ( m_pSeriesLabel && m_bShowQuantity )
|
||
|
{
|
||
|
static CSchemaAttributeDefHandle pAttrDef_CrateSeries( "set supply crate series" );
|
||
|
static CSchemaAttributeDefHandle pAttrDef_HideSeries( "hide crate series number" );
|
||
|
|
||
|
float fCrateSeries;
|
||
|
if ( pAttrDef_CrateSeries && FindAttribute_UnsafeBitwiseCast<attrib_value_t>( &m_ItemData, pAttrDef_CrateSeries, &fCrateSeries ) && pAttrDef_HideSeries && !m_ItemData.FindAttribute( pAttrDef_HideSeries ) )
|
||
|
{
|
||
|
wchar_t wszSeries[16]=L"";
|
||
|
_snwprintf( wszSeries, ARRAYSIZE( wszSeries ), L"#%i", (int)fCrateSeries );
|
||
|
m_pSeriesLabel->SetVisible( true );
|
||
|
m_pSeriesLabel->SetText( wszSeries );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pSeriesLabel->SetVisible( false );
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Read through a few items and see if they match the recipe's criteria
|
||
|
// Show elipses while still tallying. Remove our tick once all items
|
||
|
// are tallied.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CItemModelPanel::CheckRecipeMatches()
|
||
|
{
|
||
|
// Don't do this if either we or our parent are invisible
|
||
|
if( !IsVisible() || ( GetParent() && !GetParent()->IsVisible() ) )
|
||
|
return false;
|
||
|
|
||
|
const IEconTool* pTool = m_ItemData.GetStaticData()->GetEconTool();
|
||
|
|
||
|
// If this isnt a dynamic recipe tool, dont show or do any of this
|
||
|
if( !pTool
|
||
|
|| V_stricmp( m_ItemData.GetStaticData()->GetEconTool()->GetTypeName() , "dynamic_recipe")
|
||
|
|| m_ItemData.GetStaticData()->GetDefaultLoadoutSlot() != INVALID_EQUIPPED_SLOT )
|
||
|
{
|
||
|
if( m_pMatchesLabel )
|
||
|
{
|
||
|
m_pMatchesLabel->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool bStillWorking = true;
|
||
|
if( m_pMatchesLabel && m_bShowQuantity )
|
||
|
{
|
||
|
CPlayerInventory *pLocalInv = TFInventoryManager()->GetLocalInventory();
|
||
|
if ( pLocalInv == NULL )
|
||
|
return false;
|
||
|
|
||
|
// We still need to match recipe components
|
||
|
if ( m_nRecipeMatchingIndex < pLocalInv->GetItemCount() )
|
||
|
sai_NumLoadingRequests[LOADING_RECIPE_MATCHES]++;
|
||
|
|
||
|
if ( se_CurrentLoadingTask == LOADING_RECIPE_MATCHES )
|
||
|
{
|
||
|
// Go through our entire backpack and check for matches, but only go through a few at a time
|
||
|
while ( m_nRecipeMatchingIndex < pLocalInv->GetItemCount() && sm_flLoadingTimeThisFrame < tf_time_loading_item_panels.GetFloat() )
|
||
|
{
|
||
|
// Mark this time
|
||
|
float flTime = Plat_FloatTime();
|
||
|
|
||
|
CEconItemView *pItem = pLocalInv->GetItem( m_nRecipeMatchingIndex );
|
||
|
Assert( pItem );
|
||
|
|
||
|
// Check each item
|
||
|
CRecipeComponentMatchingIterator matchingIterator( &m_ItemData, pItem );
|
||
|
m_ItemData.IterateAttributes( &matchingIterator );
|
||
|
const CUtlVector< const CEconItemAttributeDefinition* >& matchingAttribs = matchingIterator.GetMatchingComponentInputs();
|
||
|
Assert( matchingAttribs.Count() <= 1 );
|
||
|
FOR_EACH_VEC( matchingAttribs, j )
|
||
|
{
|
||
|
CAttribute_DynamicRecipeComponent value;
|
||
|
const CEconItemAttributeDefinition* pAttrib = matchingAttribs[j];
|
||
|
attrib_definition_index_t nIndex = pAttrib->GetDefinitionIndex();
|
||
|
m_ItemData.FindAttribute( pAttrib, &value );
|
||
|
|
||
|
// Add this entry if it doesnt exist in out map yet
|
||
|
if( m_mapMatchingAttributes.Find( nIndex ) == m_mapMatchingAttributes.InvalidIndex() )
|
||
|
{
|
||
|
m_mapMatchingAttributes.Insert( nIndex );
|
||
|
m_mapMatchingAttributes[ m_mapMatchingAttributes.Find( nIndex ) ] = 0;
|
||
|
}
|
||
|
|
||
|
// Increment this value if it's less than the max needed
|
||
|
int &nCount = m_mapMatchingAttributes[ m_mapMatchingAttributes.Find( nIndex ) ];
|
||
|
if( (unsigned)nCount < ( value.num_required() - value.num_fulfilled() ) )
|
||
|
{
|
||
|
++nCount;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_nRecipeMatchingIndex++;
|
||
|
// Accumulate time
|
||
|
sm_flLoadingTimeThisFrame += ( Plat_FloatTime() - flTime );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bStillWorking = m_nRecipeMatchingIndex != pLocalInv->GetItemCount();
|
||
|
wchar_t wszMatches[16]=L"...";
|
||
|
|
||
|
if( !bStillWorking )
|
||
|
{
|
||
|
CRecipeComponentMatchingIterator matchingIterator( &m_ItemData, NULL );
|
||
|
m_ItemData.IterateAttributes( &matchingIterator );
|
||
|
int nTotalAttribs = matchingIterator.GetTotalInputs() - matchingIterator.GetInputsFulfilled();
|
||
|
int nMatchingAttribs = 0;
|
||
|
|
||
|
unsigned short index = m_mapMatchingAttributes.FirstInorder();
|
||
|
while( index != m_mapMatchingAttributes.InvalidIndex() )
|
||
|
{
|
||
|
nMatchingAttribs += m_mapMatchingAttributes[ index ];
|
||
|
index = m_mapMatchingAttributes.NextInorder( index );
|
||
|
}
|
||
|
|
||
|
// Fill out the actual number of matches
|
||
|
_snwprintf( wszMatches, ARRAYSIZE( wszMatches ), L"%i/%i", nMatchingAttribs, nTotalAttribs );
|
||
|
}
|
||
|
|
||
|
m_pMatchesLabel->SetVisible( true );
|
||
|
m_pMatchesLabel->SetText( wszMatches );
|
||
|
}
|
||
|
|
||
|
return bStillWorking;
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::UpdateDescription()
|
||
|
{
|
||
|
if ( !m_bDescriptionDirty )
|
||
|
return;
|
||
|
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
|
||
|
m_bDescriptionDirty = false;
|
||
|
|
||
|
enum { kAttribBufferSize = 4 * 1024 };
|
||
|
wchar_t wszAttribBuffer[ kAttribBufferSize ] = L"";
|
||
|
|
||
|
enum { kCollectionBufferSize = 4 * 1024 };
|
||
|
wchar_t wszCollectionListBuffer[kCollectionBufferSize] = L"";
|
||
|
|
||
|
wchar_t wszCollectionNameBuffer[512] = L"";
|
||
|
|
||
|
if ( !m_bNameOnly )
|
||
|
{
|
||
|
const CEconItemDescription *pDescription = m_ItemData.GetDescription();
|
||
|
if ( pDescription )
|
||
|
{
|
||
|
unsigned int unWrittenLines = 0;
|
||
|
unsigned int unWrittenCollectionLines = 0;
|
||
|
for ( unsigned int i = 0; i < pDescription->GetLineCount(); i++ )
|
||
|
{
|
||
|
const econ_item_description_line_t& line = pDescription->GetLine(i);
|
||
|
|
||
|
// m_bSpecialAttributesOnly, only show purple and orange text, ignore rest
|
||
|
if ( m_bSpecialAttributesOnly )
|
||
|
{
|
||
|
if ( line.eColor == ATTRIB_COL_UNUSUAL || line.eColor == ATTRIB_COL_STRANGE )
|
||
|
{
|
||
|
V_wcscat_safe( wszAttribBuffer, unWrittenLines++ == 0 ? L"" : L"\n" ); // add empty lines everywhere except before the first line
|
||
|
V_wcscat_safe( wszAttribBuffer, line.sText.Get() );
|
||
|
}
|
||
|
}
|
||
|
else if ( ( line.unMetaType & kDescLineFlag_CollectionName ) != 0 )
|
||
|
{
|
||
|
// Ignore name spacers
|
||
|
if ( !( line.unMetaType & kDescLineFlag_Empty) )
|
||
|
{
|
||
|
V_wcscat_safe( wszCollectionNameBuffer, line.sText.Get() );
|
||
|
}
|
||
|
}
|
||
|
else if ( ( line.unMetaType & kDescLineFlag_Collection ) != 0 )
|
||
|
{
|
||
|
V_wcscat_safe( wszCollectionListBuffer, unWrittenCollectionLines++ == 0 ? L"" : L"\n" ); // add empty lines everywhere except before the first line
|
||
|
V_wcscat_safe( wszCollectionListBuffer, line.sText.Get() );
|
||
|
}
|
||
|
else if ( (line.unMetaType & kDescLineFlag_Name ) == 0 )
|
||
|
{
|
||
|
V_wcscat_safe( wszAttribBuffer, unWrittenLines++ == 0 ? L"" : L"\n" ); // add empty lines everywhere except before the first line
|
||
|
V_wcscat_safe( wszAttribBuffer, line.sText.Get() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If we have an unknown name, we should try to rebuild for "awhile"
|
||
|
m_bDescriptionDirty |= pDescription->HasUnknownPlayer();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( m_pMainContentContainer )
|
||
|
{
|
||
|
m_pMainContentContainer->SetDialogVariable( "attriblist", wszAttribBuffer );
|
||
|
m_pMainContentContainer->SetDialogVariable( "collectionname", wszCollectionNameBuffer );
|
||
|
m_pMainContentContainer->SetDialogVariable( "collectionlist", wszCollectionListBuffer );
|
||
|
m_pMainContentContainer->SetDialogVariable( "itemname", m_ItemData.GetItemName() );
|
||
|
}
|
||
|
|
||
|
if ( m_pItemNameLabel )
|
||
|
{
|
||
|
// Set the name to the quality color
|
||
|
// Rarity Econ Colorization
|
||
|
EEconItemQuality eQuality = (EEconItemQuality)m_ItemData.GetItemQuality();
|
||
|
if ( GetItemSchema()->GetRarityColor( m_ItemData.GetItemDefinition()->GetRarity() ) && eQuality != AE_SELFMADE )
|
||
|
{
|
||
|
m_pItemNameLabel->SetColorStr( GetItemSchema()->GetRarityColor( m_ItemData.GetItemDefinition()->GetRarity() ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
const char *pszQualityColorString = EconQuality_GetColorString( eQuality );
|
||
|
if ( m_ItemData.IsValid() && !m_bStandardTextColor && pszQualityColorString )
|
||
|
{
|
||
|
m_pItemNameLabel->SetColorStr( pszQualityColorString );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pItemNameLabel->SetColorStr( m_OrgItemTextColor );
|
||
|
}
|
||
|
}
|
||
|
m_pItemNameLabel->SetVisible( !m_bAttribOnly );
|
||
|
}
|
||
|
|
||
|
if ( m_pItemAttribLabel )
|
||
|
{
|
||
|
m_pItemAttribLabel->SetVisible( !m_bNameOnly );
|
||
|
}
|
||
|
|
||
|
bool bCollectionVisible = m_bHideCollectionPanel ? false : !m_bNameOnly;
|
||
|
|
||
|
if ( m_pItemCollectionNameLabel )
|
||
|
{
|
||
|
m_pItemCollectionNameLabel->SetVisible( bCollectionVisible );
|
||
|
}
|
||
|
if ( m_pItemCollectionListLabel )
|
||
|
{
|
||
|
m_pItemCollectionListLabel->SetVisible( bCollectionVisible );
|
||
|
}
|
||
|
if ( m_pItemCollectionHighlight )
|
||
|
{
|
||
|
m_pItemCollectionHighlight->SetVisible( bCollectionVisible );
|
||
|
}
|
||
|
|
||
|
InvalidateLayout( true );
|
||
|
|
||
|
// Now that we've built the attribute description, give the attribute colors to our label
|
||
|
if ( m_pItemAttribLabel && !m_bNameOnly && m_pItemAttribLabel->GetTextImage() && m_ItemData.GetDescription() )
|
||
|
{
|
||
|
const CEconItemDescription *pDescription = m_ItemData.GetDescription();
|
||
|
vgui::TextImage *pAttrTextImage = m_pItemAttribLabel->GetTextImage();
|
||
|
pAttrTextImage->ClearColorChangeStream();
|
||
|
|
||
|
vgui::TextImage *pCollectionNameTextImage = m_pItemCollectionNameLabel ? m_pItemCollectionNameLabel->GetTextImage() : NULL;
|
||
|
if ( pCollectionNameTextImage )
|
||
|
pCollectionNameTextImage->ClearColorChangeStream();
|
||
|
|
||
|
vgui::TextImage *pCollectionListTextImage = m_pItemCollectionListLabel ? m_pItemCollectionListLabel->GetTextImage() : NULL;
|
||
|
if ( pCollectionListTextImage )
|
||
|
pCollectionListTextImage->ClearColorChangeStream();
|
||
|
|
||
|
vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
|
||
|
|
||
|
Color prevAttrColor(0,0,0);
|
||
|
Color prevCollectionColor(0,0,0);
|
||
|
unsigned int unCurrentAttrTextStreamIndex = 0;
|
||
|
unsigned int unCurrentCollectionNameTextStreamIndex = 0;
|
||
|
unsigned int unCurrentCollectionListTextStreamIndex = 0;
|
||
|
int iCollectionLineCount = 0;
|
||
|
|
||
|
if ( m_pItemCollectionHighlight )
|
||
|
{
|
||
|
m_pItemCollectionHighlight->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
for ( unsigned int i = 0; i < pDescription->GetLineCount(); i++ )
|
||
|
{
|
||
|
const econ_item_description_line_t& line = pDescription->GetLine(i);
|
||
|
|
||
|
// Ignore the name line, it was added above
|
||
|
if ( ( line.unMetaType & kDescLineFlag_Name ) != 0 )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// collection
|
||
|
int fontHeight = surface()->GetFontTall( m_pFontAttribSmall );
|
||
|
if ( ( line.unMetaType & (kDescLineFlag_Collection | kDescLineFlag_CollectionName | kDescLineFlag_CollectionCurrentItem ) ) != 0 && pCollectionNameTextImage && pCollectionListTextImage )
|
||
|
{
|
||
|
bool bIsCollectionName = ( line.unMetaType & kDescLineFlag_CollectionName ) != 0;
|
||
|
vgui::TextImage *pTextImage = bIsCollectionName ? pCollectionNameTextImage : pCollectionListTextImage;
|
||
|
unsigned int &unCurrentCollectionTextStreamIndex = bIsCollectionName ? unCurrentCollectionNameTextStreamIndex : unCurrentCollectionListTextStreamIndex;
|
||
|
|
||
|
bool bIsCurrentItem = ( line.unMetaType & kDescLineFlag_CollectionCurrentItem ) != 0;
|
||
|
// use bg color as text color for current item for a better highlight
|
||
|
Color col = bIsCurrentItem ? Color( 0, 0, 0, 255 ) : pScheme->GetColor( GetColorNameForAttribColor( line.eColor ), Color( 255, 255, 255, 255 ) );
|
||
|
// Output a color change if necessary.
|
||
|
if ( i == 0 || prevCollectionColor != col )
|
||
|
{
|
||
|
pTextImage->AddColorChange( col, unCurrentCollectionTextStreamIndex );
|
||
|
prevCollectionColor = col;
|
||
|
}
|
||
|
|
||
|
unCurrentCollectionTextStreamIndex += StringFuncs<locchar_t>::Length( line.sText.Get() ) + 1; // add one character to deal with newlines
|
||
|
|
||
|
if ( bIsCollectionName )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Current line highlight
|
||
|
if ( bIsCurrentItem && 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_pItemCollectionListLabel->GetPos( x, y );
|
||
|
m_pItemCollectionHighlight->SetPos( x, y + iCollectionLineCount * fontHeight );
|
||
|
m_pItemCollectionHighlight->SetBgColor( bgColor );
|
||
|
m_pItemCollectionHighlight->SetVisible( bCollectionVisible );
|
||
|
}
|
||
|
iCollectionLineCount++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Color col = pScheme->GetColor( GetColorNameForAttribColor( line.eColor ), Color( 255, 255, 255, 255 ) );
|
||
|
|
||
|
// m_bSpecialAttributesOnly, only show purple and orange text, ignore rest
|
||
|
if ( m_bSpecialAttributesOnly )
|
||
|
{
|
||
|
if ( ( line.eColor != ATTRIB_COL_UNUSUAL && line.eColor != ATTRIB_COL_STRANGE ) )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Output a color change if necessary.
|
||
|
if ( i == 0 || prevAttrColor != col )
|
||
|
{
|
||
|
pAttrTextImage->AddColorChange( col, unCurrentAttrTextStreamIndex );
|
||
|
prevAttrColor = col;
|
||
|
}
|
||
|
unCurrentAttrTextStreamIndex += StringFuncs<locchar_t>::Length( line.sText.Get() ) + 1; // add one character to deal with newlines
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::DirtyDescription()
|
||
|
{
|
||
|
m_bDescriptionDirty = true;
|
||
|
|
||
|
if ( HasItem() )
|
||
|
GetItem()->OnAttributeValuesChanged();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CItemModelPanel::UpdateMatchesLabel()
|
||
|
{
|
||
|
const IEconTool* pTool = m_ItemData.GetStaticData()->GetEconTool();
|
||
|
|
||
|
if( !pTool || Q_stricmp( m_ItemData.GetStaticData()->GetEconTool()->GetTypeName() , "dynamic_recipe") )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
m_nRecipeMatchingIndex = 0;
|
||
|
m_mapMatchingAttributes.Purge();
|
||
|
SetNeedsToLoad();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CItemModelPanel::UpdateQuantityLabel()
|
||
|
{
|
||
|
if ( m_pItemQuantityLabel )
|
||
|
{
|
||
|
bool bVisible = m_bShowQuantity && m_ItemData.GetStaticData() != NULL;
|
||
|
if ( bVisible )
|
||
|
{
|
||
|
const IEconTool *pEconTool = m_ItemData.GetStaticData()->GetEconTool();
|
||
|
if ( pEconTool && pEconTool->ShouldDisplayQuantity( &m_ItemData ) )
|
||
|
{
|
||
|
wchar_t wszQuantity[16]=L"";
|
||
|
_snwprintf( wszQuantity, ARRAYSIZE( wszQuantity ), L"%i", m_ItemData.GetQuantity() );
|
||
|
m_pItemQuantityLabel->SetVisible( true );
|
||
|
m_pItemQuantityLabel->SetText( wszQuantity );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bVisible = false;
|
||
|
}
|
||
|
}
|
||
|
m_pItemQuantityLabel->SetVisible( bVisible );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Simple utility function to allocate memory and duplicate a wide string
|
||
|
*/
|
||
|
inline wchar_t *CloneWString( const wchar_t *str )
|
||
|
{
|
||
|
const int nLen = V_wcslen(str)+1;
|
||
|
wchar_t *cloneStr = new wchar_t [ nLen ];
|
||
|
const int nSize = nLen * sizeof( wchar_t );
|
||
|
V_wcsncpy( cloneStr, str, nSize );
|
||
|
return cloneStr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::SetNoItemText( const wchar_t *pwszTitleOverride, const wchar_t *pwszAttribs, int iNegAttribsBegin )
|
||
|
{
|
||
|
static CSchemaColorDefHandle pColorDef_DescAttribPositive( "desc_attrib_positive" );
|
||
|
static CSchemaColorDefHandle pColorDef_DescAttribNegative( "ItemAttribNegative" );
|
||
|
|
||
|
CleanupNoItemWChars();
|
||
|
|
||
|
m_pwcNoItemText = CloneWString( pwszTitleOverride );
|
||
|
m_pszNoItemText = NULL;
|
||
|
|
||
|
if ( pwszAttribs )
|
||
|
{
|
||
|
m_pwcNoItemAttrib = CloneWString( pwszAttribs );
|
||
|
|
||
|
if ( m_pItemAttribLabel && m_pItemAttribLabel->GetTextImage() )
|
||
|
{
|
||
|
m_pItemAttribLabel->GetTextImage()->ClearColorChangeStream();
|
||
|
|
||
|
if ( iNegAttribsBegin )
|
||
|
{
|
||
|
vgui::IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
|
||
|
|
||
|
if ( pColorDef_DescAttribPositive )
|
||
|
{
|
||
|
Color col = pScheme->GetColor( pColorDef_DescAttribPositive->GetColorName(), Color(255,255,255,255) );
|
||
|
m_pItemAttribLabel->GetTextImage()->AddColorChange( col, 0 );
|
||
|
}
|
||
|
|
||
|
if ( pColorDef_DescAttribNegative )
|
||
|
{
|
||
|
Color col = pScheme->GetColor( pColorDef_DescAttribNegative->GetColorName(), Color(255,255,255,255) );
|
||
|
m_pItemAttribLabel->GetTextImage()->AddColorChange( col, iNegAttribsBegin );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !HasItem() )
|
||
|
{
|
||
|
UpdatePanels();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::HideAllModifierIcons()
|
||
|
{
|
||
|
if ( m_pPaintIcon )
|
||
|
{
|
||
|
m_pPaintIcon->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pTF2Icon )
|
||
|
{
|
||
|
m_pTF2Icon->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pItemEquippedLabel )
|
||
|
{
|
||
|
m_pItemEquippedLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pItemQuantityLabel )
|
||
|
{
|
||
|
m_pItemQuantityLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pVisionRestrictionImage )
|
||
|
{
|
||
|
m_pVisionRestrictionImage->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pIsStrangeImage )
|
||
|
{
|
||
|
m_pIsStrangeImage->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pIsUnusualImage )
|
||
|
{
|
||
|
m_pIsUnusualImage->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pIsLoanerImage )
|
||
|
{
|
||
|
m_pIsLoanerImage->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pSeriesLabel )
|
||
|
{
|
||
|
m_pSeriesLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pMatchesLabel )
|
||
|
{
|
||
|
m_pMatchesLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pItemEquippedLabel && m_bForceShowEquipped )
|
||
|
{
|
||
|
m_pItemEquippedLabel->SetVisible( m_bForceShowEquipped );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::UpdatePanels( void )
|
||
|
{
|
||
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||
|
|
||
|
if ( !m_pModelPanel )
|
||
|
return;
|
||
|
|
||
|
m_pModelPanel->SetModelHidden( m_bHideModel );
|
||
|
|
||
|
// By default we dont need a tick.
|
||
|
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
|
||
|
|
||
|
// Default to loading icons
|
||
|
se_CurrentLoadingTask = LOADING_ICONS;
|
||
|
|
||
|
m_pModelPanel->SetItem( &m_ItemData );
|
||
|
// We need to load if our image isn't in memory already.
|
||
|
if ( !m_bHideModel && ( m_pModelPanel->IsImageNotLoaded() || m_pModelPanel->IsLoadingWeaponSkin() ) )
|
||
|
{
|
||
|
if ( m_pMainContentContainer )
|
||
|
{
|
||
|
m_pMainContentContainer->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
// Show the spinner
|
||
|
if ( m_pLoadingSpinner )
|
||
|
{
|
||
|
m_pLoadingSpinner->SetVisible( true );
|
||
|
}
|
||
|
|
||
|
SetNeedsToLoad();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// hide the spinner
|
||
|
if ( m_pLoadingSpinner )
|
||
|
{
|
||
|
m_pLoadingSpinner->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !HasItem() )
|
||
|
{
|
||
|
if ( m_bModelOnly )
|
||
|
{
|
||
|
if ( m_pItemNameLabel )
|
||
|
{
|
||
|
m_pItemNameLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pItemAttribLabel )
|
||
|
{
|
||
|
m_pItemAttribLabel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( m_pItemNameLabel )
|
||
|
{
|
||
|
const wchar_t *wcNOText = NULL;
|
||
|
if ( m_pszNoItemText && m_pszNoItemText[0] )
|
||
|
{
|
||
|
wcNOText = g_pVGuiLocalize->Find( m_pszNoItemText );
|
||
|
}
|
||
|
else if ( m_pwcNoItemText )
|
||
|
{
|
||
|
wcNOText = m_pwcNoItemText;
|
||
|
}
|
||
|
|
||
|
if ( wcNOText && wcNOText[0] )
|
||
|
{
|
||
|
if ( m_pMainContentContainer )
|
||
|
m_pMainContentContainer->SetDialogVariable( "itemname", wcNOText );
|
||
|
m_pItemNameLabel->SetVisible( true );
|
||
|
m_pItemNameLabel->SetColorStr( m_NoItemTextColor );
|
||
|
|
||
|
m_pItemNameLabel->InvalidateLayout(true,true);
|
||
|
if ( m_iForceTextSize && m_iForceTextSize <= 3 )
|
||
|
{
|
||
|
// Leave center wrap on if the noitem text is getting to use the whole panel
|
||
|
if ( !m_bNoItemFullPanel )
|
||
|
{
|
||
|
m_pItemNameLabel->SetCenterWrap( false );
|
||
|
}
|
||
|
|
||
|
switch ( m_iForceTextSize )
|
||
|
{
|
||
|
case 1:
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameLarge );
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameSmall );
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
m_pItemNameLabel->SetFont( m_pFontNameSmallest );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pItemNameLabel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !m_bNameOnly && m_pwcNoItemAttrib )
|
||
|
{
|
||
|
if ( m_pMainContentContainer )
|
||
|
m_pMainContentContainer->SetDialogVariable( "attriblist", m_pwcNoItemAttrib );
|
||
|
if ( m_pItemAttribLabel && !m_pItemAttribLabel->IsVisible() )
|
||
|
{
|
||
|
m_pItemAttribLabel->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( m_pItemAttribLabel && m_pItemAttribLabel->IsVisible() )
|
||
|
{
|
||
|
m_pItemAttribLabel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HideAllModifierIcons();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( m_bHideModifierIcons )
|
||
|
{
|
||
|
HideAllModifierIcons();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( m_pPaintIcon )
|
||
|
{
|
||
|
m_pPaintIcon->SetVisible( false );
|
||
|
if ( !m_bHideModel && !m_bHidePaintIcon )
|
||
|
{
|
||
|
// Empty out our list of paint colors. We may or may not put things back in -- an empty
|
||
|
// list at the end means "don't draw the paint icon".
|
||
|
m_pPaintIcon->m_colPaintColors.RemoveAll();
|
||
|
|
||
|
// Fetch custom texture, if any
|
||
|
m_pPaintIcon->m_hUGCId = m_ItemData.GetCustomUserTextureID();
|
||
|
if ( m_pPaintIcon->m_hUGCId != 0 )
|
||
|
m_pPaintIcon->SetVisible( true );
|
||
|
|
||
|
// Don't show paint icons on any tools, their icon contains the color
|
||
|
const bool bIsEconTool = m_ItemData.GetItemDefinition()->IsTool();
|
||
|
|
||
|
// Has the item been painted?
|
||
|
int iRGB0 = m_ItemData.GetModifiedRGBValue( false ),
|
||
|
iRGB1 = m_ItemData.GetModifiedRGBValue( true );
|
||
|
|
||
|
if ( !bIsEconTool && (iRGB0 != 0 || iRGB1 != 0))
|
||
|
{
|
||
|
m_pPaintIcon->SetVisible( true );
|
||
|
m_pPaintIcon->m_colPaintColors.AddToTail( Color( clamp( (iRGB0 & 0xFF0000) >> 16, 0, 255 ), clamp( (iRGB0 & 0xFF00) >> 8, 0, 255 ), clamp( (iRGB0 & 0xFF), 0, 255 ), 255 ) );
|
||
|
if ( iRGB0 != iRGB1 )
|
||
|
{
|
||
|
m_pPaintIcon->m_colPaintColors.AddToTail( Color( clamp( (iRGB1 & 0xFF0000) >> 16, 0, 255 ), clamp( (iRGB1 & 0xFF00) >> 8, 0, 255 ), clamp( (iRGB1 & 0xFF), 0, 255 ), 255 ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_pTF2Icon )
|
||
|
{
|
||
|
if ( m_bHideModel || m_bHidePaintIcon )
|
||
|
{
|
||
|
m_pTF2Icon->SetVisible( false );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pTF2Icon->SetVisible( m_ItemData.GetSOCData() && m_ItemData.GetSOCData()->IsForeign() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_bNoItemFullPanel )
|
||
|
{
|
||
|
// If we're a noitem-fullpanel mode, we don't show strings when we have an item.
|
||
|
m_pItemNameLabel->SetVisible( false );
|
||
|
m_pItemAttribLabel->SetVisible( false );
|
||
|
}
|
||
|
else if ( m_bModelOnly )
|
||
|
{
|
||
|
if ( m_pItemNameLabel )
|
||
|
{
|
||
|
m_pItemNameLabel->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pItemAttribLabel )
|
||
|
{
|
||
|
m_pItemAttribLabel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// deferred description loading
|
||
|
m_bDescriptionDirty = true;
|
||
|
SetNeedsToLoad();
|
||
|
if ( m_pMainContentContainer )
|
||
|
m_pMainContentContainer->SetDialogVariable( "itemname", "" );
|
||
|
}
|
||
|
|
||
|
if ( m_pItemEquippedLabel )
|
||
|
{
|
||
|
m_pItemEquippedLabel->SetVisible( m_bForceShowEquipped || (m_bShowEquipped && IsEquipped()) );
|
||
|
}
|
||
|
|
||
|
// Hide all of these labels
|
||
|
if( m_pMatchesLabel )
|
||
|
{
|
||
|
m_pMatchesLabel->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
if( m_pSeriesLabel )
|
||
|
{
|
||
|
m_pSeriesLabel->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
if( m_pItemQuantityLabel )
|
||
|
{
|
||
|
m_pItemQuantityLabel->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
|
||
|
// Update that number in the top right
|
||
|
if ( !UpdateMatchesLabel() )
|
||
|
{
|
||
|
if ( !UpdateSeriesLabel() )
|
||
|
{
|
||
|
UpdateQuantityLabel();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_pVisionRestrictionImage )
|
||
|
{
|
||
|
int nVisionFilterFlags = 0;
|
||
|
const CEconItemDefinition *pData = m_ItemData.GetItemDefinition();
|
||
|
if ( !m_bModelOnly && pData )
|
||
|
{
|
||
|
nVisionFilterFlags = pData->GetVisionFilterFlags();
|
||
|
|
||
|
// Add support for all the holidays and "vision" mode restrictions
|
||
|
if ( pData->GetHolidayRestriction() )
|
||
|
{
|
||
|
int iHolidayRestriction = UTIL_GetHolidayForString( pData->GetHolidayRestriction() );
|
||
|
switch ( iHolidayRestriction )
|
||
|
{
|
||
|
default:
|
||
|
case kHoliday_None:
|
||
|
case kHoliday_TFBirthday:
|
||
|
case kHoliday_Christmas:
|
||
|
case kHoliday_Valentines:
|
||
|
case kHoliday_MeetThePyro:
|
||
|
case kHoliday_AprilFools:
|
||
|
case kHoliday_EOTL:
|
||
|
case kHoliday_CommunityUpdate:
|
||
|
break;
|
||
|
|
||
|
case kHoliday_Halloween:
|
||
|
case kHoliday_FullMoon:
|
||
|
case kHoliday_HalloweenOrFullMoon:
|
||
|
case kHoliday_HalloweenOrFullMoonOrValentines:
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
nVisionFilterFlags |= TF_VISION_FILTER_HALLOWEEN;
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch ( nVisionFilterFlags )
|
||
|
{
|
||
|
default:
|
||
|
AssertMsg1( false, "Unexpected vision restriction flags %d", nVisionFilterFlags );
|
||
|
case 0:
|
||
|
m_pVisionRestrictionImage->SetVisible( false );
|
||
|
break;
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
case 1:
|
||
|
m_pVisionRestrictionImage->SetImage( "viewmode_pyrovision" );
|
||
|
m_pVisionRestrictionImage->SetVisible( true );
|
||
|
break;
|
||
|
case 2:
|
||
|
// Check if most players who have not specifically opted in will see the item.
|
||
|
if ( TFGameRules() ? TFGameRules()->IsHolidayActive( kHoliday_HalloweenOrFullMoon ) : TF_IsHolidayActive( kHoliday_HalloweenOrFullMoon ) )
|
||
|
{
|
||
|
m_pVisionRestrictionImage->SetImage( "viewmode_spooky" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pVisionRestrictionImage->SetImage( "viewmode_spooky_off" );
|
||
|
}
|
||
|
m_pVisionRestrictionImage->SetVisible( true );
|
||
|
break;
|
||
|
case 4:
|
||
|
m_pVisionRestrictionImage->SetVisible( false );
|
||
|
break;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Strange Icon
|
||
|
static CSchemaAttributeDefHandle pAttrDef_StatTrakModule( "weapon_uses_stattrak_module" );
|
||
|
if ( m_pIsStrangeImage )
|
||
|
{
|
||
|
m_pIsStrangeImage->SetVisible( false );
|
||
|
|
||
|
if ( !m_bIsMouseOverPanel )
|
||
|
{
|
||
|
// Allow for already strange items
|
||
|
bool bIsStrange = false;
|
||
|
if ( m_ItemData.GetQuality() == AE_STRANGE )
|
||
|
{
|
||
|
bIsStrange = true;
|
||
|
}
|
||
|
|
||
|
if ( !bIsStrange )
|
||
|
{
|
||
|
// Go over the attributes of the item, if it has any strange attributes the item is strange and don't apply
|
||
|
for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
|
||
|
{
|
||
|
if ( m_ItemData.FindAttribute( GetKillEaterAttr_Score( i ) ) )
|
||
|
{
|
||
|
bIsStrange = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( bIsStrange )
|
||
|
{
|
||
|
if ( pAttrDef_StatTrakModule && m_ItemData.FindAttribute( pAttrDef_StatTrakModule ) )
|
||
|
{
|
||
|
m_pIsStrangeImage->SetImage( "viewmode_statclock" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pIsStrangeImage->SetImage( "viewmode_strange" );
|
||
|
|
||
|
}
|
||
|
m_pIsStrangeImage->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Unusual Icon
|
||
|
if ( m_pIsUnusualImage )
|
||
|
{
|
||
|
m_pIsUnusualImage->SetVisible( false );
|
||
|
|
||
|
static CSchemaAttributeDefHandle pAttrDef_ParticleEffect( "attach particle effect" );
|
||
|
static CSchemaAttributeDefHandle pAttrDef_TauntParticle( "on taunt attach particle index" );
|
||
|
if ( pAttrDef_ParticleEffect && pAttrDef_TauntParticle && !m_bIsMouseOverPanel )
|
||
|
{
|
||
|
// Cant use quality cause of old legacy items. Quality is just a quick test
|
||
|
if ( m_ItemData.FindAttribute( pAttrDef_ParticleEffect ) || m_ItemData.FindAttribute( pAttrDef_TauntParticle ) )
|
||
|
{
|
||
|
m_pIsUnusualImage->SetImage( "viewmode_unusual" );
|
||
|
m_pIsUnusualImage->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_pIsLoanerImage )
|
||
|
{
|
||
|
m_pIsLoanerImage->SetVisible( false );
|
||
|
if ( !m_bIsMouseOverPanel && GetAssociatedQuestItemID( &m_ItemData ) != INVALID_ITEM_ID )
|
||
|
{
|
||
|
m_pIsLoanerImage->SetImage( "viewmode_loaner" );
|
||
|
m_pIsLoanerImage->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
InvalidateLayout();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CItemModelPanel::IsEquipped( void )
|
||
|
{
|
||
|
if ( !HasItem() )
|
||
|
return false;
|
||
|
|
||
|
return m_ItemData.IsEquipped();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::SetGreyedOut( const char *pszGreyedOutReason )
|
||
|
{
|
||
|
m_pszGreyedOutReason = pszGreyedOutReason;
|
||
|
if ( m_pModelPanel )
|
||
|
{
|
||
|
m_pModelPanel->SetGreyedOut( m_pszGreyedOutReason != NULL );
|
||
|
}
|
||
|
UpdateEquippedLabel();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CItemModelPanel::HasItem( void )
|
||
|
{
|
||
|
return m_ItemData.IsValid();
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::SetModelIsHidden( bool bHideModel )
|
||
|
{
|
||
|
m_bHideModel = bHideModel;
|
||
|
if ( m_pModelPanel )
|
||
|
{
|
||
|
m_pModelPanel->SetModelHidden( bHideModel );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::OnTick()
|
||
|
{
|
||
|
bool bStillWorking = LoadData();
|
||
|
if ( m_pContainedItemPanel )
|
||
|
{
|
||
|
bStillWorking |= m_pContainedItemPanel->LoadData();
|
||
|
}
|
||
|
|
||
|
// If we're done working, we dont need to tick anymore
|
||
|
if ( !bStillWorking )
|
||
|
{
|
||
|
LoadDataCompleted();
|
||
|
}
|
||
|
|
||
|
BaseClass::OnTick();
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::SetNeedsToLoad()
|
||
|
{
|
||
|
vgui::ivgui()->AddTickSignalToHead( GetVPanel() );
|
||
|
}
|
||
|
|
||
|
bool CItemModelPanel::LoadData()
|
||
|
{
|
||
|
// Different frame?
|
||
|
if ( sm_nCurrentDecriptionUpdateFrame != gpGlobals->framecount )
|
||
|
{
|
||
|
// Reset
|
||
|
sm_nCurrentDecriptionUpdateFrame = gpGlobals->framecount;
|
||
|
sm_flLoadingTimeThisFrame = 0.f;
|
||
|
|
||
|
// Figure out which loading we're going to do. We want to load
|
||
|
// certain things sooner (visual things, ie icons) than we start
|
||
|
// figuring out recipe matches.
|
||
|
eLoadingType_t type = NUM_LOADING_TYPES;
|
||
|
for( int i=0; i < NUM_LOADING_TYPES; ++i )
|
||
|
{
|
||
|
if ( sai_NumLoadingRequests[i] > 0 && eLoadingType_t(i) < type )
|
||
|
{
|
||
|
type = eLoadingType_t(i);
|
||
|
}
|
||
|
sai_NumLoadingRequests[i] = 0;
|
||
|
}
|
||
|
|
||
|
se_CurrentLoadingTask = type;
|
||
|
}
|
||
|
|
||
|
bool bStillWorking = CheckRecipeMatches();
|
||
|
|
||
|
if ( !m_bHideModel && m_pModelPanel )
|
||
|
{
|
||
|
bool bImageLoaded = true;
|
||
|
bool bLoadingWeaponSkin = m_pModelPanel->IsLoadingWeaponSkin();
|
||
|
bool bLoadingBackpackIcon = m_pModelPanel->IsImageNotLoaded();
|
||
|
|
||
|
if ( bLoadingWeaponSkin || bLoadingBackpackIcon )
|
||
|
{
|
||
|
// We still need to load icons
|
||
|
sai_NumLoadingRequests[LOADING_ICONS]++;
|
||
|
if ( sm_flLoadingTimeThisFrame < tf_time_loading_item_panels.GetFloat() && se_CurrentLoadingTask == LOADING_ICONS )
|
||
|
{
|
||
|
float flTime = Plat_FloatTime();
|
||
|
|
||
|
// no need to load texture if we're doing composite weapon skin
|
||
|
if ( bLoadingWeaponSkin )
|
||
|
{
|
||
|
g_pMatSystemSurface->BeginSkinCompositionPainting();
|
||
|
m_pModelPanel->Paint();
|
||
|
g_pMatSystemSurface->EndSkinCompositionPainting();
|
||
|
}
|
||
|
|
||
|
if ( bLoadingBackpackIcon )
|
||
|
{
|
||
|
m_pModelPanel->LoadInventoryImage();
|
||
|
}
|
||
|
|
||
|
// Accumulate time
|
||
|
sm_flLoadingTimeThisFrame += ( Plat_FloatTime() - flTime );
|
||
|
}
|
||
|
|
||
|
bStillWorking = m_pModelPanel->IsLoadingWeaponSkin() || m_pModelPanel->IsImageNotLoaded();
|
||
|
bImageLoaded = !bStillWorking;
|
||
|
}
|
||
|
|
||
|
// Hide the spinner and show the main container
|
||
|
if ( bImageLoaded )
|
||
|
{
|
||
|
if ( m_pMainContentContainer && !m_pMainContentContainer->IsVisible() )
|
||
|
{
|
||
|
m_pMainContentContainer->SetVisible( true );
|
||
|
}
|
||
|
|
||
|
if ( m_pLoadingSpinner && m_pLoadingSpinner->IsVisible() )
|
||
|
{
|
||
|
m_pLoadingSpinner->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_bDescriptionDirty && !IsContainedItem() )
|
||
|
{
|
||
|
// We still need to load our description
|
||
|
sai_NumLoadingRequests[LOADING_DESCRIPTIONS]++;
|
||
|
// Check if we're clear to update. We only want to eat up a little slice of time.
|
||
|
if ( sm_flLoadingTimeThisFrame < tf_time_loading_item_panels.GetFloat() && se_CurrentLoadingTask == LOADING_DESCRIPTIONS )
|
||
|
{
|
||
|
float flTime = Plat_FloatTime();
|
||
|
// Update!
|
||
|
UpdateDescription();
|
||
|
|
||
|
// Accumulate time
|
||
|
sm_flLoadingTimeThisFrame += ( Plat_FloatTime() - flTime );
|
||
|
}
|
||
|
|
||
|
bStillWorking |= m_bDescriptionDirty;
|
||
|
}
|
||
|
|
||
|
return bStillWorking;
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::LoadDataCompleted()
|
||
|
{
|
||
|
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::SetActAsButton( bool bClickable, bool bMouseOver )
|
||
|
{
|
||
|
m_bClickable = bClickable;
|
||
|
m_bMouseOver = bMouseOver;
|
||
|
|
||
|
SetMouseInputEnabled( m_bClickable || m_bMouseOver );
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::NavigateTo()
|
||
|
{
|
||
|
BaseClass::NavigateTo();
|
||
|
|
||
|
if ( IsPC() )
|
||
|
{
|
||
|
RequestFocus( 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::NavigateFrom()
|
||
|
{
|
||
|
BaseClass::NavigateFrom();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::OnCursorEntered( void )
|
||
|
{
|
||
|
if ( !m_bMouseOver )
|
||
|
return;
|
||
|
|
||
|
if ( m_bShouldSendPanelEnterExits )
|
||
|
{
|
||
|
PostActionSignal( new KeyValues("ItemPanelEntered") );
|
||
|
}
|
||
|
|
||
|
if ( IsEnabled() && !IsSelected() )
|
||
|
{
|
||
|
NavigateTo();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::OnCursorExited( void )
|
||
|
{
|
||
|
if ( !m_bMouseOver )
|
||
|
return;
|
||
|
|
||
|
if ( m_bShouldSendPanelEnterExits )
|
||
|
{
|
||
|
PostActionSignal( new KeyValues("ItemPanelExited") );
|
||
|
}
|
||
|
|
||
|
if ( IsSelected() )
|
||
|
{
|
||
|
NavigateFrom();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
extern ISoundEmitterSystemBase *soundemitterbase;
|
||
|
void CItemModelPanel::OnMousePressed(vgui::MouseCode code)
|
||
|
{
|
||
|
if ( code == MOUSE_RIGHT )
|
||
|
{
|
||
|
PostActionSignal( new KeyValues("ItemPanelMouseRightRelease") );
|
||
|
}
|
||
|
|
||
|
if ( !m_bClickable || code != MOUSE_LEFT )
|
||
|
return;
|
||
|
|
||
|
PostActionSignal( new KeyValues("ItemPanelMousePressed") );
|
||
|
|
||
|
// audible feedback
|
||
|
const char *soundFilename = "ui/buttonclick.wav";
|
||
|
|
||
|
if ( m_bUseItemSounds )
|
||
|
{
|
||
|
CEconItemView *item = GetItem();
|
||
|
if ( item )
|
||
|
{
|
||
|
soundFilename = item->GetDefinitionString( "mouse_pressed_sound", "ui/item_default_pickup.wav" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const char *pszSound = UTIL_GetRandomSoundFromEntry( soundFilename );
|
||
|
if ( pszSound && pszSound[0] )
|
||
|
{
|
||
|
vgui::surface()->PlaySound( pszSound );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::OnMouseReleased(vgui::MouseCode code)
|
||
|
{
|
||
|
if ( !m_bClickable || code != MOUSE_LEFT )
|
||
|
return;
|
||
|
|
||
|
PostActionSignal( new KeyValues("ItemPanelMouseReleased") );
|
||
|
|
||
|
// audible feedback
|
||
|
// we're not using item sounds here because they are better handled by the drag/drop code elsewhere
|
||
|
if ( !m_bUseItemSounds )
|
||
|
{
|
||
|
vgui::surface()->PlaySound( "ui/buttonclickrelease.wav" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::OnMouseDoublePressed(vgui::MouseCode code)
|
||
|
{
|
||
|
if ( !m_bClickable || code != MOUSE_LEFT )
|
||
|
return;
|
||
|
|
||
|
PostActionSignal( new KeyValues("ItemPanelMouseDoublePressed") );
|
||
|
|
||
|
// audible feedback
|
||
|
const char *soundFilename = "ui/buttonclickrelease.wav";
|
||
|
|
||
|
if ( m_bUseItemSounds )
|
||
|
{
|
||
|
CEconItemView *item = GetItem();
|
||
|
if ( item )
|
||
|
{
|
||
|
soundFilename = item->GetDefinitionString( "mouse_double_pressed_sound", "ui/item_default_drop.wav" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vgui::surface()->PlaySound( soundFilename );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::OnCursorMoved( int x, int y )
|
||
|
{
|
||
|
if ( !m_bClickable )
|
||
|
return;
|
||
|
|
||
|
// Add our own xpos/ypos offset
|
||
|
int iXPos;
|
||
|
int iYPos;
|
||
|
GetPos( iXPos, iYPos );
|
||
|
PostActionSignal( new KeyValues("ItemPanelCursorMoved", "x", x + iXPos, "y", y + iYPos) );
|
||
|
}
|
||
|
|
||
|
void CItemModelPanel::OnKeyCodePressed( vgui::KeyCode code )
|
||
|
{
|
||
|
BaseClass::OnKeyCodePressed( code );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::OnCommand( const char *command )
|
||
|
{
|
||
|
if ( FStrEq( command, "sellitem" ) )
|
||
|
{
|
||
|
if ( HasItem() && steamapicontext && steamapicontext->SteamFriends() && steamapicontext->SteamUtils() )
|
||
|
{
|
||
|
const char *pszPrefix = "";
|
||
|
if ( GetUniverse() == k_EUniverseBeta )
|
||
|
{
|
||
|
pszPrefix = "beta.";
|
||
|
}
|
||
|
uint32 nAssetContext = 2; // k_EEconContextBackpack
|
||
|
char szURL[512];
|
||
|
V_snprintf( szURL, sizeof(szURL), "http://%ssteamcommunity.com/my/inventory/?sellOnLoad=1#%d_%d_%llu", pszPrefix, engine->GetAppID(), nAssetContext, GetItem()->GetItemID() );
|
||
|
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( szURL );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::UpdateEquippedLabel( void )
|
||
|
{
|
||
|
if ( !m_pItemEquippedLabel )
|
||
|
return;
|
||
|
|
||
|
if ( IsGreyedOut() )
|
||
|
{
|
||
|
m_pItemEquippedLabel->SetFgColor( Color(96,96,96,255) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pItemEquippedLabel->SetFgColor( Color(200,80,60,255) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanel::SetSkin( int iSkin )
|
||
|
{
|
||
|
if ( m_pModelPanel )
|
||
|
{
|
||
|
m_pModelPanel->SetSkin( iSkin );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
itempanel_tooltippos_t g_iTooltipStrategies[NUM_IPTTP_STRATEGIES][NUM_POSITIONS_PER_STRATEGY] =
|
||
|
{
|
||
|
{ IPTTP_LEFT, IPTTP_LEFT_CENTERED, IPTTP_ABOVE, IPTTP_BELOW, IPTTP_RIGHT_CENTERED, IPTTP_RIGHT }, // IPTTP_LEFT_SIDE
|
||
|
{ IPTTP_RIGHT, IPTTP_RIGHT_CENTERED, IPTTP_ABOVE, IPTTP_BELOW, IPTTP_LEFT_CENTERED, IPTTP_LEFT }, // IPTTP_RIGHT_SIDE
|
||
|
{ IPTTP_ABOVE, IPTTP_LEFT_CENTERED, IPTTP_RIGHT_CENTERED, IPTTP_LEFT, IPTTP_RIGHT, IPTTP_ABOVE }, // IPTTP_TOP_SIDE
|
||
|
{ IPTTP_BELOW, IPTTP_LEFT_CENTERED, IPTTP_RIGHT_CENTERED, IPTTP_LEFT, IPTTP_RIGHT, IPTTP_ABOVE }, // IPTTP_BOTTOM_SIDE
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CItemModelPanelToolTip::CItemModelPanelToolTip( vgui::Panel *parent, const char *text )
|
||
|
: vgui::BaseTooltip( parent, text )
|
||
|
, m_pMouseOverItemPanel( NULL )
|
||
|
, m_iPositioningStrategy( IPTTP_BOTTOM_SIDE )
|
||
|
{
|
||
|
m_hCurrentPanel = NULL;
|
||
|
SetTooltipDelay( 100 );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanelToolTip::GetPosition( itempanel_tooltippos_t iTooltipPosition, CItemModelPanel *pItemPanel, int iItemX, int iItemY, int *iXPos, int *iYPos )
|
||
|
{
|
||
|
switch ( iTooltipPosition )
|
||
|
{
|
||
|
case IPTTP_LEFT:
|
||
|
*iXPos = (iItemX - m_pMouseOverItemPanel->GetWide() + XRES(18));
|
||
|
*iYPos = iItemY - YRES(7);
|
||
|
break;
|
||
|
case IPTTP_RIGHT:
|
||
|
*iXPos = (iItemX + pItemPanel->GetWide() - XRES(20));
|
||
|
*iYPos = iItemY - YRES(7);
|
||
|
break;
|
||
|
case IPTTP_LEFT_CENTERED:
|
||
|
*iXPos = (iItemX - m_pMouseOverItemPanel->GetWide()) - XRES(4);
|
||
|
*iYPos = (iItemY - (m_pMouseOverItemPanel->GetTall() * 0.5));
|
||
|
break;
|
||
|
case IPTTP_RIGHT_CENTERED:
|
||
|
*iXPos = (iItemX + pItemPanel->GetWide()) + XRES(4);
|
||
|
*iYPos = (iItemY - (m_pMouseOverItemPanel->GetTall() * 0.5));
|
||
|
break;
|
||
|
case IPTTP_ABOVE:
|
||
|
*iXPos = (iItemX + (pItemPanel->GetWide() * 0.5)) - (m_pMouseOverItemPanel->GetWide() * 0.5);
|
||
|
*iYPos = (iItemY - m_pMouseOverItemPanel->GetTall() - YRES(4));
|
||
|
break;
|
||
|
case IPTTP_BELOW:
|
||
|
*iXPos = (iItemX + (pItemPanel->GetWide() * 0.5)) - (m_pMouseOverItemPanel->GetWide() * 0.5);
|
||
|
*iYPos = (iItemY + pItemPanel->GetTall() + YRES(4));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CItemModelPanelToolTip::ValidatePosition( CItemModelPanel *pItemPanel, int iItemX, int iItemY, int *iXPos, int *iYPos )
|
||
|
{
|
||
|
bool bSucceeded = true;
|
||
|
|
||
|
// Make sure the popup stays onscreen.
|
||
|
if ( *iXPos < 0 )
|
||
|
{
|
||
|
*iXPos = 0;
|
||
|
}
|
||
|
else if ( (*iXPos + m_pMouseOverItemPanel->GetWide()) > m_pParentPanel->GetWide() )
|
||
|
{
|
||
|
int iXPosNew = m_pParentPanel->GetWide() - m_pMouseOverItemPanel->GetWide();
|
||
|
// make sure it is still on the screen
|
||
|
if ( iXPosNew >= 0 )
|
||
|
{
|
||
|
*iXPos = iXPosNew;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bSucceeded = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( *iYPos < 0 )
|
||
|
{
|
||
|
*iYPos = 0;
|
||
|
}
|
||
|
else if ( (*iYPos + m_pMouseOverItemPanel->GetTall() + YRES(32)) > m_pParentPanel->GetTall() )
|
||
|
{
|
||
|
// Move it up above our item
|
||
|
int iYPosNew = iItemY - m_pMouseOverItemPanel->GetTall() - YRES(4);
|
||
|
// make sure it is still on the screen
|
||
|
if ( iYPosNew >= 0 )
|
||
|
{
|
||
|
*iYPos = iYPosNew;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bSucceeded = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( bSucceeded )
|
||
|
{
|
||
|
// We also fail if moving it to keep it on screen moved it over the item panel itself
|
||
|
Vector2D vecToolTipMin, vecToolTipMax, vecItemMin, vecItemMax;
|
||
|
vecToolTipMin.x = *iXPos;
|
||
|
vecToolTipMin.y = *iYPos;
|
||
|
vecToolTipMax.x = vecToolTipMin.x + m_pMouseOverItemPanel->GetWide();
|
||
|
vecToolTipMax.y = vecToolTipMin.y + m_pMouseOverItemPanel->GetTall();
|
||
|
|
||
|
vecItemMin.x = iItemX;
|
||
|
vecItemMin.y = iItemY;
|
||
|
vecItemMax.x = vecItemMin.x + m_hCurrentPanel->GetWide();
|
||
|
vecItemMax.y = vecItemMin.y + m_hCurrentPanel->GetTall();
|
||
|
|
||
|
bSucceeded = !( vecToolTipMin.x < vecItemMax.x && vecToolTipMax.x > vecItemMin.x && vecToolTipMin.y < vecItemMax.y && vecToolTipMax.y > vecItemMin.y );
|
||
|
}
|
||
|
|
||
|
return bSucceeded;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanelToolTip::PerformLayout()
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
if ( !ShouldLayout() )
|
||
|
return;
|
||
|
|
||
|
_isDirty = false;
|
||
|
|
||
|
CItemModelPanel *pItemPanel = m_hCurrentPanel.Get();
|
||
|
if ( m_pMouseOverItemPanel && pItemPanel )
|
||
|
{
|
||
|
CEconItemView *pItem = pItemPanel->GetItem();
|
||
|
if ( pItem && pItemPanel->ShouldShowTooltip() /*&& !IsIgnoringItemPanelEnters()*/ )
|
||
|
{
|
||
|
m_pMouseOverItemPanel->SetGreyedOut( pItemPanel->GetGreyedOutReason() );
|
||
|
m_pMouseOverItemPanel->SetItem( pItem );
|
||
|
m_pMouseOverItemPanel->DirtyDescription(); // Force rebuilding the description when we first display
|
||
|
m_pMouseOverItemPanel->UpdateDescription();
|
||
|
m_pMouseOverItemPanel->HideContainedItemPanel();
|
||
|
m_pMouseOverItemPanel->InvalidateLayout(true);
|
||
|
|
||
|
int x,y;
|
||
|
|
||
|
// If the panel is somewhere in a derived class, we need to get its position in our space
|
||
|
if ( pItemPanel->GetParent() != m_pMouseOverItemPanel->GetParent() )
|
||
|
{
|
||
|
int iItemAbsX, iItemAbsY;
|
||
|
vgui::ipanel()->GetAbsPos( pItemPanel->GetVPanel(), iItemAbsX, iItemAbsY );
|
||
|
int iParentAbsX, iParentAbsY;
|
||
|
vgui::ipanel()->GetAbsPos( m_pMouseOverItemPanel->GetParent()->GetVPanel(), iParentAbsX, iParentAbsY );
|
||
|
|
||
|
x = (iItemAbsX - iParentAbsX);
|
||
|
y = (iItemAbsY - iParentAbsY);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pItemPanel->GetPos( x, y );
|
||
|
}
|
||
|
|
||
|
int iXPos = 0;
|
||
|
int iYPos = 0;
|
||
|
|
||
|
// Loop through the positions in our strategy, and hope we find a valid spot
|
||
|
for ( int i = 0; i < NUM_POSITIONS_PER_STRATEGY; i++ )
|
||
|
{
|
||
|
itempanel_tooltippos_t iPos = g_iTooltipStrategies[m_iPositioningStrategy][i];
|
||
|
GetPosition( iPos, pItemPanel, x, y, &iXPos, &iYPos );
|
||
|
|
||
|
if ( ValidatePosition( pItemPanel, x, y, &iXPos, &iYPos ) )
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
m_pMouseOverItemPanel->SetPos( iXPos, iYPos );
|
||
|
m_pMouseOverItemPanel->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanelToolTip::ShowTooltip( Panel *currentPanel )
|
||
|
{
|
||
|
if ( m_pMouseOverItemPanel && currentPanel != m_hCurrentPanel.Get() )
|
||
|
{
|
||
|
CItemModelPanel *pItemPanel = assert_cast<CItemModelPanel *>(currentPanel);
|
||
|
m_hCurrentPanel.Set( pItemPanel );
|
||
|
pItemPanel->PostActionSignal( new KeyValues("ItemPanelEntered") );
|
||
|
vgui::surface()->PlaySound( "ui/item_info_mouseover.wav" );
|
||
|
|
||
|
m_pMouseOverItemPanel->HideContainedItemPanel();
|
||
|
}
|
||
|
BaseClass::ShowTooltip( currentPanel );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CItemModelPanelToolTip::HideTooltip()
|
||
|
{
|
||
|
if ( m_pMouseOverItemPanel )
|
||
|
{
|
||
|
m_pMouseOverItemPanel->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
if ( m_hCurrentPanel )
|
||
|
{
|
||
|
m_hCurrentPanel.Get()->PostActionSignal( new KeyValues("ItemPanelExited") );
|
||
|
m_hCurrentPanel = NULL;
|
||
|
}
|
||
|
}
|