This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions
+183
View File
@@ -0,0 +1,183 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "ObjectControlPanel.h"
#include <vgui_controls/Controls.h>
#include <vgui_controls/Label.h>
#include "vgui_bitmapbutton.h"
#include <vgui/ISurface.h>
#include <vgui/IVGui.h>
#include "c_tf_player.h"
#include "clientmode_tf.h"
#include <vgui/IScheme.h>
#include <vgui_controls/Slider.h>
#include "vgui_rotation_slider.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define DISMANTLE_WAIT_TIME 5.0
//-----------------------------------------------------------------------------
// Standard VGUI panel for objects
//-----------------------------------------------------------------------------
DECLARE_VGUI_SCREEN_FACTORY( CObjectControlPanel, "object_control_panel" );
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CObjectControlPanel::CObjectControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, panelName, NULL )
{
// Make some high-level panels to group stuff we want to activate/deactivate
m_pActivePanel = new CCommandChainingPanel( this, "ActivePanel" );
SetCursor( vgui::dc_none ); // don't draw a VGUI cursor for this panel, and for its children
// Make sure these are behind everything
m_pActivePanel->SetZPos( -1 );
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CObjectControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Make sure we get ticked...
vgui::ivgui()->AddTickSignal( GetVPanel() );
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
SetCursor( vgui::dc_none ); // don't draw a VGUI cursor for this panel, and for its children
// Make the bounds of the sub-panels match
int x, y, w, h;
GetBounds( x, y, w, h );
m_pActivePanel->SetBounds( x, y, w, h );
// Make em all invisible
m_pActivePanel->SetVisible( false );
m_pCurrentPanel = m_pActivePanel;
return true;
}
//-----------------------------------------------------------------------------
// Returns the object it's attached to
//-----------------------------------------------------------------------------
C_BaseObject *CObjectControlPanel::GetOwningObject() const
{
C_BaseEntity *pScreenEnt = GetEntity();
if (!pScreenEnt)
return NULL;
C_BaseEntity *pObj = pScreenEnt->GetOwnerEntity();
if (!pObj)
return NULL;
Assert( dynamic_cast<C_BaseObject*>(pObj) );
return static_cast<C_BaseObject*>(pObj);
}
//-----------------------------------------------------------------------------
// Ticks the panel when its in its various states
//-----------------------------------------------------------------------------
void CObjectControlPanel::OnTickActive( C_BaseObject *pObj, C_TFPlayer *pLocalPlayer )
{
//ShowDismantleButton( !(pObj->GetFlags() & OF_CANNOT_BE_DISMANTLED) && pObj->GetOwner() == pLocalPlayer );
}
vgui::Panel* CObjectControlPanel::TickCurrentPanel()
{
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
C_BaseObject *pObj = GetOwningObject();
m_pCurrentPanel = GetActivePanel();
OnTickActive(pObj, pLocalPlayer);
return m_pCurrentPanel;
}
void CObjectControlPanel::SendToServerObject( const char *pMsg )
{
C_BaseObject *pObj = GetOwningObject();
if (pObj)
{
pObj->SendClientCommand( pMsg );
}
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CObjectControlPanel::OnTick()
{
BaseClass::OnTick();
C_BaseObject *pObj = GetOwningObject();
if (!pObj)
return;
if ( IsVisible() )
{
// Update the current subpanel
m_pCurrentPanel->SetVisible( false );
m_pCurrentPanel = TickCurrentPanel();
m_pCurrentPanel->SetVisible( true );
}
}
//-----------------------------------------------------------------------------
// Button click handlers
//-----------------------------------------------------------------------------
void CObjectControlPanel::OnCommand( const char *command )
{
BaseClass::OnCommand(command);
}
DECLARE_VGUI_SCREEN_FACTORY( CRotatingObjectControlPanel, "rotating_object_control_panel" );
//-----------------------------------------------------------------------------
// This is a panel for an object that has rotational controls
//-----------------------------------------------------------------------------
CRotatingObjectControlPanel::CRotatingObjectControlPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, panelName )
{
}
bool CRotatingObjectControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Grab ahold of certain well-known controls
m_pRotationSlider = new CRotationSlider( GetActivePanel(), "RotationSlider" );
m_pRotationLabel = new vgui::Label( GetActivePanel(), "RotationLabel", "Rotation Control" );
if (!BaseClass::Init(pKeyValues, pInitData))
return false;
m_pRotationSlider->SetControlledObject( GetOwningObject() );
return true;
}
void CRotatingObjectControlPanel::OnTickActive( C_BaseObject *pObj, C_TFPlayer *pLocalPlayer )
{
BaseClass::OnTickActive( pObj, pLocalPlayer );
bool bEnable = (pObj->GetOwner() == pLocalPlayer);
m_pRotationSlider->SetVisible( bEnable );
m_pRotationLabel->SetVisible( bEnable );
}
+108
View File
@@ -0,0 +1,108 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Clients CBaseObject
//
// $NoKeywords: $
//=============================================================================//
#ifndef OBJECTCONTROLPANEL_H
#define OBJECTCONTROLPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "c_vguiscreen.h"
namespace vgui
{
class Panel;
class Label;
class Button;
}
class C_BaseObject;
class CRotationSlider;
class C_TFPlayer;
//-----------------------------------------------------------------------------
// Base class for all vgui screens on objects:
//-----------------------------------------------------------------------------
class CObjectControlPanel : public CVGuiScreenPanel
{
DECLARE_CLASS( CObjectControlPanel, CVGuiScreenPanel );
public:
CObjectControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnCommand( const char *command );
virtual void OnTick();
protected:
// Method to add controls to particular panels
vgui::Panel *GetActivePanel() { return m_pActivePanel; }
// Override these to deal with various controls in various modes
virtual void OnTickActive( C_BaseObject *pObj, C_TFPlayer *pLocalPlayer );
C_BaseObject *GetOwningObject() const;
// This should update the current panel and return that panel.
virtual vgui::Panel* TickCurrentPanel();
// Send a message to the owner.
void SendToServerObject( const char *pMsg );
private:
vgui::EditablePanel *m_pActivePanel;
vgui::Panel *m_pCurrentPanel;
};
// This is used for child panels. It forwards the messages to the parent panel.
class CCommandChainingPanel : public vgui::EditablePanel
{
typedef vgui::EditablePanel BaseClass;
public:
CCommandChainingPanel( vgui::Panel *parent, const char *panelName ) :
BaseClass( parent, panelName )
{
SetPaintBackgroundEnabled( false );
}
void OnCommand( const char *command )
{
BaseClass::OnCommand( command );
if (GetParent())
{
GetParent()->OnCommand(command);
}
}
};
//-----------------------------------------------------------------------------
// This is a panel for an object that has rotational controls
//-----------------------------------------------------------------------------
class CRotatingObjectControlPanel : public CObjectControlPanel
{
DECLARE_CLASS( CRotatingObjectControlPanel, CObjectControlPanel );
public:
CRotatingObjectControlPanel( vgui::Panel *parent, const char *panelName );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
protected:
virtual void OnTickActive( C_BaseObject *pObj, C_TFPlayer *pLocalPlayer );
private:
CRotationSlider *m_pRotationSlider;
vgui::Label *m_pRotationLabel;
};
#endif // OBJECTCONTROLPANEL_H
+677
View File
@@ -0,0 +1,677 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "backgroundpanel.h"
#include <vgui/IVGui.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <vgui_controls/Label.h>
#include <vgui/ILocalize.h>
#include "vgui_controls/BuildGroup.h"
#include "vgui_controls/BitmapImagePanel.h"
using namespace vgui;
#define DEBUG_WINDOW_RESIZING 0
#define DEBUG_WINDOW_REPOSITIONING 0
//-----------------------------------------------------------------------------
const int NumSegments = 7;
static int coord[NumSegments+1] = {
0,
1,
2,
3,
4,
6,
9,
10
};
//-----------------------------------------------------------------------------
void DrawRoundedBackground( Color bgColor, int wide, int tall )
{
int x1, x2, y1, y2;
surface()->DrawSetColor(bgColor);
surface()->DrawSetTextColor(bgColor);
int i;
// top-left corner --------------------------------------------------------
int xDir = 1;
int yDir = -1;
int xIndex = 0;
int yIndex = NumSegments - 1;
int xMult = 1;
int yMult = 1;
int x = 0;
int y = 0;
for ( i=0; i<NumSegments; ++i )
{
x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
y1 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
y2 = y + coord[NumSegments];
surface()->DrawFilledRect( x1, y1, x2, y2 );
xIndex += xDir;
yIndex += yDir;
}
// top-right corner -------------------------------------------------------
xDir = 1;
yDir = -1;
xIndex = 0;
yIndex = NumSegments - 1;
x = wide;
y = 0;
xMult = -1;
yMult = 1;
for ( i=0; i<NumSegments; ++i )
{
x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
y1 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
y2 = y + coord[NumSegments];
surface()->DrawFilledRect( x1, y1, x2, y2 );
xIndex += xDir;
yIndex += yDir;
}
// bottom-right corner ----------------------------------------------------
xDir = 1;
yDir = -1;
xIndex = 0;
yIndex = NumSegments - 1;
x = wide;
y = tall;
xMult = -1;
yMult = -1;
for ( i=0; i<NumSegments; ++i )
{
x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
y1 = y - coord[NumSegments];
y2 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
surface()->DrawFilledRect( x1, y1, x2, y2 );
xIndex += xDir;
yIndex += yDir;
}
// bottom-left corner -----------------------------------------------------
xDir = 1;
yDir = -1;
xIndex = 0;
yIndex = NumSegments - 1;
x = 0;
y = tall;
xMult = 1;
yMult = -1;
for ( i=0; i<NumSegments; ++i )
{
x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
y1 = y - coord[NumSegments];
y2 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
surface()->DrawFilledRect( x1, y1, x2, y2 );
xIndex += xDir;
yIndex += yDir;
}
// paint between top left and bottom left ---------------------------------
x1 = 0;
x2 = coord[NumSegments];
y1 = coord[NumSegments];
y2 = tall - coord[NumSegments];
surface()->DrawFilledRect( x1, y1, x2, y2 );
// paint between left and right -------------------------------------------
x1 = coord[NumSegments];
x2 = wide - coord[NumSegments];
y1 = 0;
y2 = tall;
surface()->DrawFilledRect( x1, y1, x2, y2 );
// paint between top right and bottom right -------------------------------
x1 = wide - coord[NumSegments];
x2 = wide;
y1 = coord[NumSegments];
y2 = tall - coord[NumSegments];
surface()->DrawFilledRect( x1, y1, x2, y2 );
}
//-----------------------------------------------------------------------------
void DrawRoundedBorder( Color borderColor, int wide, int tall )
{
int x1, x2, y1, y2;
surface()->DrawSetColor(borderColor);
surface()->DrawSetTextColor(borderColor);
int i;
// top-left corner --------------------------------------------------------
int xDir = 1;
int yDir = -1;
int xIndex = 0;
int yIndex = NumSegments - 1;
int xMult = 1;
int yMult = 1;
int x = 0;
int y = 0;
for ( i=0; i<NumSegments; ++i )
{
x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
y1 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
y2 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
surface()->DrawFilledRect( x1, y1, x2, y2 );
xIndex += xDir;
yIndex += yDir;
}
// top-right corner -------------------------------------------------------
xDir = 1;
yDir = -1;
xIndex = 0;
yIndex = NumSegments - 1;
x = wide;
y = 0;
xMult = -1;
yMult = 1;
for ( i=0; i<NumSegments; ++i )
{
x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
y1 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
y2 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
surface()->DrawFilledRect( x1, y1, x2, y2 );
xIndex += xDir;
yIndex += yDir;
}
// bottom-right corner ----------------------------------------------------
xDir = 1;
yDir = -1;
xIndex = 0;
yIndex = NumSegments - 1;
x = wide;
y = tall;
xMult = -1;
yMult = -1;
for ( i=0; i<NumSegments; ++i )
{
x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
y1 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
y2 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
surface()->DrawFilledRect( x1, y1, x2, y2 );
xIndex += xDir;
yIndex += yDir;
}
// bottom-left corner -----------------------------------------------------
xDir = 1;
yDir = -1;
xIndex = 0;
yIndex = NumSegments - 1;
x = 0;
y = tall;
xMult = 1;
yMult = -1;
for ( i=0; i<NumSegments; ++i )
{
x1 = MIN( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
x2 = MAX( x + coord[xIndex]*xMult, x + coord[xIndex+1]*xMult );
y1 = MIN( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
y2 = MAX( y + coord[yIndex]*yMult, y + coord[yIndex+1]*yMult );
surface()->DrawFilledRect( x1, y1, x2, y2 );
xIndex += xDir;
yIndex += yDir;
}
// top --------------------------------------------------------------------
x1 = coord[NumSegments];
x2 = wide - coord[NumSegments];
y1 = 0;
y2 = 1;
surface()->DrawFilledRect( x1, y1, x2, y2 );
// bottom -----------------------------------------------------------------
x1 = coord[NumSegments];
x2 = wide - coord[NumSegments];
y1 = tall - 1;
y2 = tall;
surface()->DrawFilledRect( x1, y1, x2, y2 );
// left -------------------------------------------------------------------
x1 = 0;
x2 = 1;
y1 = coord[NumSegments];
y2 = tall - coord[NumSegments];
surface()->DrawFilledRect( x1, y1, x2, y2 );
// right ------------------------------------------------------------------
x1 = wide - 1;
x2 = wide;
y1 = coord[NumSegments];
y2 = tall - coord[NumSegments];
surface()->DrawFilledRect( x1, y1, x2, y2 );
}
//-----------------------------------------------------------------------------
class CaptionLabel : public Label
{
public:
CaptionLabel(Panel *parent, const char *panelName, const char *text) : Label(parent, panelName, text)
{
}
virtual void ApplySchemeSettings( vgui::IScheme *pScheme )
{
Label::ApplySchemeSettings( pScheme );
SetFont( pScheme->GetFont( "MenuTitle", IsProportional() ) );
}
};
//-----------------------------------------------------------------------------
// Purpose: transform a normalized value into one that is scaled based the minimum
// of the horizontal and vertical ratios
//-----------------------------------------------------------------------------
static int GetAlternateProportionalValueFromNormal(int normalizedValue)
{
int wide, tall;
GetHudSize( wide, tall );
int proH, proW;
surface()->GetProportionalBase( proW, proH );
double scaleH = (double)tall / (double)proH;
double scaleW = (double)wide / (double)proW;
double scale = (scaleW < scaleH) ? scaleW : scaleH;
return (int)( normalizedValue * scale );
}
//-----------------------------------------------------------------------------
// Purpose: transform a standard scaled value into one that is scaled based the minimum
// of the horizontal and vertical ratios
//-----------------------------------------------------------------------------
int GetAlternateProportionalValueFromScaled(vgui::HScheme hScheme, int scaledValue)
{
return GetAlternateProportionalValueFromNormal( scheme()->GetProportionalNormalizedValueEx( hScheme, scaledValue ) );
}
//-----------------------------------------------------------------------------
// Purpose: moves and resizes a single control
//-----------------------------------------------------------------------------
static void RepositionControl( Panel *pPanel )
{
int x, y, w, h;
pPanel->GetBounds(x, y, w, h);
#if DEBUG_WINDOW_RESIZING
int x1, y1, w1, h1;
pPanel->GetBounds(x1, y1, w1, h1);
int x2, y2, w2, h2;
x2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(),x1 );
y2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(),y1 );
w2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(),w1 );
h2 = scheme()->GetProportionalNormalizedValueEx( pPanel->GetScheme(),h1 );
#endif
x = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),x);
y = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),y);
w = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),w);
h = GetAlternateProportionalValueFromScaled(pPanel->GetScheme(),h);
pPanel->SetBounds(x, y, w, h);
#if DEBUG_WINDOW_RESIZING
DevMsg( "Resizing '%s' from (%d,%d) %dx%d to (%d,%d) %dx%d -- initially was (%d,%d) %dx%d\n",
pPanel->GetName(), x1, y1, w1, h1, x, y, w, h, x2, y2, w2, h2 );
#endif
}
//-----------------------------------------------------------------------------
// Purpose: Sets colors etc for background image panels
//-----------------------------------------------------------------------------
void ApplyBackgroundSchemeSettings( EditablePanel *pWindow, vgui::IScheme *pScheme )
{
Color bgColor = Color( 255, 255, 255, pScheme->GetColor( "BgColor", Color( 0, 0, 0, 0 ) )[3] );
Color fgColor = pScheme->GetColor( "FgColor", Color( 0, 0, 0, 0 ) );
if ( !pWindow )
return;
CBitmapImagePanel *pBitmapPanel;
// corners --------------------------------------------
pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopLeftPanel" ));
if ( pBitmapPanel )
{
pBitmapPanel->setImageColor( bgColor );
}
pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopRightPanel" ));
if ( pBitmapPanel )
{
pBitmapPanel->setImageColor( bgColor );
}
pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomLeftPanel" ));
if ( pBitmapPanel )
{
pBitmapPanel->setImageColor( bgColor );
}
pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomRightPanel" ));
if ( pBitmapPanel )
{
pBitmapPanel->setImageColor( bgColor );
}
// background -----------------------------------------
pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "TopSolid" ));
if ( pBitmapPanel )
{
pBitmapPanel->setImageColor( bgColor );
}
pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "UpperMiddleSolid" ));
if ( pBitmapPanel )
{
pBitmapPanel->setImageColor( bgColor );
}
pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "LowerMiddleSolid" ));
if ( pBitmapPanel )
{
pBitmapPanel->setImageColor( bgColor );
}
pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "BottomSolid" ));
if ( pBitmapPanel )
{
pBitmapPanel->setImageColor( bgColor );
}
// Logo -----------------------------------------------
/* pBitmapPanel = dynamic_cast< CBitmapImagePanel * >(pWindow->FindChildByName( "ExclamationPanel" ));
if ( pBitmapPanel )
{
pBitmapPanel->setImageColor( fgColor );
}
*/
}
//-----------------------------------------------------------------------------
// Purpose: Re-aligns background image panels so they are touching.
//-----------------------------------------------------------------------------
static void FixupBackgroundPanels( EditablePanel *pWindow, int offsetX, int offsetY )
{
if ( !pWindow )
return;
int screenWide, screenTall;
pWindow->GetSize( screenWide, screenTall );
int inset = GetAlternateProportionalValueFromNormal( 20 );
int cornerSize = GetAlternateProportionalValueFromNormal( 10 );
int titleHeight = GetAlternateProportionalValueFromNormal( 42 );
int mainHeight = GetAlternateProportionalValueFromNormal( 376 );
int logoSize = titleHeight;
int captionInset = GetAlternateProportionalValueFromNormal( 76 );
Panel *pPanel;
// corners --------------------------------------------
pPanel = pWindow->FindChildByName( "TopLeftPanel" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( offsetX + inset, offsetY + inset, cornerSize, cornerSize );
}
pPanel = pWindow->FindChildByName( "TopRightPanel" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( screenWide - offsetX - inset - cornerSize, offsetY + inset, cornerSize, cornerSize );
}
pPanel = pWindow->FindChildByName( "BottomLeftPanel" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( offsetX + inset, screenTall - offsetY - inset - cornerSize, cornerSize, cornerSize );
}
pPanel = pWindow->FindChildByName( "BottomRightPanel" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( screenWide - offsetX - inset - cornerSize, screenTall - offsetY - inset - cornerSize, cornerSize, cornerSize );
}
// background -----------------------------------------
pPanel = pWindow->FindChildByName( "TopSolid" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( offsetX + inset + cornerSize, offsetY + inset, screenWide - 2*offsetX - 2*inset - 2*cornerSize, cornerSize );
}
pPanel = pWindow->FindChildByName( "UpperMiddleSolid" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( offsetX + inset, offsetY + inset + cornerSize, screenWide - 2*offsetX - 2*inset, titleHeight );
}
pPanel = pWindow->FindChildByName( "LowerMiddleSolid" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( offsetX + inset + cornerSize, screenTall - offsetY - inset - cornerSize, screenWide - 2*offsetX - 2*inset - 2*cornerSize, cornerSize );
}
pPanel = pWindow->FindChildByName( "BottomSolid" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( offsetX + inset, screenTall - offsetY - inset - cornerSize - mainHeight, screenWide - 2*offsetX - 2*inset, mainHeight );
}
// transparent border ---------------------------------
pPanel = pWindow->FindChildByName( "TopClear" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( 0, 0, screenWide, offsetY + inset );
}
pPanel = pWindow->FindChildByName( "BottomClear" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( 0, screenTall - offsetY - inset, screenWide, offsetY + inset );
}
pPanel = pWindow->FindChildByName( "LeftClear" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( 0, offsetY + inset, offsetX + inset, screenTall - 2*offsetY - 2*inset );
}
pPanel = pWindow->FindChildByName( "RightClear" );
if ( pPanel )
{
pPanel->SetZPos( -20 );
pPanel->SetBounds( screenWide - offsetX - inset, offsetY + inset, offsetX + inset, screenTall - 2*offsetY - 2*inset );
}
// Logo -----------------------------------------------
/* int logoInset = (cornerSize + titleHeight - logoSize)/2;
pPanel = pWindow->FindChildByName( "ExclamationPanel" );
if ( pPanel )
{
pPanel->SetZPos( -19 ); // higher than the background
pPanel->SetBounds( offsetX + inset + logoInset, offsetY + inset + logoInset, logoSize, logoSize );
}
*/
// Title caption --------------------------------------
pPanel = dynamic_cast< Label * >(pWindow->FindChildByName( "CaptionLabel" ));
if ( pPanel )
{
pPanel->SetZPos( -19 ); // higher than the background
pPanel->SetBounds( offsetX + captionInset/*inset + 2*logoInset + logoSize*/, offsetY + inset /*+ logoInset*/, screenWide, logoSize );
}
}
//-----------------------------------------------------------------------------
// Purpose: Creates background image panels
//-----------------------------------------------------------------------------
void CreateBackground( EditablePanel *pWindow )
{
// corners --------------------------------------------
new CBitmapImagePanel( pWindow, "TopLeftPanel", "gfx/vgui/round_corner_nw" );
new CBitmapImagePanel( pWindow, "TopRightPanel", "gfx/vgui/round_corner_ne" );
new CBitmapImagePanel( pWindow, "BottomLeftPanel", "gfx/vgui/round_corner_sw" );
new CBitmapImagePanel( pWindow, "BottomRightPanel", "gfx/vgui/round_corner_se" );
// background -----------------------------------------
new CBitmapImagePanel( pWindow, "TopSolid", "gfx/vgui/solid_background" );
new CBitmapImagePanel( pWindow, "UpperMiddleSolid", "gfx/vgui/solid_background" );
new CBitmapImagePanel( pWindow, "LowerMiddleSolid", "gfx/vgui/solid_background" );
new CBitmapImagePanel( pWindow, "BottomSolid", "gfx/vgui/solid_background" );
// transparent border ---------------------------------
new CBitmapImagePanel( pWindow, "TopClear", "gfx/vgui/trans_background" );
new CBitmapImagePanel( pWindow, "BottomClear", "gfx/vgui/trans_background" );
new CBitmapImagePanel( pWindow, "LeftClear", "gfx/vgui/trans_background" );
new CBitmapImagePanel( pWindow, "RightClear", "gfx/vgui/trans_background" );
// Logo -----------------------------------------------
// new CBitmapImagePanel( pWindow, "ExclamationPanel", "gfx/vgui/TF_logo" );
// Title caption --------------------------------------
Panel *pPanel = dynamic_cast< Label * >(pWindow->FindChildByName( "CaptionLabel" ));
if ( !pPanel )
new CaptionLabel( pWindow, "CaptionLabel", "" );
}
void ResizeWindowControls( EditablePanel *pWindow, int tall, int wide, int offsetX, int offsetY )
{
if (!pWindow || !pWindow->GetBuildGroup() || !pWindow->GetBuildGroup()->GetPanelList())
return;
CUtlVector<PHandle> *panelList = pWindow->GetBuildGroup()->GetPanelList();
CUtlVector<Panel *> resizedPanels;
CUtlVector<Panel *> movedPanels;
// Resize to account for 1.25 aspect ratio (1280x1024) screens
{
for ( int i = 0; i < panelList->Size(); ++i )
{
PHandle handle = (*panelList)[i];
Panel *panel = handle.Get();
bool found = false;
for ( int j = 0; j < resizedPanels.Size(); ++j )
{
if (panel == resizedPanels[j])
found = true;
}
if (!panel || found)
{
continue;
}
resizedPanels.AddToTail( panel ); // don't move a panel more than once
if ( panel != pWindow )
{
RepositionControl( panel );
}
}
}
// and now re-center them. Woohoo!
for ( int i = 0; i < panelList->Size(); ++i )
{
PHandle handle = (*panelList)[i];
Panel *panel = handle.Get();
bool found = false;
for ( int j = 0; j < movedPanels.Size(); ++j )
{
if (panel == movedPanels[j])
found = true;
}
if (!panel || found)
{
continue;
}
movedPanels.AddToTail( panel ); // don't move a panel more than once
if ( panel != pWindow )
{
int x, y;
panel->GetPos( x, y );
panel->SetPos( x + offsetX, y + offsetY );
#if DEBUG_WINDOW_REPOSITIONING
DevMsg( "Repositioning '%s' from (%d,%d) to (%d,%d) -- a distance of (%d,%d)\n",
panel->GetName(), x, y, x + offsetX, y + offsetY, offsetX, offsetY );
#endif
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Resizes windows to fit completely on-screen (for 1280x1024), and
// centers them on the screen. Sub-controls are also resized and moved.
//-----------------------------------------------------------------------------
void LayoutBackgroundPanel( EditablePanel *pWindow )
{
if ( !pWindow )
return;
int screenW, screenH;
GetHudSize( screenW, screenH );
int wide, tall;
pWindow->GetSize( wide, tall );
int offsetX = 0;
int offsetY = 0;
// Slide everything over to the center
pWindow->SetBounds( 0, 0, screenW, screenH );
if ( wide != screenW || tall != screenH )
{
wide = GetAlternateProportionalValueFromScaled(pWindow->GetScheme(), wide);
tall = GetAlternateProportionalValueFromScaled(pWindow->GetScheme(), tall);
offsetX = (screenW - wide)/2;
offsetY = (screenH - tall)/2;
ResizeWindowControls( pWindow, tall, wide, offsetX, offsetY );
}
// now that the panels are moved/resized, look for some bg panels, and re-align them
FixupBackgroundPanels( pWindow, offsetX, offsetY );
}
//-----------------------------------------------------------------------------
+53
View File
@@ -0,0 +1,53 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TFBACKGROUND_H
#define TFBACKGROUND_H
#include <vgui_controls/Frame.h>
#include <vgui_controls/EditablePanel.h>
//-----------------------------------------------------------------------------
// Purpose: Creates background image panels
//-----------------------------------------------------------------------------
void CreateBackground( vgui::EditablePanel *pWindow );
//-----------------------------------------------------------------------------
// Purpose: Resizes windows to fit completely on-screen (for 1280x1024), and
// centers them on the screen. Sub-controls are also resized and moved.
//-----------------------------------------------------------------------------
void LayoutBackgroundPanel( vgui::EditablePanel *pWindow );
//-----------------------------------------------------------------------------
// Purpose: Sets colors etc for background image panels
//-----------------------------------------------------------------------------
void ApplyBackgroundSchemeSettings( vgui::EditablePanel *pWindow, vgui::IScheme *pScheme );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ResizeWindowControls( vgui::EditablePanel *pWindow, int tall, int wide, int offsetX, int offsetY );
//-----------------------------------------------------------------------------
// Purpose: transform a standard scaled value into one that is scaled based the minimum
// of the horizontal and vertical ratios
//-----------------------------------------------------------------------------
int GetAlternateProportionalValueFromScaled( vgui::HScheme hScheme, int scaledValue );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void DrawRoundedBackground( Color bgColor, int wide, int tall );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void DrawRoundedBorder( Color borderColor, int wide, int tall );
//-----------------------------------------------------------------------------
#endif // TFBACKGROUND_H
+185
View File
@@ -0,0 +1,185 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "vgui/IInput.h"
#include <vgui/IVGui.h>
#include <vgui/IScheme.h>
#include "blueprint_panel.h"
#include "vgui_controls/TextImage.h"
#include "vgui_controls/Label.h"
#include "vgui_controls/Button.h"
#include "ienginevgui.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "renderparm.h"
DECLARE_BUILD_FACTORY( CBlueprintPanel );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBlueprintPanel::CBlueprintPanel( vgui::Panel *parent, const char *name ) : vgui::EditablePanel( parent, name )
{
m_bClickable = false;
m_bMouseOver = false;
m_bInStack = false;
SetActAsButton( false, false );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlueprintPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/build_menu/base_selectable.res" );
m_pItemNameLabel = dynamic_cast<vgui::Label*>( FindChildByName("ItemNameLabel") );
m_pItemCostLabel = dynamic_cast<vgui::Label*>( FindChildByName("CostLabel") );
m_pIcon = dynamic_cast<CIconPanel*>( FindChildByName("BuildingIcon") );
m_pMetalIcon = dynamic_cast<CIconPanel*>( FindChildByName("MetalIcon") );
m_pBackground = dynamic_cast<CIconPanel*>( FindChildByName("ItemBackground") );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlueprintPanel::SetObjectInfo( const CObjectInfo* pNewInfo )
{
m_pObjectInfo = pNewInfo;
bool bVisible = pNewInfo != NULL;
if ( m_pItemNameLabel )
{
if ( m_pObjectInfo )
{
m_pItemNameLabel->SetText( m_pObjectInfo->m_pBuilderWeaponName );
}
m_pItemNameLabel->SetVisible( bVisible );
}
if ( m_pItemCostLabel )
{
if ( m_pObjectInfo )
{
V_snprintf( m_pszCost, sizeof( m_pszCost ), "%i", m_pObjectInfo->m_Cost );
m_pItemCostLabel->SetText( m_pszCost );
}
m_pItemCostLabel->SetVisible( bVisible );
}
if ( m_pIcon )
{
if ( m_pObjectInfo )
{
m_pIcon->SetIcon( m_pObjectInfo->m_pIconMenu );
}
m_pIcon->SetVisible( bVisible );
}
if ( m_pMetalIcon )
{
m_pMetalIcon->SetVisible( bVisible );
}
if ( m_pBackground )
{
m_pBackground->SetVisible( bVisible );
}
SetVisible( bVisible );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlueprintPanel::SetActAsButton( bool bClickable, bool bMouseOver )
{
m_bClickable = bClickable;
m_bMouseOver = bMouseOver;
SetMouseInputEnabled( m_bClickable || m_bMouseOver );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlueprintPanel::OnCursorEntered( void )
{
if ( !m_bMouseOver )
return;
PostActionSignal( new KeyValues("BlueprintPanelEntered") );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlueprintPanel::OnCursorExited( void )
{
if ( !m_bMouseOver )
return;
PostActionSignal( new KeyValues("BlueprintPanelExited") );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlueprintPanel::OnMousePressed(vgui::MouseCode code)
{
if ( !m_bClickable || code != MOUSE_LEFT )
return;
PostActionSignal( new KeyValues("BlueprintPanelMousePressed") );
vgui::surface()->PlaySound( "UI/buttonclick.wav" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlueprintPanel::OnMouseReleased(vgui::MouseCode code)
{
if ( !m_bClickable || code != MOUSE_LEFT )
return;
PostActionSignal( new KeyValues("BlueprintPanelMouseReleased") );
vgui::surface()->PlaySound( "UI/buttonclickrelease.wav" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlueprintPanel::OnMouseDoublePressed(vgui::MouseCode code)
{
if ( !m_bClickable || code != MOUSE_LEFT )
return;
PostActionSignal( new KeyValues("BlueprintPanelMouseDoublePressed") );
vgui::surface()->PlaySound( "UI/buttonclickrelease.wav" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBlueprintPanel::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("BlueprintPanelCursorMoved", "x", x + iXPos, "y", y + iYPos) );
}
+61
View File
@@ -0,0 +1,61 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BLUEPRINT_PANEL_H
#define BLUEPRINT_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Panel.h>
#include <vgui_controls/Frame.h>
#include "tf_shareddefs.h"
#include "IconPanel.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CBlueprintPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CBlueprintPanel, vgui::EditablePanel );
public:
CBlueprintPanel( vgui::Panel *parent, const char *name );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
void SetObjectInfo( const CObjectInfo* pNewInfo );
const CObjectInfo* GetObjectInfo( void ) { return m_pObjectInfo; }
// Button functionality
void SetActAsButton( bool bClickable, bool bMouseOver );
virtual void OnCursorEntered();
virtual void OnCursorExited();
virtual void OnMousePressed(vgui::MouseCode code);
virtual void OnMouseDoublePressed(vgui::MouseCode code);
virtual void OnMouseReleased(vgui::MouseCode code);
MESSAGE_FUNC_INT_INT( OnCursorMoved, "OnCursorMoved", x, y );
void SetInStack( bool bVal ) { m_bInStack = bVal; }
bool IsInStack( void ) { return m_bInStack; }
vgui::Label *m_pItemNameLabel;
vgui::Label *m_pItemCostLabel;
char m_pszCost[8];
CIconPanel *m_pMetalIcon;
CIconPanel *m_pIcon;
CIconPanel *m_pBackground;
const CObjectInfo* m_pObjectInfo;
bool m_bClickable;
bool m_bMouseOver;
bool m_bInStack;
};
#endif // BLUEPRINT_PANEL_H
@@ -0,0 +1,864 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "character_info_panel.h"
#include "tf_statsummary.h"
#include "vgui_controls/PropertySheet.h"
#include "vgui/IInput.h"
#include "baseviewport.h"
#include "iclientmode.h"
#include "charinfo_loadout_subpanel.h"
#include "charinfo_armory_subpanel.h"
#include "ienginevgui.h"
#include "tf_hud_statpanel.h"
#include "c_tf_player.h"
#include "tf_item_inventory.h"
#include "econ_notifications.h"
#include <vgui/ILocalize.h>
#include <vgui_controls/AnimationController.h>
#include "econ_ui.h"
#include "c_tf_gamestats.h"
#include "tf_item_pickup_panel.h"
#include "store/v1/tf_store_panel.h"
#include "store/v2/tf_store_panel2.h"
#include "store/tf_store.h"
#include "tf_matchmaking_dashboard.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
static vgui::DHANDLE<CCharacterInfoPanel> g_CharInfoPanel;
IEconRootUI* EconUI( void )
{
if (!g_CharInfoPanel.Get())
{
g_CharInfoPanel = new CCharacterInfoPanel( NULL );
g_CharInfoPanel->MakeReadyForUse();
g_CharInfoPanel->InvalidateLayout( false, true );
}
return g_CharInfoPanel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CServerNotConnectedToSteamDialog *OpenServerNotConnectedToSteamDialog( vgui::Panel *pParent );
//-----------------------------------------------------------------------------
// Purpose: Basic help dialog
//-----------------------------------------------------------------------------
CCharacterInfoPanel::CCharacterInfoPanel( Panel *parent ) : PropertyDialog(parent, "character_info")
{
// Character info is parented to the game UI panel
vgui::VPANEL gameuiPanel = enginevgui->GetPanel( PANEL_GAMEUIDLL );
SetParent( gameuiPanel );
// We don't want the gameui to delete us, or things get messy
SetAutoDelete( false );
SetMoveable( false );
SetSizeable( false );
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
SetScheme(scheme);
SetProportional( true );
// Character loadouts
m_pLoadoutPanel = new CCharInfoLoadoutSubPanel(this);
m_pLoadoutPanel->AddActionSignalTarget( this );
AddPage( m_pLoadoutPanel, "#Loadout");
// Stat summary
CTFStatsSummaryPanel *pStatSummaryPanel = new CTFStatsSummaryPanel(this);
pStatSummaryPanel->SetupForEmbedded();
AddPage( pStatSummaryPanel, "#Stats");
CTFStatPanel *pStatPanel = GET_HUDELEMENT( CTFStatPanel );
if ( pStatPanel )
{
// Ask for our embedded stat summary be updated immediately
pStatPanel->UpdateStatSummaryPanel();
}
// Achievements
//AddPage(new CCharacterInfoSubAchievements(this), "#Achievements");
ListenForGameEvent( "gameui_hidden" );
m_pLoadoutPanel->SetVisible( false );
m_pNotificationsPresentPanel = NULL;
m_bPreventClosure = false;
m_iClosePanel = ECONUI_BASEUI;
m_iDefaultTeam = TF_TEAM_RED;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCharacterInfoPanel::~CCharacterInfoPanel()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/CharInfoPanel.res" );
SetOKButtonVisible(false);
SetCancelButtonVisible(false);
m_pNotificationsPresentPanel = FindChildByName( "NotificationsPresentPanel" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::PerformLayout( void )
{
if ( GetVParent() )
{
int w,h;
vgui::ipanel()->GetSize( GetVParent(), w, h );
SetBounds(0,0,w,h);
}
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::ShowPanel(bool bShow)
{
m_bPreventClosure = false;
// Keep the MM dashboard on top of us
bShow ? GetMMDashboardParentManager()->PushModalFullscreenPopup( this )
: GetMMDashboardParentManager()->PopModalFullscreenPopup( this );
if ( bShow )
{
if ( GetPropertySheet()->GetActivePage() != m_pLoadoutPanel )
{
GetPropertySheet()->SetActivePage( m_pLoadoutPanel );
}
else
{
// VGUI doesn't tell the starting active page that it's active, so we post a pageshow to it
ivgui()->PostMessage( m_pLoadoutPanel->GetVPanel(), new KeyValues("PageShow"), GetPropertySheet()->GetVPanel() );
}
//InvalidateLayout( false, true );
Activate();
int iClass = m_pLoadoutPanel->GetCurrentClassIndex();
OpenLoadoutToClass( iClass, false );
}
else
{
PostMessage( m_pLoadoutPanel, new KeyValues("CancelSelection") );
}
bool bWasVisible = IsVisible() && m_pLoadoutPanel->IsVisible();
SetVisible( bShow );
if ( bWasVisible && !bShow )
{
m_pLoadoutPanel->OnCharInfoClosing();
// Clear this out so it doesn't affect anything the next time the econ UI is opened
m_iClosePanel = ECONUI_BASEUI;
m_iDefaultTeam = TF_TEAM_RED;
}
m_pLoadoutPanel->SetVisible( bShow );
// When we first appear, if we're on a server that couldn't get our loadout, show the failure dialog.
if ( !bWasVisible && bShow )
{
if ( engine->IsInGame() )
{
C_TFPlayer *pLocal = C_TFPlayer::GetLocalTFPlayer();
if ( pLocal && pLocal->m_Shared.IsLoadoutUnavailable() )
{
OpenServerNotConnectedToSteamDialog( this );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::FireGameEvent( IGameEvent *event )
{
const char * type = event->GetName();
if ( Q_strcmp(type, "gameui_hidden") == 0 )
{
if ( m_bPreventClosure )
{
engine->ClientCmd_Unrestricted( "gameui_activate" );
}
else
{
ShowPanel( false );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::Close()
{
ShowPanel( false );
PostMessage( m_pLoadoutPanel, new KeyValues("CharInfoClosing") );
// If we're connected to a game server, we also close the game UI.
if ( engine->IsInGame() )
{
bool bClose = true;
if ( m_bCheckForRoomOnExit )
{
// Check to make sure the player has room for all his items. If not, bring up the discard panel. Otherwise, go away.
// We need to do this to catch players who used the "Change Loadout" button in the pickup panel, and may be out of room.
bClose = !TFInventoryManager()->CheckForRoomAndForceDiscard();
}
if ( bClose )
{
engine->ClientCmd_Unrestricted( "gameui_hide" );
}
}
// Notify any listeners that we're closed
NotifyListenersOfCloseEvent();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::NotifyListenersOfCloseEvent()
{
FOR_EACH_VEC( m_vecOnCloseListeners, i )
{
if ( m_vecOnCloseListeners[i].Get() )
{
PostMessage( m_vecOnCloseListeners[i].Get(), new KeyValues( "EconUIClosed" ) );
}
}
// Clear that motherfucker out
m_vecOnCloseListeners.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::OnCommand( const char *command )
{
if ( FStrEq( command, "back" ) )
{
// If we're at the base loadout page, or if we want to force it, close the dialog completely...
// NOTE: Right now we don't support closing from the item selection screen.
const int iShowingPanel = m_pLoadoutPanel->GetShowingPanel();
const int iCurrentClassIndex = m_pLoadoutPanel->GetCurrentClassIndex();
const bool bIsInSelectionPanel = iShowingPanel == CHAP_LOADOUT && m_pLoadoutPanel->GetClassLoadoutPanel()->IsInSelectionPanel();
const bool bNoClass = iCurrentClassIndex == TF_CLASS_UNDEFINED;
const bool bAtClosePanel = !bIsInSelectionPanel &&
( ( iShowingPanel == m_iClosePanel && bNoClass ) || ( iShowingPanel == CHAP_LOADOUT && -m_iClosePanel == iCurrentClassIndex ) );
const bool bAtBaseLoadoutPage = iShowingPanel == CHAP_LOADOUT && bNoClass;
if ( bAtClosePanel || bAtBaseLoadoutPage )
{
Close();
}
// In the item selection panel?
else if ( bIsInSelectionPanel )
{
m_pLoadoutPanel->GetClassLoadoutPanel()->GetItemSelectionPanel()->OnBackPressed();
}
// In any other panel, just go back.
else
{
ShowPanel( true );
}
}
else
{
engine->ClientCmd( const_cast<char *>( command ) );
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::OpenLoadoutToClass( int iClassIndex, bool bOpenClassLoadout )
{
Assert(iClassIndex >= TF_CLASS_UNDEFINED && iClassIndex < TF_CLASS_COUNT);
m_pLoadoutPanel->SetClassIndex( iClassIndex, bOpenClassLoadout );
m_pLoadoutPanel->SetTeamIndex( m_iDefaultTeam );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::OpenLoadoutToBackpack( void )
{
m_pLoadoutPanel->OpenToBackpack();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::OpenLoadoutToCrafting( void )
{
m_pLoadoutPanel->OpenToCrafting();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::OpenLoadoutToArmory( void )
{
m_pLoadoutPanel->OpenToArmory();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::OnOpenArmoryDirect( KeyValues *data )
{
int iItemDef = data->GetInt( "itemdef", 0 );
m_pLoadoutPanel->OpenToArmory( iItemDef );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::OnKeyCodeTyped(vgui::KeyCode code)
{
if ( code == KEY_ESCAPE )
{
if ( !m_bPreventClosure )
{
OnCommand( "back" );
}
}
else
{
BaseClass::OnKeyCodeTyped( code );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::OnKeyCodePressed(vgui::KeyCode code)
{
ButtonCode_t nButtonCode = GetBaseButtonCode( code );
if ( nButtonCode == KEY_XBUTTON_B )
{
if ( !m_bPreventClosure )
{
OnCommand( "back" );
}
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::OnThink()
{
bool bShouldBeVisible = NotificationQueue_GetNumNotifications() != 0;
if ( m_pNotificationsPresentPanel != NULL && m_pNotificationsPresentPanel->IsVisible() != bShouldBeVisible )
{
m_pNotificationsPresentPanel->SetVisible( bShouldBeVisible );
if ( bShouldBeVisible )
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "NotificationsPresentBlink" );
}
else
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "NotificationsPresentBlinkStop" );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
IEconRootUI *CCharacterInfoPanel::OpenEconUI( int iDirectToPage, bool bCheckForInventorySpaceOnExit )
{
engine->ClientCmd_Unrestricted( "gameui_activate" );
ShowPanel( true );
if ( iDirectToPage == ECONUI_BACKPACK )
{
OpenLoadoutToBackpack();
}
else if ( iDirectToPage == ECONUI_CRAFTING )
{
OpenLoadoutToCrafting();
}
else if ( iDirectToPage == ECONUI_ARMORY )
{
OpenLoadoutToArmory();
}
else if ( iDirectToPage < 0 )
{
// Negative numbers go directly to the class loadout
OpenLoadoutToClass( -(iDirectToPage), true );
}
SetCheckForRoomOnExit( bCheckForInventorySpaceOnExit );
return this;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::CloseEconUI( void )
{
if ( IsVisible() )
{
ShowPanel( false );
NotifyListenersOfCloseEvent();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CCharacterInfoPanel::IsUIPanelVisible( EconBaseUIPanels_t iPanel )
{
if ( !IsVisible() )
return false;
switch ( iPanel )
{
case ECONUI_BACKPACK:
return (GetBackpackPanel() && GetBackpackPanel()->IsVisible());
case ECONUI_CRAFTING:
return (GetCraftingPanel() && GetCraftingPanel()->IsVisible());
case ECONUI_ARMORY:
return (GetArmoryPanel() && GetArmoryPanel()->IsVisible());
case ECONUI_TRADING:
break;
default:
Assert(0);
break;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Open_CharInfo( const CCommand &args )
{
EconUI()->OpenEconUI();
}
ConCommand open_charinfo( "open_charinfo", Open_CharInfo, "Open the character info panel", FCVAR_NONE );
void CCharacterInfoPanel::SetPreventClosure( bool bPrevent )
{
m_bPreventClosure = bPrevent;
Panel* pBackButton = FindChildByName( "BackButton" );
if ( pBackButton )
{
pBackButton->SetEnabled( !bPrevent );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Open_CharInfoDirect( const CCommand &args )
{
// If we're in-game, start by opening the class we're currently playing
int iClass = TF_CLASS_UNDEFINED;
if ( engine->IsInGame() )
{
C_TFPlayer *pLocal = C_TFPlayer::GetLocalTFPlayer();
if ( pLocal )
{
iClass = -(pLocal->m_Shared.GetDesiredPlayerClassIndex());
if ( iClass == TF_CLASS_UNDEFINED )
{
iClass = -(pLocal->GetPlayerClass()->GetClassIndex());
}
}
}
// override with command arg
if ( args.ArgC() > 1 )
{
iClass = -atoi( args.Arg( 1 ) );
}
EconUI()->OpenEconUI( iClass );
}
ConCommand open_charinfo_direct( "open_charinfo_direct", Open_CharInfoDirect, "Open the character info panel directly to the class you're currently playing.", FCVAR_NONE );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Open_CharInfoBackpack( const CCommand &args )
{
EconUI()->OpenEconUI( ECONUI_BACKPACK );
}
ConCommand open_charinfo_backpack( "open_charinfo_backpack", Open_CharInfoBackpack, "Open the character info panel directly to backpack.", FCVAR_NONE );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Open_CharInfoCrafting( const CCommand &args )
{
EconUI()->OpenEconUI( ECONUI_CRAFTING );
}
ConCommand open_charinfo_crafting( "open_charinfo_crafting", Open_CharInfoCrafting, "Open the character info panel directly to crafting screen.", FCVAR_NONE );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Open_CharInfoArmory( const CCommand &args )
{
EconUI()->OpenEconUI( ECONUI_ARMORY );
}
ConCommand open_charinfo_armory( "open_charinfo_armory", Open_CharInfoArmory, "Open the character info panel directly to armory.", FCVAR_NONE );
//================================================================================================================================
// NOT CONNECTED TO STEAM WARNING DIALOG
//================================================================================================================================
static vgui::DHANDLE<CServerNotConnectedToSteamDialog> g_ServerNotConnectedPanel;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CServerNotConnectedToSteamDialog::CServerNotConnectedToSteamDialog( vgui::Panel *pParent, const char *pElementName ) : BaseClass( pParent, "ServerNotConnectedToSteamDialog" )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CServerNotConnectedToSteamDialog::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
// load control settings...
LoadControlSettings( "resource/UI/ServerNotConnectedToSteam.res" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CServerNotConnectedToSteamDialog::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "close" ) )
{
TFModalStack()->PopModal( this );
SetVisible( false );
return;
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CServerNotConnectedToSteamDialog *OpenServerNotConnectedToSteamDialog( vgui::Panel *pParent )
{
if (!g_ServerNotConnectedPanel.Get())
{
g_ServerNotConnectedPanel = vgui::SETUP_PANEL( new CServerNotConnectedToSteamDialog( pParent, NULL ) );
}
g_ServerNotConnectedPanel->InvalidateLayout( false, true );
g_ServerNotConnectedPanel->SetVisible( true );
g_ServerNotConnectedPanel->MakePopup();
g_ServerNotConnectedPanel->MoveToFront();
g_ServerNotConnectedPanel->SetKeyBoardInputEnabled(true);
g_ServerNotConnectedPanel->SetMouseInputEnabled(true);
TFModalStack()->PushModal( g_ServerNotConnectedPanel );
return g_ServerNotConnectedPanel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBackpackPanel *CCharacterInfoPanel::GetBackpackPanel( void )
{
return m_pLoadoutPanel->GetBackpackPanel();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCraftingPanel *CCharacterInfoPanel::GetCraftingPanel( void )
{
return m_pLoadoutPanel->GetCraftingPanel();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CArmoryPanel *CCharacterInfoPanel::GetArmoryPanel( void )
{
return m_pLoadoutPanel->GetArmoryPanel();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::Gamestats_ItemTransaction( int eventID, CEconItemView *item, const char *pszReason, int iQuality )
{
C_CTF_GameStats.Event_ItemTransaction( eventID, item, pszReason, iQuality );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::Gamestats_Store( int eventID, CEconItemView* item, const char* panelName, int classId,
const cart_item_t* cartItem, int checkoutAttempts, const char* storeError, int totalPrice, int currencyCode )
{
C_CTF_GameStats.Event_Store( eventID, item, panelName, classId, cartItem, checkoutAttempts, storeError, totalPrice, currencyCode );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::SetExperimentValue( uint64 experimentValue )
{
C_CTF_GameStats.SetExperimentValue( experimentValue );
}
static vgui::DHANDLE<CTFItemPickupPanel> g_TFItemPickupPanel;
static vgui::DHANDLE<CTFItemDiscardPanel> g_TFItemDiscardPanel;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CItemPickupPanel *CCharacterInfoPanel::OpenItemPickupPanel( void )
{
if (!g_TFItemPickupPanel.Get())
{
g_TFItemPickupPanel = vgui::SETUP_PANEL( new CTFItemPickupPanel( NULL ) );
g_TFItemPickupPanel->InvalidateLayout( false, true );
}
engine->ClientCmd_Unrestricted( "gameui_activate" );
g_TFItemPickupPanel->ShowPanel( true );
return g_TFItemPickupPanel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CItemDiscardPanel *CCharacterInfoPanel::OpenItemDiscardPanel( void )
{
if (!g_TFItemDiscardPanel.Get())
{
g_TFItemDiscardPanel = vgui::SETUP_PANEL( new CTFItemDiscardPanel( NULL ) );
g_TFItemDiscardPanel->InvalidateLayout( false, true );
}
engine->ClientCmd_Unrestricted( "gameui_activate" );
g_TFItemDiscardPanel->ShowPanel( true );
return g_TFItemDiscardPanel;
}
static vgui::DHANDLE<CTFBaseStorePanel> g_StorePanel;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::CreateStorePanel( void )
{
// Clean up previous store panel?
if ( g_StorePanel.Get() != NULL )
{
g_StorePanel->MarkForDeletion();
}
// Create the store panel
CTFBaseStorePanel *pStorePanel = NULL;
if ( ShouldUseNewStore() )
{
pStorePanel = new CTFStorePanel2( NULL );
}
else
{
pStorePanel = new CTFStorePanel1( NULL );
}
g_StorePanel = vgui::SETUP_PANEL( pStorePanel );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStorePanel *CCharacterInfoPanel::OpenStorePanel( int iItemDef, bool bAddToCart )
{
// Make sure we've got the appropriate connections to Steam
if ( !steamapicontext || !steamapicontext->SteamUtils() )
{
OpenStoreStatusDialog( NULL, "#StoreUpdate_SteamRequired", true, false );
return NULL;
}
if ( !steamapicontext->SteamUtils()->IsOverlayEnabled() )
{
OpenStoreStatusDialog( NULL, "#StoreUpdate_OverlayRequired", true, false );
return NULL;
}
if ( !CStorePanel::IsPricesheetLoaded() )
{
OpenStoreStatusDialog( NULL, "#StoreUpdate_Loading", false, false );
CStorePanel::SetShouldShowWarnings( true );
CStorePanel::RequestPricesheet();
return NULL;
}
if ( !g_StorePanel )
return NULL;
engine->ClientCmd_Unrestricted( "gameui_activate" );
if ( iItemDef )
{
g_StorePanel->StartAtItemDef( iItemDef, bAddToCart );
}
g_StorePanel->ShowPanel( true );
return g_StorePanel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStorePanel *CCharacterInfoPanel::GetStorePanel( void )
{
return g_StorePanel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::AddPanelCloseListener( vgui::Panel *pListener )
{
if ( !pListener )
return;
VPanelHandle hPanel;
hPanel.Set( pListener->GetVPanel() );
m_vecOnCloseListeners.AddToHead( hPanel );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCharacterInfoPanel::SetClosePanel( int iPanel )
{
AssertMsg( ( iPanel < 0 && IsValidTFPlayerClass( -iPanel ) ) ||
( iPanel >= ECONUI_FIRST_PANEL && iPanel <= ECONUI_LAST_PANEL ),
"Panel out of range!"
);
m_iClosePanel = iPanel;
}
void CCharacterInfoPanel::SetDefaultTeam( int iTeam )
{
AssertMsg( iTeam == TF_TEAM_RED || iTeam == TF_TEAM_BLUE, "Invalid team" );
m_iDefaultTeam = iTeam;
}
//================================================================================================================================
// NOT CONNECTED TO STEAM WARNING DIALOG
//================================================================================================================================
static vgui::DHANDLE<CCheatDetectionDialog> g_CheatDetectionDialog;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCheatDetectionDialog::CCheatDetectionDialog( vgui::Panel *pParent, const char *pElementName ) : BaseClass( pParent, "CheatDetectionDialog" )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCheatDetectionDialog::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
// load control settings...
LoadControlSettings( "resource/UI/CheatDetectionDialog.res" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCheatDetectionDialog::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "close" ) )
{
TFModalStack()->PopModal( this );
SetVisible( false );
return;
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCheatDetectionDialog *OpenCheatDetectionDialog( vgui::Panel *pParent, const char *pszCheatMessage )
{
if (!g_CheatDetectionDialog.Get())
{
g_CheatDetectionDialog = vgui::SETUP_PANEL( new CCheatDetectionDialog( pParent, NULL ) );
}
g_CheatDetectionDialog->InvalidateLayout( false, true );
g_CheatDetectionDialog->SetVisible( true );
g_CheatDetectionDialog->MakePopup();
g_CheatDetectionDialog->MoveToFront();
g_CheatDetectionDialog->SetKeyBoardInputEnabled(true);
g_CheatDetectionDialog->SetMouseInputEnabled(true);
TFModalStack()->PushModal( g_CheatDetectionDialog );
g_CheatDetectionDialog->SetDialogVariable( "reason", g_pVGuiLocalize->Find( pszCheatMessage ) );
return g_CheatDetectionDialog;
}
+135
View File
@@ -0,0 +1,135 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CHARACTER_INFO_PANEL_H
#define CHARACTER_INFO_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "econ_ui.h"
#include "vgui_controls/PropertyDialog.h"
#include "tf_shareddefs.h"
#include "GameEventListener.h"
#include "vgui_controls/Panel.h"
#include "vgui_controls/PHandle.h"
class CCharInfoLoadoutSubPanel;
class CArmoryPanel;
class CBackpackPanel;
class CCraftingPanel;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CServerNotConnectedToSteamDialog : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CServerNotConnectedToSteamDialog, vgui::EditablePanel );
public:
CServerNotConnectedToSteamDialog( vgui::Panel *pParent, const char *pElementName );
virtual void ApplySchemeSettings( vgui::IScheme *scheme );
virtual void OnCommand( const char *command );
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CCheatDetectionDialog : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CCheatDetectionDialog, vgui::EditablePanel );
public:
CCheatDetectionDialog( vgui::Panel *pParent, const char *pElementName );
virtual void ApplySchemeSettings( vgui::IScheme *scheme );
virtual void OnCommand( const char *command );
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CCharacterInfoPanel : public vgui::PropertyDialog, public IEconRootUI, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CCharacterInfoPanel, vgui::PropertyDialog );
public:
CCharacterInfoPanel( Panel *parent );
virtual ~CCharacterInfoPanel();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout( void );
virtual void OnCommand( const char *command );
virtual void ShowPanel( bool bShow );
virtual void OnKeyCodeTyped(vgui::KeyCode code) OVERRIDE;
virtual void OnKeyCodePressed(vgui::KeyCode code) OVERRIDE;
virtual void OnThink();
void OpenLoadoutToClass( int iClassIndex, bool bOpenClassLoadout );
void OpenLoadoutToBackpack( void );
void OpenLoadoutToCrafting( void );
void OpenLoadoutToArmory( void );
void SetCheckForRoomOnExit( bool bCheck ) { m_bCheckForRoomOnExit = bCheck; }
void FireGameEvent( IGameEvent *event );
CArmoryPanel *GetArmoryPanel( void );
MESSAGE_FUNC_PARAMS( OnOpenArmoryDirect, "OpenArmoryDirect", data );
//---------------------------------------
// IEconRootUI
virtual IEconRootUI *OpenEconUI( int iDirectToPage = 0, bool bCheckForInventorySpaceOnExit = false );
virtual void CloseEconUI( void );
virtual bool IsUIPanelVisible( EconBaseUIPanels_t iPanel );
virtual void SetPreventClosure( bool bPrevent ) OVERRIDE;
// Sub panel access.
// These are panels that are parented to the root EconUI.
virtual CBackpackPanel *GetBackpackPanel( void );
virtual CCraftingPanel *GetCraftingPanel( void );
// Gamestats access
virtual void Gamestats_ItemTransaction( int eventID, CEconItemView *item, const char *pszReason = NULL, int iQuality = 0 );
virtual void Gamestats_Store( int eventID, CEconItemView* item=NULL, const char* panelName=NULL,
int classId=0, const cart_item_t* in_cartItem=NULL, int in_checkoutAttempts=0, const char* storeError=NULL, int in_totalPrice=0, int in_currencyCode=0 );
virtual void SetExperimentValue( uint64 experimentValue );
// Open separate economy panels (they're not parented to the root EconUI)
// This is here so that games can customize the implementation of these panels.
virtual CItemPickupPanel *OpenItemPickupPanel( void );
virtual CItemDiscardPanel *OpenItemDiscardPanel( void );
virtual void CreateStorePanel( void );
virtual CStorePanel *OpenStorePanel( int iItemDef, bool bAddToCart );
virtual CStorePanel *GetStorePanel( void );
// When the root UI is closed, send an "EconUIClosed" message to pListener.
virtual void AddPanelCloseListener( vgui::Panel *pListener );
// The panel at which we want back to actually close the UI - defaults to the root panel - a negative value can be passed in for class loadout panels
virtual void SetClosePanel( int iPanel );
// Call this to set which team the class loadout should display
virtual void SetDefaultTeam( int iTeam );
private:
void Close();
void NotifyListenersOfCloseEvent();
vgui::Panel *m_pNotificationsPresentPanel;
CCharInfoLoadoutSubPanel *m_pLoadoutPanel;
bool m_bCheckForRoomOnExit;
bool m_bPreventClosure;
int m_iClosePanel;
int m_iDefaultTeam;
CUtlVector< vgui::VPanelHandle > m_vecOnCloseListeners;
};
CCheatDetectionDialog *OpenCheatDetectionDialog( vgui::Panel *pParent, const char *pszCheatMessage );
#endif // CHARACTER_INFO_PANEL_H
@@ -0,0 +1,945 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "charinfo_armory_subpanel.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
#include "vgui/ILocalize.h"
#include "c_tf_player.h"
#include "c_tf_gamestats.h"
#include "gamestringpool.h"
#include "tf_item_inventory.h"
#include "econ_item_system.h"
#include "iachievementmgr.h"
#include "store/store_panel.h"
#include "character_info_panel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
ConVar tf_explanations_charinfo_armory_panel( "tf_explanations_charinfo_armory_panel", "0", FCVAR_ARCHIVE, "Whether the user has seen explanations for this panel." );
const char *g_szArmoryFilterStrings[ARMFILT_TOTAL] =
{
"#ArmoryFilter_AllItems", // ARMFILT_ALL_ITEMS.
"#ArmoryFilter_Weapons", // ARMFILT_WEAPONS,
"#ArmoryFilter_Headgear", // ARMFILT_HEADGEAR,
"#ArmoryFilter_MiscItems", // ARMFILT_MISCITEMS,
"#ArmoryFilter_ActionItems", // ARMFILT_ACTIONITEMS,
"#ArmoryFilter_CraftItems", // ARMFILT_CRAFTITEMS,
"#ArmoryFilter_Tools", // ARMFILT_TOOLS,
"#ArmoryFilter_AllClass", // ARMFILT_CLASS_ALL,
"#ArmoryFilter_Scout", // ARMFILT_CLASS_SCOUT,
"#ArmoryFilter_Sniper", // ARMFILT_CLASS_SNIPER,
"#ArmoryFilter_Soldier", // ARMFILT_CLASS_SOLDIER,
"#ArmoryFilter_Demoman", // ARMFILT_CLASS_DEMOMAN,
"#ArmoryFilter_Medic", // ARMFILT_CLASS_MEDIC,
"#ArmoryFilter_Heavy", // ARMFILT_CLASS_HEAVY,
"#ArmoryFilter_Pyro", // ARMFILT_CLASS_PYRO,
"#ArmoryFilter_Spy", // ARMFILT_CLASS_SPY,
"#ArmoryFilter_Engineer", // ARMFILT_CLASS_ENGINEER,
"#ArmoryFilter_Donationitems", // ARMFILT_DONATIONITEMS,
"", // ARMFILT_NUM_IN_DROPDOWN
"Not Used", // ARMFILT_CUSTOM
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CArmoryPanel::CArmoryPanel(Panel *parent, const char *panelName) : vgui::EditablePanel( parent, panelName )
{
m_pSelectedItemModelPanel = new CItemModelPanel( this, "SelectedItemModelPanel" );
m_pSelectedItemImageModelPanel = new CItemModelPanel( this, "SelectedItemImageModelPanel" );
m_pThumbnailModelPanelKVs = NULL;
m_bReapplyItemKVs = false;
m_CurrentFilter = ARMFILT_ALL_ITEMS;
m_OldFilter = ARMFILT_ALL_ITEMS;
m_iFilterPage = 0;
m_pNextPageButton = NULL;
m_pPrevPageButton = NULL;
m_pViewSetButton = NULL;
m_pStoreButton = NULL;
m_bAllowGotoStore = false;
m_pDataPanel = new vgui::EditablePanel( this, "DataPanel" );
m_pDataTextRichText = NULL;
m_pMouseOverItemPanel = new CItemModelPanel( this, "mouseoveritempanel" );
m_pMouseOverTooltip = new CItemModelPanelToolTip( this );
m_pMouseOverTooltip->SetupPanels( this, m_pMouseOverItemPanel );
m_pMouseOverTooltip->SetPositioningStrategy( IPTTP_BOTTOM_SIDE );
m_pFilterComboBox = new vgui::ComboBox( this, "FilterComboBox", ARMFILT_NUM_IN_DROPDOWN, false );
m_pFilterComboBox->AddActionSignalTarget( this );
REGISTER_COLOR_AS_OVERRIDABLE( m_colThumbnailBG, "thumbnail_bgcolor" );
REGISTER_COLOR_AS_OVERRIDABLE( m_colThumbnailBGMouseover, "thumbnail_bgcolor_mouseover" );
REGISTER_COLOR_AS_OVERRIDABLE( m_colThumbnailBGSelected, "thumbnail_bgcolor_selected" );
m_bEventLogging = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CArmoryPanel::~CArmoryPanel()
{
if ( m_pThumbnailModelPanelKVs )
{
m_pThumbnailModelPanelKVs->deleteThis();
m_pThumbnailModelPanelKVs = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/CharInfoArmorySubPanel.res" );
m_bReapplyItemKVs = true;
m_pMouseOverItemPanel->SetBorder( pScheme->GetBorder("LoadoutItemPopupBorder") );
m_pDataTextRichText = dynamic_cast<CEconItemDetailsRichText*>( m_pDataPanel->FindChildByName( "Data_TextRichText" ) );
m_pNextPageButton = dynamic_cast<CExButton*>( FindChildByName("NextPageButton") );
m_pPrevPageButton = dynamic_cast<CExButton*>( FindChildByName("PrevPageButton") );
m_pViewSetButton = dynamic_cast<CExButton*>( FindChildByName("ViewSetButton") );
m_pStoreButton = dynamic_cast<CExButton*>( FindChildByName("StoreButton") );
m_pDataTextRichText->SetURLClickedHandler( this );
m_colSetName = GetSchemeColor( "ItemSetName", Color(255, 255, 255, 255), pScheme );
SetupComboBox( NULL );
UpdateSelectedItem();
m_pFilterComboBox->SetBorder( NULL );
m_pMouseOverItemPanel->SetVisible( false );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::SetupComboBox( const char *pszCustomAddition )
{
m_pFilterComboBox->RemoveAll();
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
vgui::HFont hFont = pScheme->GetFont( "HudFontSmallestBold", true );
m_pFilterComboBox->SetFont( hFont );
KeyValues *pKeyValues = new KeyValues( "data" );
for ( int i = 0; i < ARMFILT_NUM_IN_DROPDOWN; i++ )
{
pKeyValues->SetInt( "setfilter", i );
m_pFilterComboBox->AddItem( g_szArmoryFilterStrings[i], pKeyValues );
}
if ( pszCustomAddition )
{
pKeyValues->SetInt( "setfilter", ARMFILT_CUSTOM );
m_pFilterComboBox->AddItem( g_pVGuiLocalize->Find( pszCustomAddition ), pKeyValues );
// Start with the custom filter selected
m_pFilterComboBox->SetNumberOfEditLines( ARMFILT_NUM_IN_DROPDOWN + 1 );
m_pFilterComboBox->ActivateItemByRow( ARMFILT_NUM_IN_DROPDOWN );
}
else
{
m_pFilterComboBox->SetNumberOfEditLines( ARMFILT_NUM_IN_DROPDOWN );
m_pFilterComboBox->ActivateItemByRow( 0 );
}
pKeyValues->deleteThis();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
KeyValues *pItemKV = inResourceData->FindKey( "thumbnail_modelpanels_kv" );
if ( pItemKV )
{
if ( m_pThumbnailModelPanelKVs )
{
m_pThumbnailModelPanelKVs->deleteThis();
}
m_pThumbnailModelPanelKVs = new KeyValues("thumbnail_modelpanels_kv");
pItemKV->CopySubkeys( m_pThumbnailModelPanelKVs );
}
}
// C_CTF_GameStats.Event_Item( IE_ARMORY_EXITED );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::OnShowPanel( void )
{
InvalidateLayout( true, true );
m_pMouseOverItemPanel->SetVisible( false );
UpdateSelectedItem();
// If this is the first time we've opened the armory, start the armory explanations
if ( !tf_explanations_charinfo_armory_panel.GetBool() && ShouldShowExplanations() )
{
m_flStartExplanationsAt = engine->Time() + 0.5;
}
SetVisible( true );
if ( !m_bEventLogging )
{
C_CTF_GameStats.Event_Catalog( IE_ARMORY_ENTERED );
m_bEventLogging = true;
}
}
//-----------------------------------------------------------------------------
// Purpose: Select the given item and jump to the appropriate page
//-----------------------------------------------------------------------------
void CArmoryPanel::JumpToItem( int iItemDef, armory_filters_t nFilter )
{
// Setup filter and select iItemDef
SetFilterTo( iItemDef, nFilter );
// If we have an item def, find out what page it's on and move to it
if ( iItemDef > 0 )
{
const CEconItemDefinition *pDef = ItemSystem()->GetStaticDataForItemByDefIndex( iItemDef );
if ( pDef )
{
// Attempt to get item def from armory remap parameter
int iArmoryRemap = pDef->GetArmoryRemap();
if ( iArmoryRemap > 0 )
{
iItemDef = iArmoryRemap;
SetSelectedItem( iItemDef );
}
// If the item specified is a stock item, find the upgradeable version of it instead
else if ( pDef->GetQuality() == AE_NORMAL )
{
// Prepend the upgradeable string
char szTmpName[256];
Q_snprintf( szTmpName, sizeof(szTmpName), "Upgradeable %s", pDef->GetDefinitionName() );
pDef = ItemSystem()->GetStaticDataForItemByName( szTmpName );
if ( pDef )
{
iItemDef = pDef->GetDefinitionIndex();
}
}
}
// Find and select the page iItemDef is on
FOR_EACH_VEC( m_FilteredItemList, i )
{
if ( m_FilteredItemList[i] == (item_definition_index_t)iItemDef )
{
int iThumbnailsPerPage = (m_iThumbnailRows * m_iThumbnailColumns);
m_iFilterPage = floor( (float)i / (float)iThumbnailsPerPage );
break;
}
}
}
else
{
// Default behavior - select first item on first page
m_iFilterPage = 0;
SetSelectedItem( m_FilteredItemList[0] );
}
UpdateItemList();
UpdateSelectedItem();
m_pMouseOverItemPanel->SetVisible( false );
}
//-----------------------------------------------------------------------------
// Purpose: Show the armory with one of the default filters set
//-----------------------------------------------------------------------------
void CArmoryPanel::ShowPanel( int iItemDef, armory_filters_t nFilter )
{
JumpToItem( iItemDef, nFilter );
OnShowPanel();
m_pFilterComboBox->ActivateItemByRow( 0 );
}
//-----------------------------------------------------------------------------
// Purpose: Show the armory with a custom list of item definitions, and a custom filter string
//-----------------------------------------------------------------------------
void CArmoryPanel::ShowPanel( const char *pszFilterString, CUtlVector<item_definition_index_t> *vecItems )
{
m_CustomFilteredList = *vecItems;
SetupComboBox( pszFilterString );
ShowPanel( 0, ARMFILT_CUSTOM );
// Move to the custom entry
m_pFilterComboBox->ActivateItemByRow( ARMFILT_NUM_IN_DROPDOWN );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::OnClosing()
{
if ( m_bEventLogging )
{
C_CTF_GameStats.Event_Catalog( IE_ARMORY_EXITED );
m_bEventLogging = false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::OnCommand( const char *command )
{
if ( !Q_strnicmp( command, "prevpage", 8 ) )
{
if ( m_iFilterPage > 0 )
{
m_iFilterPage--;
UpdateItemList();
UpdateSelectedItem();
}
return;
}
else if ( !Q_strnicmp( command, "nextpage", 8 ) )
{
int nMaxPages = MAX( 1, ceil(m_FilteredItemList.Count() / (float)(m_iThumbnailRows * m_iThumbnailColumns)) );
if ( m_iFilterPage < (nMaxPages-1) )
{
m_iFilterPage++;
UpdateItemList();
UpdateSelectedItem();
}
return;
}
else if ( !Q_strnicmp( command, "back", 4 ) )
{
PostMessage( GetParent(), new KeyValues("ArmoryClosed") );
return;
}
else if ( !Q_stricmp( command, "reloadscheme" ) )
{
InvalidateLayout( false, true );
SetTall( YRES(400) );
SetVisible( true );
}
else if ( !Q_stricmp( command, "openstore" ) )
{
// Only available in the loadout->catalog path. So we close down the character info, and move to the store.
// Bit of a hack.
EconUI()->CloseEconUI();
int iItemDef = m_SelectedItem.IsValid() ? m_SelectedItem.GetItemDefIndex() : 0;
EconUI()->OpenStorePanel( iItemDef, false );
return;
}
else if ( !Q_stricmp( command, "wiki" ) )
{
if ( steamapicontext && steamapicontext->SteamFriends() )
{
if ( IsVisible() && m_SelectedItem.IsValid() )
{
// Determine which language we should use
char uilanguage[ 64 ];
uilanguage[0] = 0;
engine->GetUILanguage( uilanguage, sizeof( uilanguage ) );
ELanguage iLang = PchLanguageToELanguage( uilanguage );
char szURL[512];
Q_snprintf( szURL, sizeof(szURL), "http://wiki.teamfortress.com/scripts/itemredirect.php?id=%d&lang=%s", m_SelectedItem.GetItemDefIndex(), GetLanguageICUName( iLang ) );
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( szURL );
C_CTF_GameStats.Event_Catalog( IE_ARMORY_BROWSE_WIKI, NULL, &m_SelectedItem );
}
}
}
else if ( !Q_stricmp( command, "viewset" ) )
{
if ( m_SelectedItem.IsValid() )
{
const CEconItemSetDefinition *pItemSet = m_SelectedItem.GetStaticData()->GetItemSetDefinition();
if ( pItemSet )
{
m_CustomFilteredList.Purge();
FOR_EACH_VEC( pItemSet->m_iItemDefs, i )
{
m_CustomFilteredList.AddToTail( pItemSet->m_iItemDefs[i] );
}
SetupComboBox( pItemSet->m_pszLocalizedName );
SetFilterTo( m_SelectedItem.GetItemDefIndex(), ARMFILT_CUSTOM );
}
}
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::MoveItem( int iDelta )
{
int iIdx = m_FilteredItemList.Find( m_SelectedItem.GetItemDefIndex() );
m_SelectedItem.Invalidate();
if ( iIdx != m_FilteredItemList.InvalidIndex() )
{
iIdx += iDelta;
if ( iIdx >= m_FilteredItemList.Count() )
{
iIdx = 0;
}
else if ( iIdx < 0 )
{
iIdx = m_FilteredItemList.Count() - 1;
}
if ( iIdx < m_FilteredItemList.Count() )
{
const CEconItemDefinition *pDef = ItemSystem()->GetStaticDataForItemByDefIndex( m_FilteredItemList[iIdx] );
if ( pDef )
{
SetSelectedItem( pDef->GetDefinitionIndex() );
}
}
}
UpdateSelectedItem();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::PerformLayout( void )
{
if ( m_bReapplyItemKVs )
{
m_bReapplyItemKVs = false;
if ( m_pThumbnailModelPanelKVs )
{
FOR_EACH_VEC( m_pThumbnailModelPanels, i )
{
m_pThumbnailModelPanels[i]->ApplySettings( m_pThumbnailModelPanelKVs );
SetBorderForItem( m_pThumbnailModelPanels[i], false );
m_pThumbnailModelPanels[i]->InvalidateLayout();
}
}
}
BaseClass::PerformLayout();
if ( m_pThumbnailModelPanels.Count() > 0 && m_iThumbnailColumns )
{
int iThumbnailModelWide = m_pThumbnailModelPanels[0]->GetWide();
int iThumbnailModelTall = m_pThumbnailModelPanels[0]->GetTall();
FOR_EACH_VEC( m_pThumbnailModelPanels, i )
{
if ( m_pThumbnailModelPanels[i]->HasItem() )
{
m_pThumbnailModelPanels[i]->SetVisible( true );
}
int iXPos = ( i % m_iThumbnailColumns );
int iYPos = ( i / m_iThumbnailColumns );
int iX = m_iThumbnailX + (m_iThumbnailDeltaX * iXPos) + (iThumbnailModelWide * iXPos);
int iY = m_iThumbnailY + (m_iThumbnailDeltaY * iYPos) + (iThumbnailModelTall * iYPos);
m_pThumbnailModelPanels[i]->SetPos( iX, iY );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::SetFilterTo( int iItemDef, armory_filters_t nFilter )
{
m_FilteredItemList.Purge();
m_OldFilter = m_CurrentFilter;
m_CurrentFilter = nFilter;
m_iFilterPage = 0;
if ( nFilter == ARMFILT_CUSTOM )
{
m_FilteredItemList = m_CustomFilteredList;
}
else
{
// First, build a list of all the items that match the filter
const CEconItemSchema::SortedItemDefinitionMap_t& mapItemDefs = ItemSystem()->GetItemSchema()->GetSortedItemDefinitionMap();
FOR_EACH_MAP( mapItemDefs, i )
{
const CTFItemDefinition *pDef = dynamic_cast<const CTFItemDefinition *>( mapItemDefs[i] );
// Never show:
// - Hidden items
// - Items that don't have fixed qualities
// - Normal quality items
// - Items that haven't asked to be shown
if ( pDef->IsHidden() || pDef->GetQuality() == k_unItemQuality_Any || pDef->GetQuality() == AE_NORMAL || !pDef->ShouldShowInArmory() )
continue;
#ifdef DEBUG
// In Debug, make sure that every item shows up in a filter other than the All Items list
bool bFoundMatchingFilter = false;
for ( int iFilter = ARMFILT_WEAPONS; iFilter < ARMFILT_NUM_IN_DROPDOWN; iFilter++ )
{
if ( DefPassesFilter(pDef,(armory_filters_t)iFilter) )
{
bFoundMatchingFilter = true;
break;
}
}
Assert( bFoundMatchingFilter );
#endif
if ( DefPassesFilter( pDef, m_CurrentFilter ) )
{
m_FilteredItemList.AddToTail( pDef->GetDefinitionIndex() );
if ( iItemDef == pDef->GetDefinitionIndex() )
{
SetSelectedItem( pDef->GetDefinitionIndex() );
}
}
}
}
// Make sure our current item is in the list
if ( m_SelectedItem.IsValid() )
{
if ( m_FilteredItemList.Find( m_SelectedItem.GetItemDefIndex() ) == m_FilteredItemList.InvalidIndex() )
{
m_SelectedItem.Invalidate();
}
}
UpdateItemList();
if ( m_CurrentFilter != m_OldFilter )
{
C_CTF_GameStats.Event_Catalog( IE_ARMORY_CHANGE_FILTER, g_szArmoryFilterStrings[m_CurrentFilter] );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CArmoryPanel::DefPassesFilter( const CTFItemDefinition *pDef, armory_filters_t iFilter )
{
bool bInList = false;
switch (iFilter)
{
case ARMFILT_ALL_ITEMS:
{
bInList = true;
break;
}
case ARMFILT_WEAPONS:
{
int iSlot = pDef->GetDefaultLoadoutSlot();
bInList = ( iSlot == LOADOUT_POSITION_PRIMARY || iSlot == LOADOUT_POSITION_SECONDARY || iSlot == LOADOUT_POSITION_MELEE );
break;
}
case ARMFILT_HEADGEAR:
{
bInList = (pDef->GetDefaultLoadoutSlot() == LOADOUT_POSITION_HEAD);
break;
}
case ARMFILT_MISCITEMS:
{
bInList = (pDef->GetDefaultLoadoutSlot() == LOADOUT_POSITION_MISC);
break;
}
case ARMFILT_ACTIONITEMS:
{
bInList = (pDef->GetDefaultLoadoutSlot() == LOADOUT_POSITION_ACTION);
break;
}
case ARMFILT_CRAFTITEMS:
{
bInList = pDef->GetItemClass() && ( !V_strcmp( pDef->GetItemClass(), "craft_item" ) || !V_strcmp( pDef->GetItemClass(), "class_token" ) || !V_strcmp( pDef->GetItemClass(), "slot_token" ) );
break;
}
case ARMFILT_TOOLS:
{
// For now, put the supply crates into the tool list, since it's the only item that shows up in no other lists
bInList = pDef->GetItemClass() && ( !V_strcmp( pDef->GetItemClass(), "tool" ) || !V_strcmp( pDef->GetItemClass(), "supply_crate" ) );
break;
}
case ARMFILT_CLASS_ALL:
{
bInList = pDef->CanBeUsedByAllClasses();
break;
}
case ARMFILT_CLASS_SCOUT:
case ARMFILT_CLASS_SNIPER:
case ARMFILT_CLASS_SOLDIER:
case ARMFILT_CLASS_DEMOMAN:
case ARMFILT_CLASS_MEDIC:
case ARMFILT_CLASS_HEAVY:
case ARMFILT_CLASS_PYRO:
case ARMFILT_CLASS_SPY:
case ARMFILT_CLASS_ENGINEER:
{
// Don't show class/slot usage for class/slot tokens
if ( pDef->GetItemClass() && !V_strcmp( pDef->GetItemClass(), "class_token" ) )
break;
bInList = ( !pDef->CanBeUsedByAllClasses() && pDef->CanBeUsedByClass( iFilter - ARMFILT_CLASS_SCOUT + 1 ) );
break;
}
case ARMFILT_DONATIONITEMS:
{
// Don't show class/slot usage for class/slot tokens
bInList = pDef->GetItemClass() && !V_strcmp( pDef->GetItemClass(), "map_token" );
break;
}
}
return bInList;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::UpdateItemList( void )
{
int iMaxThumbnails = (m_iThumbnailRows * m_iThumbnailColumns);
int iNumThumbnails = MIN( m_FilteredItemList.Count(), iMaxThumbnails );
if ( m_pThumbnailModelPanels.Count() < iNumThumbnails )
{
for ( int i = m_pThumbnailModelPanels.Count(); i < iNumThumbnails; i++ )
{
CItemModelPanel *pPanel = vgui::SETUP_PANEL( new CItemModelPanel( this, VarArgs("thumbnailmodelpanel%d", i) ) );
pPanel->SetActAsButton( true, true );
pPanel->ApplySettings( m_pThumbnailModelPanelKVs );
SetBorderForItem( pPanel, false );
m_pThumbnailModelPanels.AddToTail( pPanel );
pPanel->SetTooltip( m_pMouseOverTooltip, "" );
}
}
else if ( m_pThumbnailModelPanels.Count() > iMaxThumbnails )
{
FOR_EACH_VEC_BACK( m_pThumbnailModelPanels, i )
{
if ( i < iMaxThumbnails )
break;
m_pThumbnailModelPanels[i]->MarkForDeletion();
m_pThumbnailModelPanels.Remove( i );
}
}
int iStartPos = (m_iFilterPage * iMaxThumbnails);
CEconItemView *pItemData = new CEconItemView();
FOR_EACH_VEC( m_pThumbnailModelPanels, i )
{
int iItemPos = iStartPos + i;
if ( iItemPos >= m_FilteredItemList.Count() )
{
m_pThumbnailModelPanels[i]->SetItem( NULL );
m_pThumbnailModelPanels[i]->SetVisible( false );
continue;
}
pItemData->Init( m_FilteredItemList[iItemPos], AE_USE_SCRIPT_VALUE, AE_USE_SCRIPT_VALUE, true );
m_pThumbnailModelPanels[i]->SetItem( pItemData );
m_pThumbnailModelPanels[i]->SetVisible( true );
}
delete pItemData;
char szTmp[16];
int nMaxPages = MAX( 1, ceil(m_FilteredItemList.Count() / (float)(m_iThumbnailRows * m_iThumbnailColumns)) );
Q_snprintf(szTmp, 16, "%d/%d", m_iFilterPage+1, nMaxPages );
SetDialogVariable( "thumbnailpage", szTmp );
bool bNextEnabled = m_iFilterPage < (nMaxPages-1);
m_pNextPageButton->SetEnabled( bNextEnabled );
m_pPrevPageButton->SetEnabled( m_iFilterPage > 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::UpdateSelectedItem( void )
{
if ( !m_SelectedItem.IsValid() )
{
if ( m_FilteredItemList.Count() )
{
const CEconItemDefinition *pDef = ItemSystem()->GetStaticDataForItemByDefIndex( m_FilteredItemList[0] );
if ( pDef )
{
SetSelectedItem( pDef->GetDefinitionIndex() );
}
}
}
if ( m_pSelectedItemModelPanel )
{
m_pSelectedItemModelPanel->SetItem( &m_SelectedItem );
m_pSelectedItemModelPanel->InvalidateLayout( true );
int iYDelta = YRES(10);
// Resize & position the atribute background image
int iItemX, iItemY, iItemW, iItemH;
m_pSelectedItemModelPanel->GetBounds( iItemX, iItemY, iItemW, iItemH );
// Never shrink the attribute background below a certain size
int iNewPaperH = MAX( iItemH + (iYDelta*2), YRES(100) );
int iNewPaperY = iItemY - iYDelta;
int iNewY = iNewPaperY + iNewPaperH;
// Reposition the data panel now that we know how big the item is
int iX,iY;
m_pDataTextRichText->GetPos( iX, iY );
int iDataPanelX, iDataPanelY;
m_pDataPanel->GetPos( iDataPanelX, iDataPanelY );
int iRichTextYPosInDataPanel = iNewY - iDataPanelY;
m_pDataTextRichText->SetBounds( iX, iRichTextYPosInDataPanel, m_pDataTextRichText->GetWide(), m_pDataPanel->GetTall() - iRichTextYPosInDataPanel );
}
if ( m_pSelectedItemImageModelPanel )
{
m_pSelectedItemImageModelPanel->SetItem( &m_SelectedItem );
}
FOR_EACH_VEC( m_pThumbnailModelPanels, i )
{
if ( !m_pThumbnailModelPanels[i]->IsVisible() || !m_pThumbnailModelPanels[i]->HasItem() )
continue;
bool bSelected = (m_SelectedItem.GetItemDefIndex() == m_pThumbnailModelPanels[i]->GetItem()->GetItemDefIndex() );
if ( bSelected != m_pThumbnailModelPanels[i]->IsSelected() )
{
m_pThumbnailModelPanels[i]->SetSelected( bSelected );
SetBorderForItem( m_pThumbnailModelPanels[i], false );
}
}
UpdateDataBlock();
if ( m_pViewSetButton )
{
m_pViewSetButton->SetVisible( false );
if ( m_SelectedItem.IsValid() )
{
if ( m_SelectedItem.GetStaticData()->GetItemSetDefinition() )
{
m_pViewSetButton->SetVisible( true );
}
}
}
if ( m_pStoreButton )
{
bool bShowStoreButton = m_bAllowGotoStore && EconUI()->GetStorePanel() && EconUI()->GetStorePanel()->GetPriceSheet() && EconUI()->GetStorePanel()->GetPriceSheet()->GetEntry( m_SelectedItem.GetItemDefIndex() );
m_pStoreButton->SetVisible( bShowStoreButton );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::UpdateDataBlock( void )
{
if ( !CalculateDataText() )
{
m_pDataPanel->SetVisible( false );
return;
}
m_pDataPanel->SetVisible( true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CArmoryPanel::CalculateDataText( void )
{
if ( !m_SelectedItem.IsValid() )
return false;
CTFItemDefinition *pDef = ItemSystem()->GetStaticDataForItemByDefIndex( m_SelectedItem.GetItemDefIndex() );
if ( !pDef )
return false;
m_pDataTextRichText->UpdateDetailsForItem( pDef );
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::OnItemPanelEntered( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( pItemPanel && IsVisible() )
{
CEconItemView *pItem = pItemPanel->GetItem();
SetBorderForItem( pItemPanel, pItem != NULL );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::OnItemPanelExited( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( pItemPanel && IsVisible() )
{
SetBorderForItem( pItemPanel, false );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::OnItemPanelMouseReleased( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( pItemPanel && IsVisible() && pItemPanel->HasItem() && !pItemPanel->IsSelected() )
{
SetSelectedItem( pItemPanel->GetItem() );
// Hide the mouseover panel now, so it doesn't obscure the rich text info
m_pMouseOverItemPanel->SetVisible( false );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::SetSelectedItem( CEconItemView* newItem )
{
m_PreviousItem = m_SelectedItem;
m_SelectedItem = *newItem;
m_SelectedItem.SetClientItemFlags( kEconItemFlagClient_Preview );
UpdateSelectedItem();
if ( m_bEventLogging && m_SelectedItem.IsValid() && m_SelectedItem != m_PreviousItem )
{
C_CTF_GameStats.Event_Catalog( IE_ARMORY_SELECT_ITEM, g_szArmoryFilterStrings[m_CurrentFilter], &m_SelectedItem );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::SetSelectedItem( int newIndex )
{
m_PreviousItem = m_SelectedItem;
m_SelectedItem.Init( newIndex, AE_USE_SCRIPT_VALUE, AE_USE_SCRIPT_VALUE, true );
m_SelectedItem.SetClientItemFlags( kEconItemFlagClient_Preview );
if ( m_bEventLogging && m_SelectedItem.IsValid() && m_SelectedItem != m_PreviousItem )
{
C_CTF_GameStats.Event_Catalog( IE_ARMORY_SELECT_ITEM, g_szArmoryFilterStrings[m_CurrentFilter], &m_SelectedItem );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::SetBorderForItem( CItemModelPanel *pItemPanel, bool bMouseOver )
{
if ( !pItemPanel )
return;
// Store panels use backgrounds instead of borders
pItemPanel->SetBorder( NULL );
pItemPanel->SetPaintBackgroundEnabled( true );
if ( pItemPanel->IsSelected() )
{
pItemPanel->SetBgColor( m_colThumbnailBGSelected );
}
else if ( bMouseOver )
{
pItemPanel->SetBgColor( m_colThumbnailBGMouseover );
}
else
{
pItemPanel->SetBgColor( m_colThumbnailBG );
}
}
//-----------------------------------------------------------------------------
// Purpose: Called when text changes in combo box
//-----------------------------------------------------------------------------
void CArmoryPanel::OnTextChanged( KeyValues *data )
{
if ( !m_pFilterComboBox )
return;
Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
vgui::ComboBox *pComboBox = dynamic_cast<vgui::ComboBox *>( pPanel );
if ( pComboBox == m_pFilterComboBox )
{
// the class selection combo box changed, update class details
KeyValues *pUserData = m_pFilterComboBox->GetActiveItemUserData();
if ( !pUserData )
return;
armory_filters_t nFilter = (armory_filters_t)pUserData->GetInt( "setfilter", -1 );
if ( nFilter != armory_filters_t(-1) )
{
SetFilterTo( 0, nFilter );
UpdateSelectedItem();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CArmoryPanel::OnItemLinkClicked( KeyValues *pParams )
{
const char *pURL = pParams->GetString( "url" );
int iItemDef = atoi( pURL + 7 );
JumpToItem( iItemDef, ARMFILT_ALL_ITEMS );
m_pFilterComboBox->ActivateItemByRow( 0 );
}
@@ -0,0 +1,151 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CHARINFO_ARMORY_SUBPANEL_H
#define CHARINFO_ARMORY_SUBPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <game/client/iviewport.h>
#include "vgui_controls/PropertyPage.h"
#include <vgui_controls/Button.h>
#include <vgui_controls/ComboBox.h>
#include "tf_controls.h"
#include "tf_shareddefs.h"
#include "backpack_panel.h"
#include "class_loadout_panel.h"
enum armory_filters_t
{
// These are listed in the dropdown, for players to select
ARMFILT_ALL_ITEMS,
ARMFILT_WEAPONS,
ARMFILT_HEADGEAR,
ARMFILT_MISCITEMS,
ARMFILT_ACTIONITEMS,
ARMFILT_CRAFTITEMS,
ARMFILT_TOOLS,
ARMFILT_CLASS_ALL,
ARMFILT_CLASS_SCOUT,
ARMFILT_CLASS_SNIPER,
ARMFILT_CLASS_SOLDIER,
ARMFILT_CLASS_DEMOMAN,
ARMFILT_CLASS_MEDIC,
ARMFILT_CLASS_HEAVY,
ARMFILT_CLASS_PYRO,
ARMFILT_CLASS_SPY,
ARMFILT_CLASS_ENGINEER,
ARMFILT_DONATIONITEMS,
ARMFILT_NUM_IN_DROPDOWN,
ARMFILT_CUSTOM,
ARMFILT_TOTAL,
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CArmoryPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CArmoryPanel, vgui::EditablePanel );
public:
CArmoryPanel(Panel *parent, const char *panelName);
virtual ~CArmoryPanel();
// Show the armory with one of the default filters set
void ShowPanel( int iItemDef, armory_filters_t nFilter = ARMFILT_ALL_ITEMS );
// Show the armory with a custom list of item definitions, and a custom filter string
void ShowPanel( const char *pszFilterString, CUtlVector<item_definition_index_t> *vecItems );
// Select the given item and jump to the appropriate page
void JumpToItem( int iItemDef, armory_filters_t nFilter );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void OnCommand( const char *command );
virtual void PerformLayout( void );
bool ShouldShowExplanations( void ) { return true; }
void UpdateItemList( void );
void UpdateSelectedItem( void );
void AllowGotoStore( void ) { m_bAllowGotoStore = true; }
MESSAGE_FUNC_PTR( OnItemPanelEntered, "ItemPanelEntered", panel );
MESSAGE_FUNC_PTR( OnItemPanelExited, "ItemPanelExited", panel );
MESSAGE_FUNC_PTR( OnItemPanelMouseReleased, "ItemPanelMouseReleased", panel );
MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
MESSAGE_FUNC_PARAMS( OnItemLinkClicked, "URLClicked", pParams );
MESSAGE_FUNC( OnClosing, "Closing" );
private:
void OnShowPanel( void );
void MoveItem( int iDelta );
void UpdateDataBlock( void );
bool CalculateDataText( void );
void SetFilterTo( int iItemDef, armory_filters_t nFilter );
void SetBorderForItem( CItemModelPanel *pItemPanel, bool bMouseOver );
bool DefPassesFilter( const CTFItemDefinition *pDef, armory_filters_t iFilter );
void SetupComboBox( const char *pszCustomAddition );
void SetSelectedItem( CEconItemView* newItem );
void SetSelectedItem( int newIndex );
private:
float m_flStartExplanationsAt;
CEconItemView m_SelectedItem;
CEconItemView m_PreviousItem;
CItemModelPanel *m_pSelectedItemModelPanel;
CItemModelPanel *m_pSelectedItemImageModelPanel;
// Filters
vgui::ComboBox *m_pFilterComboBox;
armory_filters_t m_CurrentFilter;
armory_filters_t m_OldFilter;
int m_iFilterPage;
CExButton *m_pNextPageButton;
CExButton *m_pPrevPageButton;
CUtlVector<item_definition_index_t> m_FilteredItemList;
CUtlVector<item_definition_index_t> m_CustomFilteredList;
// Thumbnails
KeyValues *m_pThumbnailModelPanelKVs;
bool m_bReapplyItemKVs;
CUtlVector<CItemModelPanel*> m_pThumbnailModelPanels;
CItemModelPanel *m_pMouseOverItemPanel;
CItemModelPanelToolTip *m_pMouseOverTooltip;
bool m_bEventLogging; // Handles sending entered/exited stats messages.
// Data display
vgui::EditablePanel *m_pDataPanel;
CEconItemDetailsRichText *m_pDataTextRichText;
CExButton *m_pViewSetButton;
bool m_bAllowGotoStore;
CExButton *m_pStoreButton;
CPanelAnimationVar( int, m_iThumbnailRows, "thumbnails_rows", "1" );
CPanelAnimationVar( int, m_iThumbnailColumns, "thumbnails_columns", "1" );
CPanelAnimationVarAliasType( int, m_iThumbnailX, "thumbnails_x", "0", "proportional_xpos" );
CPanelAnimationVarAliasType( int, m_iThumbnailY, "thumbnails_y", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_iThumbnailDeltaX, "thumbnails_delta_x", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iThumbnailDeltaY, "thumbnails_delta_y", "0", "proportional_int" );
Color m_colThumbnailBG;
Color m_colThumbnailBGMouseover;
Color m_colThumbnailBGSelected;
Color m_colSetName;
};
#endif // CHARINFO_ARMORY_SUBPANEL_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,177 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CHARINFO_LOADOUT_SUBPANEL_H
#define CHARINFO_LOADOUT_SUBPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <game/client/iviewport.h>
#include "vgui_controls/PropertyPage.h"
#include <vgui_controls/Button.h>
#include "tf_controls.h"
#include "tf_shareddefs.h"
#include "item_pickup_panel.h"
#include "backpack_panel.h"
#include "class_loadout_panel.h"
#include "crafting_panel.h"
#include "charinfo_armory_subpanel.h"
#define NUM_CLASSES_IN_LOADOUT_PANEL (TF_LAST_NORMAL_CLASS-1) // We don't allow unlockables for the civilian
class CImageButton : public vgui::Button
{
private:
DECLARE_CLASS_SIMPLE( CImageButton, vgui::Button );
public:
CImageButton( vgui::Panel *parent, const char *panelName );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnSizeChanged( int newWide, int newTall );
void SetActiveImage( const char *imagename );
void SetInactiveImage( const char *imagename );
void SetActiveImage( vgui::IImage *image );
void SetInactiveImage( vgui::IImage *image );
public:
virtual void Paint();
private:
vgui::IImage *m_pActiveImage;
char *m_pszActiveImageName;
vgui::IImage *m_pInactiveImage;
char *m_pszInactiveImageName;
bool m_bScaleImage;
Color m_ActiveDrawColor;
Color m_InactiveDrawColor;
};
enum charinfo_activepanels_t
{
CHAP_LOADOUT,
CHAP_BACKPACK,
CHAP_CRAFTING,
CHAP_ARMORY,
};
enum charinfosubbuttons_t
{
CHSB_BACKPACK,
CHSB_CRAFTING,
CHSB_ARMORY,
CHSB_TRADING,
CHSB_NUM_BUTTONS
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CCharInfoLoadoutSubPanel : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( CCharInfoLoadoutSubPanel, vgui::PropertyPage );
public:
CCharInfoLoadoutSubPanel(Panel *parent);
virtual ~CCharInfoLoadoutSubPanel();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnCommand( const char *command );
virtual void PerformLayout( void );
virtual void OnCursorMoved( int x, int y );
void SetClassIndex( int iClassIndex, bool bOpenClassLoadout );
void SetTeamIndex( int iTeamIndex );
void OpenToBackpack( void ) { OpenSubPanel( CHAP_BACKPACK ); }
void OpenToCrafting( void ) { OpenSubPanel( CHAP_CRAFTING ); }
void OpenToArmory( int iItemDef = 0 ) { m_iArmoryItemDef = iItemDef; OpenSubPanel( CHAP_ARMORY ); }
void OpenSubPanel( charinfo_activepanels_t iPanel );
void UpdateModelPanels( bool bOpenClassLoadout = true );
CClassLoadoutPanel *GetClassLoadoutPanel( void ) { return m_pClassLoadoutPanel; }
CBackpackPanel *GetBackpackPanel( void ) { return m_pBackpackPanel; }
CCraftingPanel *GetCraftingPanel( void ) { return m_pCraftingPanel; }
CArmoryPanel *GetArmoryPanel( void ) { return m_pArmoryPanel; }
void UpdateLabelFromClass( int nClass );
void UpdateLabelFromSubButton( int nButton );
virtual void OnTick( void );
void RecalculateTargetClassLayout( void );
void RecalculateTargetClassLayoutAtPos( int x, int y );
void MoveCharacterSelection( int nDirection );
void OnKeyCodeTyped( vgui::KeyCode code );
void OnKeyCodePressed( vgui::KeyCode code );
bool ShouldShowExplanations( void ) { return (m_iShowingPanel == CHAP_LOADOUT && m_iCurrentClassIndex == TF_CLASS_UNDEFINED); }
charinfo_activepanels_t GetShowingPanel() const { return m_iShowingPanel; }
int GetCurrentClassIndex() const { return m_iCurrentClassIndex; }
MESSAGE_FUNC( OnPageShow, "PageShow" );
MESSAGE_FUNC( OnSelectionStarted, "SelectionStarted" );
MESSAGE_FUNC( OnSelectionEnded, "SelectionEnded" );
MESSAGE_FUNC( OnCancelSelection, "CancelSelection" );
MESSAGE_FUNC( OnOpenCrafting, "OpenCrafting" );
MESSAGE_FUNC( OnCraftingClosed, "CraftingClosed" );
MESSAGE_FUNC( OnArmoryClosed, "ArmoryClosed" );
MESSAGE_FUNC( OnCharInfoClosing, "CharInfoClosing" );
private:
void RequestInventoryRefresh();
CImageButton *m_pClassButtons[NUM_CLASSES_IN_LOADOUT_PANEL+1];
CImageButton *m_pSubButtons[CHSB_NUM_BUTTONS];
CExLabel *m_pButtonLabels[CHSB_NUM_BUTTONS];
int m_iOverSubButton;
int m_iClassLayout[NUM_CLASSES_IN_LOADOUT_PANEL+1][4];
bool m_bClassLayoutDirty;
bool m_bSnapClassLayout;
bool m_bRequestingInventoryRefresh;
int m_iCurrentClassIndex;
int m_iCurrentTeamIndex;
charinfo_activepanels_t m_iShowingPanel;
charinfo_activepanels_t m_iPrevShowingPanel;
CClassLoadoutPanel *m_pClassLoadoutPanel;
CBackpackPanel *m_pBackpackPanel;
CCraftingPanel *m_pCraftingPanel;
CArmoryPanel *m_pArmoryPanel;
vgui::Label *m_pSelectLabel;
vgui::Label *m_pLoadoutChangesLabel;
vgui::Label *m_pNoSteamLabel;
vgui::Label *m_pNoGCLabel;
vgui::Label *m_pClassLabel;
CExLabel *m_pItemsLabel;
int m_iMouseXPos;
int m_iMouseYPos;
int m_iLabelSetToClass;
int m_iClassLabelYPos;
int m_iItemLabelYPos;
Color m_ItemColorNone;
Color m_ItemColor;
float m_flStartExplanationsAt;
int m_iArmoryItemDef;
CPanelAnimationVarAliasType( int, m_iSelectLabelY, "selectlabely_default", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iSelectLabelOnChangesY, "selectlabely_onchanges", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iClassYPos, "class_ypos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iClassXDelta, "class_xdelta", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iClassWideMin, "class_wide_min", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iClassWideMax, "class_wide_max", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iClassTallMin, "class_tall_min", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iClassTallMax, "class_tall_max", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iClassDistanceMin, "class_distance_min", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iClassDistanceMax, "class_distance_max", "0", "proportional_int" );
};
#endif // CHARINFO_LOADOUT_SUBPANEL_H
File diff suppressed because it is too large Load Diff
+157
View File
@@ -0,0 +1,157 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CLASS_LOADOUT_PANEL_H
#define CLASS_LOADOUT_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "base_loadout_panel.h"
#include "tf_playermodelpanel.h"
#include "item_selection_panel.h"
#include <../common/GameUI/cvarslider.h>
#include <vgui/VGUI.h>
#include "vgui_controls/CheckButton.h"
#define NUM_ITEM_PANELS_IN_LOADOUT CLASS_LOADOUT_POSITION_COUNT
class CLoadoutPresetPanel;
class CLoadoutItemOptionsPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CLoadoutItemOptionsPanel, vgui::EditablePanel );
public:
CLoadoutItemOptionsPanel( Panel *parent, const char *pName );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout( void );
virtual void OnCommand( const char *command );
virtual void OnMessage( const KeyValues* pParams, vgui::VPANEL hFromPanel );
void SetItemSlot( loadout_positions_t eItemSlot, int iClassIndex );
loadout_positions_t GetItemSlot() const { return m_eItemSlot; }
void UpdateItemOptionsUI();
private:
void AddControlsParticleEffect( void ) const;
void AddControlsSetStyle( void ) const;
CEconItemView* GetItem( void ) const;
class vgui::PanelListPanel *m_pListPanel;
CCvarSlider *m_pHatParticleSlider;
CExButton *m_pSetStyleButton;
vgui::CheckButton *m_pHatParticleUseHeadButton;
int m_iCurrentClassIndex;
loadout_positions_t m_eItemSlot;
};
//-----------------------------------------------------------------------------
// A loadout screen that handles modifying the loadout of a specific class
//-----------------------------------------------------------------------------
class CClassLoadoutPanel : public CBaseLoadoutPanel
{
DECLARE_CLASS_SIMPLE( CClassLoadoutPanel, CBaseLoadoutPanel );
public:
CClassLoadoutPanel( vgui::Panel *parent );
~CClassLoadoutPanel();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
virtual void PerformLayout( void );
virtual void FireGameEvent( IGameEvent *event );
virtual void AddNewItemPanel( int iPanelIndex ) OVERRIDE;
virtual void UpdateModelPanels( void );
virtual int GetNumItemPanels( void ) { return NUM_ITEM_PANELS_IN_LOADOUT; };
virtual void OnShowPanel( bool bVisible, bool bReturningFromArmory );
virtual void PostShowPanel( bool bVisible );
virtual void OnKeyCodePressed( vgui::KeyCode code ) OVERRIDE;
virtual void OnNavigateTo( const char* panelName ) OVERRIDE;
virtual void OnNavigateFrom( const char* panelName ) OVERRIDE;
void SetClass( int iClass );
void SetTeam( int iTeam );
int GetNumRelevantSlots() const;
CEconItemView *GetItemInSlot( int iSlot );
MESSAGE_FUNC_PTR( OnItemPanelMouseReleased, "ItemPanelMouseReleased", panel );
MESSAGE_FUNC_PARAMS( OnSelectionReturned, "SelectionReturned", data );
MESSAGE_FUNC( OnCancelSelection, "CancelSelection" );
MESSAGE_FUNC( OnClosing, "Closing" );
virtual void OnCommand( const char *command );
virtual void OnMessage( const KeyValues* pParams, vgui::VPANEL hFromPanel );
void SetSelectionPanel( CEquipSlotItemSelectionPanel *pPanel ) { m_pSelectionPanel = pPanel; }
void UpdatePassiveAttributes( void );
bool IsInSelectionPanel() const { return m_pSelectionPanel != NULL; }
CEquipSlotItemSelectionPanel *GetItemSelectionPanel() { return m_pSelectionPanel; }
bool IsEditingTauntSlots() const { return m_bInTauntLoadoutMode; }
enum classloadoutpage_t
{
CHARACTER_LOADOUT_PAGE,
TAUNT_LOADOUT_PAGE
};
void SetLoadoutPage( classloadoutpage_t loadoutPage );
protected:
virtual void SetBorderForItem( CItemModelPanel *pItemPanel, bool bMouseOver );
void AddAttribPassiveText( const class CEconAttributeDescription& AttrDesc, INOUT_Z_CAP(iNumPassiveChars) wchar_t *out_wszPassiveDesc, int iNumPassiveChars );
void RespawnPlayer();
virtual void ApplyKVsToItemPanels( void ) OVERRIDE;
void ClearItemOptionsMenu( void );
void SetOptionsButtonText( int nIndex, const char* pszText );
static bool AnyOptionsAvailableForItem( const CEconItemView *pItem );
int m_iCurrentClassIndex;
int m_iCurrentTeamIndex;
int m_iCurrentSlotIndex;
bool m_bLoadoutHasChanged;
bool m_bInTauntLoadoutMode;
CTFPlayerModelPanel *m_pPlayerModelPanel;
CEquipSlotItemSelectionPanel *m_pSelectionPanel;
vgui::Label *m_pTauntHintLabel;
CExLabel *m_pTauntLabel;
CExLabel *m_pTauntCaratLabel;
CExLabel *m_pPassiveAttribsLabel;
Panel *m_pTopLinePanel;
CExButton *m_pBuildablesButton;
CExImageButton *m_pCharacterLoadoutButton;
CExImageButton *m_pTauntLoadoutButton;
CLoadoutPresetPanel *m_pLoadoutPresetPanel;
CExplanationPopup *m_pPresetsExplanationPopup;
CExplanationPopup *m_pTauntsExplanationPopup;
KeyValues *m_pItemOptionPanelKVs;
CUtlVector< CExButton * > m_vecItemOptionButtons;
CLoadoutItemOptionsPanel *m_pItemOptionPanel;
private:
void UpdatePageButtonColor( CExImageButton *pPageButton, bool bIsActive );
enum PageButtonColors_t
{
LOADED = 0, NOTLOADED,
FG = 0, BG,
DEFAULT = 0, ARMED, DEPRESSED
};
Color m_aDefaultColors[2][2][3]; // [LOADED|NOTLOADED][FG|BG][DEFAULT|ARMED|DEPRESSED]
};
extern CClassLoadoutPanel *g_pClassLoadoutPanel;
#endif // CLASS_LOADOUT_PANEL_H
@@ -0,0 +1,829 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "collection_crafting_panel.h"
#include "cdll_client_int.h"
#include "ienginevgui.h"
#include "econ_item_tools.h"
#include "econ_ui.h"
#include <vgui_controls/AnimationController.h>
#include "clientmode_tf.h"
#include "softline.h"
#include "drawing_panel.h"
#include "tf_item_inventory.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCollectionCraftingPanel::CCollectionCraftingPanel( vgui::Panel *parent, CItemModelPanelToolTip* pTooltip )
: BaseClass( parent, "CollectionCraftingPanel" )
, m_pKVItemPanels( NULL )
, m_pModelPanel( NULL )
, m_bWaitingForGCResponse( false )
, m_bEnvelopeReadyToSend( false )
, m_pMouseOverTooltip( pTooltip )
, m_bShowing( false )
, m_bShowImmediately( false )
{
ListenForGameEvent( "gameui_hidden" );
m_pSelectingItemModelPanel = NULL;
m_pTradeUpContainer = new EditablePanel( this, "TradeUpContainer" );
m_pInspectPanel = new CTFItemInspectionPanel( this, "NewItemPanel" );
m_pCosmeticResultItemModelPanel = new CItemModelPanel( m_pInspectPanel, "CosmeticResultItemModelPanel" );
m_pStampPanel = new ImagePanel( this, "Stamp" );
m_pStampButton = new CExButton( this, "ApplyStampButton", "" );
EditablePanel* pPaperContainer = new EditablePanel( m_pTradeUpContainer, "PaperContainer" );
m_pOKButton = new CExButton( pPaperContainer, "OkButton", "" );
m_pNextItemButton = new CExButton( this, "NextItemButton", "" );
m_pDrawingPanel = new CDrawingPanel( this, "drawingpanel" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCollectionCraftingPanel::~CCollectionCraftingPanel( void )
{
if ( m_hSelectionPanel )
{
m_hSelectionPanel->MarkForDeletion();
}
if ( m_pKVItemPanels )
{
m_pKVItemPanels->deleteThis();
}
}
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::SetItemPanelCount( )
{
// only do this once
if ( m_vecItemContainers.Count() != 0 )
return;
const int nNumItems = GetInputItemCount();
const int nNumOutput = GetOutputItemCount();
EditablePanel* pPaperContainer = dynamic_cast<vgui::EditablePanel*>( m_pTradeUpContainer->FindChildByName( "PaperContainer" ) );
if ( pPaperContainer )
{
m_vecItemContainers.SetCount( nNumItems );
FOR_EACH_VEC( m_vecItemContainers, i )
{
m_vecItemContainers[i] = new EditablePanel( pPaperContainer, "itemcontainer" );
}
m_vecOutputItemContainers.SetCount( nNumOutput );
FOR_EACH_VEC( m_vecOutputItemContainers, i )
{
m_vecOutputItemContainers[i] = new EditablePanel( pPaperContainer, "itemcontainer" );
}
}
}
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::CreateSelectionPanel()
{
m_hSelectionPanel = new CCollectionCraftingSelectionPanel( this );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( GetResFile() );
m_pModelPanel = FindControl< CBaseModelPanel >( "ReturnModel" );
if ( m_pModelPanel )
{
m_pModelPanel->SetLookAtCamera( false );
}
if ( m_pDrawingPanel )
{
m_pDrawingPanel->SetType( DRAWING_PANEL_TYPE_CRAFTING );
}
m_pItemNamePanel = m_pInspectPanel->FindControl< CItemModelPanel >( "ItemName" );
Assert( m_pItemNamePanel );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
KeyValues *pItemKV = inResourceData->FindKey( "ItemContainerKV" );
if ( pItemKV )
{
if ( m_pKVItemPanels )
{
m_pKVItemPanels->deleteThis();
}
m_pKVItemPanels = new KeyValues("ItemContainerKV");
pItemKV->CopySubkeys( m_pKVItemPanels );
}
m_vecImagePanels.Purge();
m_vecItemPanels.Purge();
KeyValues *pBoxTopsKV = inResourceData->FindKey( "BoxTops" );
if ( pBoxTopsKV )
{
m_vecBoxTopNames.Purge();
FOR_EACH_VALUE( pBoxTopsKV, pValue )
{
m_vecBoxTopNames.AddToTail( pValue->GetString() );
}
}
Assert( m_vecBoxTopNames.Count() );
KeyValues *pStampNames = inResourceData->FindKey( "stampimages" );
if ( pStampNames )
{
m_vecStampNames.Purge();
FOR_EACH_VALUE( pStampNames, pValue )
{
m_vecStampNames.AddToTail( pValue->GetString() );
}
}
Assert( m_vecStampNames.Count() );
KeyValues *pResulStrings = inResourceData->FindKey( "resultstring" );
if ( pResulStrings )
{
m_vecResultStrings.Purge();
FOR_EACH_VALUE( pResulStrings, pValue )
{
m_vecResultStrings.AddToTail( pValue->GetString() );
}
}
Assert( m_vecResultStrings.Count() );
KeyValues *pLocalizedPanelNames = inResourceData->FindKey( "localizedpanels" );
if ( pLocalizedPanelNames )
{
m_vecLocalizedPanels.Purge();
FOR_EACH_TRUE_SUBKEY( pLocalizedPanelNames, pValue )
{
m_vecLocalizedPanels.AddToTail( { pValue->GetString( "panelname" ), pValue->GetBool( "show_for_english", false ) } );
}
}
CreateItemPanels();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::PerformLayout()
{
BaseClass::PerformLayout();
if ( m_pModelPanel )
{
m_pModelPanel->SetMDL( "models/player/items/crafting/mannco_crate_tradeup.mdl" );
}
FOR_EACH_VEC( m_vecItemContainers, i )
{
m_vecItemContainers[ i ]->SetPos( m_iButtonsStartX + m_iButtonsStepX * ( i % 5 )
, m_iButtonsStartY + m_iButtonsStepY * ( i / 5 ) );
}
FOR_EACH_VEC( m_vecOutputItemContainers, i )
{
m_vecOutputItemContainers[i]->SetPos( m_iOutputItemStartX + m_iOutputItemStepX * ( i % 5 )
, m_iOutputItemStartY + m_iOutputItemStepY * ( i / 5 ) );
}
if ( steamapicontext && steamapicontext->SteamApps() )
{
char uilanguage[ 64 ];
uilanguage[0] = 0;
engine->GetUILanguage( uilanguage, sizeof( uilanguage ) );
ELanguage language = PchLanguageToELanguage( uilanguage );
FOR_EACH_VEC( m_vecLocalizedPanels, i )
{
bool bShow = language == k_Lang_English && m_vecLocalizedPanels[ i ].m_bShowForEnglish;
Panel* pPanel = m_pTradeUpContainer->FindChildByName( m_vecLocalizedPanels[ i ].m_strPanel, true );
if ( pPanel )
{
pPanel->SetVisible( bShow );
}
}
}
UpdateOKButton();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::CreateItemPanels()
{
SetItemPanelCount();
m_vecImagePanels.SetCount( m_vecItemContainers.Count() );
m_vecItemPanels.SetCount( m_vecItemContainers.Count() );
FOR_EACH_VEC( m_vecItemContainers, i )
{
m_vecItemContainers[ i ]->ApplySettings( m_pKVItemPanels );
m_vecImagePanels[ i ] = m_vecItemContainers[ i ]->FindControl< ImagePanel >( "imagepanel" );
m_vecItemPanels[ i ] = m_vecItemContainers[ i ]->FindControl< CItemModelPanel >( "itempanel" );
m_vecItemPanels[ i ]->SetActAsButton( true, true );
m_vecItemPanels[ i ]->SetTooltip( m_pMouseOverTooltip, "" );
CExButton* pButton = m_vecItemContainers[ i ]->FindControl< CExButton >( "BackgroundButton" );
if ( pButton )
{
pButton->SetCommand( CFmtStr( "select%d", i ) );
pButton->AddActionSignalTarget( this );
}
}
m_vecOutputImagePanels.SetCount( m_vecOutputItemContainers.Count() );
m_vecOutputItemPanels.SetCount( m_vecOutputItemContainers.Count() );
FOR_EACH_VEC( m_vecOutputItemContainers, i )
{
m_vecOutputItemContainers[i]->ApplySettings( m_pKVItemPanels );
m_vecOutputImagePanels[i] = m_vecOutputItemContainers[i]->FindControl< ImagePanel >( "imagepanel" );
m_vecOutputItemPanels[i] = m_vecOutputItemContainers[i]->FindControl< CItemModelPanel >( "itempanel" );
m_vecOutputItemPanels[i]->SetTooltip( m_pMouseOverTooltip, "" );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "reloadscheme" ) )
{
InvalidateLayout( false, true );
return;
}
if ( FStrEq( "doneselectingitems", command ) )
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_LetterStart" );
m_bEnvelopeReadyToSend = false;
if ( m_vecStampNames.Count() )
{
m_pStampPanel->SetImage( m_vecStampNames[ RandomInt( 0, m_vecStampNames.Count() - 1 ) ] );
}
return;
}
else if ( FStrEq( "cancel", command ) )
{
SetVisible( false );
return;
}
else if ( Q_strnicmp( "select", command, 6 ) == 0 )
{
SelectPanel( atoi( command + 6 ) );
return;
}
else if ( FStrEq( "envelopesend", command ) )
{
GCSDK::CProtoBufMsg<CMsgCraftCollectionUpgrade> msg( k_EMsgGCCraftCollectionUpgrade );
// Construct message
FOR_EACH_VEC( m_vecItemPanels, i )
{
if ( m_vecItemPanels[ i ]->GetItem() == NULL )
return;
msg.Body().add_item_id( m_vecItemPanels[ i ]->GetItem()->GetItemID() );
}
// Send if off
GCClientSystem()->BSendMessage( msg );
m_bWaitingForGCResponse = true;
m_nFoundItemID.Purge();
m_timerResponse.Start( 5.f );
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_LetterSend" );
return;
}
else if ( FStrEq( "placestamp", command ) )
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_PlaceStamp" );
return;
}
else if( Q_strnicmp( "playcratesequence", command, 17 ) == 0 )
{
m_pModelPanel->SetSequence( atoi( command + 17 ), true );
return;
}
else if( FStrEq( "itemget", command ) )
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_ItemRecieved" );
wchar_t *pszLocalized = NULL;
//
if ( m_eEconItemOrigin == kEconItemOrigin_FoundInCrate )
{
pszLocalized = g_pVGuiLocalize->Find( "#NewItemMethod_FoundInCrate" );
}
else if ( m_vecResultStrings.Count() )
{
pszLocalized = g_pVGuiLocalize->Find( m_vecResultStrings[ RandomInt( 0, m_vecResultStrings.Count() - 1 ) ] );
}
m_pInspectPanel->SetDialogVariable( "resultstring", pszLocalized );
return;
}
else if( Q_strnicmp( "playsound", command, 9 ) == 0 )
{
vgui::surface()->PlaySound( command + 10 );
return;
}
else if( FStrEq( "startexplanation1", command ) )
{
CExplanationPopup *pPopup = dynamic_cast<CExplanationPopup*>( FindChildByName("StartExplanation") );
if ( pPopup )
{
pPopup->Popup();
}
return;
}
else if( FStrEq( "startexplanation2", command ) )
{
CExplanationPopup *pPopup = dynamic_cast<CExplanationPopup*>( FindChildByName("SigningExplanation") );
if ( pPopup )
{
pPopup->Popup();
}
return;
}
else if ( FStrEq( "nextitem", command ) )
{
if ( m_nFoundItemID.Count() > 1 )
{
// Remove head, reset timer to drop next item
m_nFoundItemID.Remove( 0 );
m_timerResponse.Start( 5.f );
m_bShowImmediately = true;
}
}
else if( FStrEq( "reload", command ) )
{
g_pVGuiLocalize->ReloadLocalizationFiles();
InvalidateLayout( false, true );
SetVisible( true );
return;
}
BaseClass::OnCommand( command );
}
void CCollectionCraftingPanel::SelectPanel( int nPanel )
{
m_pSelectingItemModelPanel = m_vecItemPanels[ nPanel ];
CCopyableUtlVector< const CEconItemView* > vecCurrentItems;
FOR_EACH_VEC( m_vecItemPanels, i )
{
if ( m_vecItemPanels[ i ]->GetItem() )
{
vecCurrentItems.AddToTail( m_vecItemPanels[ i ]->GetItem() );
}
}
if ( !m_hSelectionPanel )
{
CreateSelectionPanel();
m_hSelectionPanel->SetAutoDelete( false );
}
if ( m_hSelectionPanel )
{
// Clicked on an item in the crafting area. Open up the selection panel.
m_hSelectionPanel->SetCorrespondingItems( vecCurrentItems );
m_hSelectionPanel->ShowDuplicateCounts( true );
m_hSelectionPanel->ShowPanel( 0, true );
m_hSelectionPanel->SetCaller( this );
m_hSelectionPanel->SetZPos( GetZPos() + 1 );
}
}
void CCollectionCraftingPanel::FireGameEvent( IGameEvent *event )
{
if ( FStrEq( event->GetName(), "gameui_hidden" ) )
{
SetVisible( false );
return;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::OnItemPanelMousePressed( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( pItemPanel && IsVisible() && !pItemPanel->IsGreyedOut() )
{
auto idx = m_vecItemPanels.Find( pItemPanel );
if ( idx != m_vecItemPanels.InvalidIndex() )
{
OnCommand( CFmtStr( "select%d", idx ) );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::OnSelectionReturned( KeyValues *data )
{
Assert( m_pSelectingItemModelPanel );
m_hSelectionPanel->SetVisible( false );
if ( data && m_pSelectingItemModelPanel )
{
uint64 ulIndex = data->GetUint64( "itemindex", INVALID_ITEM_ID );
CEconItemView* pSelectedItem = InventoryManager()->GetLocalInventory()->GetInventoryItemByItemID( ulIndex );
if ( pSelectedItem )
{
vgui::surface()->PlaySound( "ui/trade_up_apply_sticker.wav" );
}
auto idx = m_vecItemPanels.Find( m_pSelectingItemModelPanel );
SetItem( pSelectedItem, idx );
}
m_pSelectingItemModelPanel = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::UpdateOKButton()
{
bool bOKEnabled = true;
FOR_EACH_VEC( m_vecItemPanels, i )
{
bOKEnabled &= m_vecItemPanels[ i ]->GetItem() != NULL;
}
m_pOKButton->SetEnabled( bOKEnabled );
if ( bOKEnabled )
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pOKButton->GetParent(), "CollectionCrafting_OKBlink" );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::SetVisible( bool bVisible )
{
BaseClass::SetVisible( bVisible );
if ( bVisible )
{
m_pInspectPanel->SetVisible( false );
EditablePanel* pDimmer = FindControl< EditablePanel >( "Dimmer" );
if ( pDimmer )
{
pDimmer->SetAlpha( 0 );
}
EditablePanel* pBG = FindControl< EditablePanel >( "BG" );
if ( pBG )
{
pBG->SetPos( pBG->GetXPos(), GetTall() );
}
m_pTradeUpContainer->SetVisible( true );
m_pTradeUpContainer->SetPos( m_pTradeUpContainer->GetXPos(), -700 );
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_Intro" );
vgui::surface()->PlaySound( "ui/trade_up_panel_slide.wav" );
m_pDrawingPanel->ClearLines( GetLocalPlayerIndex() );
}
else
{
if ( m_hSelectionPanel )
{
m_hSelectionPanel->SetVisible( false );
}
if ( m_bShowing )
{
EconUI()->SetPreventClosure( false );
}
m_bShowing = false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::SOCreated( const CSteamID & steamIDOwner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent )
{
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
if ( m_bWaitingForGCResponse )
{
if( pObject->GetTypeID() != CEconItem::k_nTypeID )
return;
CEconItem *pItem = (CEconItem *)pObject;
if ( IsUnacknowledged( pItem->GetInventoryToken() ) && ( pItem->GetOrigin() == m_eEconItemOrigin ) )
{
//Assert( m_nFoundItemID == INVALID_ITEM_ID );
//m_bWaitingForGCResponse = false;
m_nFoundItemID.AddToTail( pItem->GetItemID() );
CEconItemView* pNewEconItemView = InventoryManager()->GetLocalInventory()->GetInventoryItemByItemID( pItem->GetItemID() );
if ( pNewEconItemView )
{
// Acknowledge the item
InventoryManager()->AcknowledgeItem( pNewEconItemView, true );
InventoryManager()->SaveAckFile();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::Show( CUtlVector< const CEconItemView* >& vecStartingItems )
{
FOR_EACH_VEC( m_vecItemPanels, i )
{
const CEconItemView* pItem = i < vecStartingItems.Count() ? vecStartingItems[ i ] : NULL;
SetItem( pItem, i );
}
m_bShowing = true;
EconUI()->SetPreventClosure( true );
SetVisible( true );
m_eEconItemOrigin = kEconItemOrigin_TradeUp;
}
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::SetWaitingForItem( eEconItemOrigin eOrigin )
{
// Clear Panels
FOR_EACH_VEC( m_vecItemPanels, i )
{
SetItem( NULL, i );
}
m_bShowing = true;
EconUI()->SetPreventClosure( true );
m_pInspectPanel->SetVisible( false );
EditablePanel* pDimmer = FindControl< EditablePanel >( "Dimmer" );
if ( pDimmer )
{
pDimmer->SetAlpha( 0 );
}
EditablePanel* pBG = FindControl< EditablePanel >( "BG" );
if ( pBG )
{
pBG->SetPos( pBG->GetXPos(), GetTall() );
}
m_pTradeUpContainer->SetVisible( false );
// reset
m_pInspectPanel->SetItemCopy( NULL );
m_pCosmeticResultItemModelPanel->SetItem( NULL );
// Do not use Derived SetVisible since it does extra animations we do not want here
BaseClass::SetVisible( true );
m_eEconItemOrigin = eOrigin;
m_bWaitingForGCResponse = true;
m_nFoundItemID.Purge();
m_timerResponse.Start( 5.f );
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_WaitForItemsOnly" );
return;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::SetItem( const CEconItemView* pItem, int nIndex )
{
if ( nIndex != m_vecItemPanels.InvalidIndex() )
{
m_vecImagePanels[ nIndex ]->SetVisible( pItem != NULL );
m_vecItemPanels[ nIndex ]->SetVisible( pItem != NULL );
m_vecItemPanels[ nIndex ]->SetItem( pItem );
if ( pItem && m_vecBoxTopNames.Count() )
{
CUniformRandomStream randomStream;
randomStream.SetSeed( pItem->GetItemID() );
m_vecImagePanels[ nIndex ]->SetImage( m_vecBoxTopNames[ randomStream.RandomInt( 0, m_vecBoxTopNames.Count() - 1 ) ] );
}
}
UpdateOKButton();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCollectionCraftingPanel::OnThink()
{
BaseClass::OnThink();
const float flSoonestAirDropTime = 2.f;
if ( m_timerResponse.HasStarted() )
{
// Elapsed is bad. This means the item server didnt get back to us
if ( m_timerResponse.IsElapsed() )
{
m_nFoundItemID.Purge();
m_bWaitingForGCResponse = false;
m_timerResponse.Invalidate();
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_HideWaiting" );
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_ShowFailure" );
}
else if ( m_timerResponse.GetElapsedTime() > flSoonestAirDropTime || m_bShowImmediately )
{
m_bShowImmediately = false;
// At 2 seconds we want to either show that we're still waiting, or show the item
if ( m_nFoundItemID.Count() > 0 )
{
OnCommand( "itemget" );
m_timerResponse.Invalidate();
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_HideWaiting" );
// Setup the item in the panel
CEconItemView* pNewEconItemView = InventoryManager()->GetLocalInventory()->GetInventoryItemByItemID( m_nFoundItemID[0] );
if ( pNewEconItemView )
{
static CSchemaAttributeDefHandle pAttrib_WeaponAllowInspect( "weapon_allow_inspect" );
if ( pNewEconItemView->FindAttribute( pAttrib_WeaponAllowInspect ) )
{
m_pInspectPanel->SetItemCopy( pNewEconItemView );
m_pInspectPanel->SetSpecialAttributesOnly( true );
m_pCosmeticResultItemModelPanel->SetItem( NULL );
}
else //( IsMiscSlot( pNewEconItemView->GetStaticData()->GetDefaultLoadoutSlot() ) )
{
m_pCosmeticResultItemModelPanel->SetItem( pNewEconItemView );
m_pCosmeticResultItemModelPanel->SetNameOnly( false );
m_pInspectPanel->SetSpecialAttributesOnly( true );
m_pInspectPanel->SetItemCopy( NULL );
}
// Acknowledge the item
InventoryManager()->AcknowledgeItem( pNewEconItemView, true );
InventoryManager()->SaveAckFile();
if ( m_pItemNamePanel )
{
m_pItemNamePanel->SetItem( pNewEconItemView );
}
}
m_bWaitingForGCResponse = false;
// only show if more then 1 item in queue
m_pNextItemButton->SetVisible( m_nFoundItemID.Count() > 1 );
}
else
{
// Say that we're waiting
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_ShowWaiting" );
}
}
}
bool bEnvelopReadyToSendThisFrame = true;
// They need to have drawn a little bit
bEnvelopReadyToSendThisFrame &= m_pDrawingPanel->GetLines( GetLocalPlayerIndex() ).Count() > 10;
// And placed a stamp
bEnvelopReadyToSendThisFrame &= m_pStampPanel->IsVisible();
// Show the send button?
if ( bEnvelopReadyToSendThisFrame && !m_bEnvelopeReadyToSend )
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_ShowSendButton" );
}
m_bEnvelopeReadyToSend = bEnvelopReadyToSendThisFrame;
}
//* **************************************************************************************************************************************
// Stat Clock Crafting
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCraftCommonStatClockPanel::CCraftCommonStatClockPanel( vgui::Panel *parent, CItemModelPanelToolTip* pTooltip )
: BaseClass( parent, pTooltip )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCraftCommonStatClockPanel::~CCraftCommonStatClockPanel( void )
{
}
//-----------------------------------------------------------------------------
void CCraftCommonStatClockPanel::Show( CUtlVector< const CEconItemView* >& vecStartingItems )
{
BaseClass::Show( vecStartingItems );
// Create output
static CSchemaItemDefHandle pItemDef_CommonStatClock( "Common Stat Clock" );
m_outputItem.SetItemDefIndex( pItemDef_CommonStatClock->GetDefinitionIndex() );
m_outputItem.SetItemQuality( AE_UNIQUE ); // Unique by default
m_outputItem.SetItemLevel( 0 ); // Hide this?
m_outputItem.SetItemID( 0 );
m_outputItem.SetInitialized( true );
m_vecOutputImagePanels[0]->SetVisible( true );
m_vecOutputItemPanels[0]->SetVisible( true );
m_vecOutputItemPanels[0]->SetItem( &m_outputItem );
if ( m_vecBoxTopNames.Count() )
{
CUniformRandomStream randomStream;
randomStream.SetSeed( 0 );
m_vecOutputImagePanels[0]->SetImage( m_vecBoxTopNames[randomStream.RandomInt( 0, m_vecBoxTopNames.Count() - 1 )] );
}
}
//-----------------------------------------------------------------------------
void CCraftCommonStatClockPanel::CreateSelectionPanel()
{
CStatClockCraftingSelectionPanel *pSelectionPanel = new CStatClockCraftingSelectionPanel( this );
m_hSelectionPanel = (CCollectionCraftingSelectionPanel*)pSelectionPanel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCraftCommonStatClockPanel::OnCommand( const char *command )
{
if ( FStrEq( "envelopesend", command ) )
{
GCSDK::CProtoBufMsg<CMsgCraftCommonStatClock> msg( k_EMsgGCCraftCommonStatClock );
// Find out if the user owns this item or not and place in the proper bucket
CPlayerInventory *pLocalInv = TFInventoryManager()->GetLocalInventory();
if ( !pLocalInv )
return;
FOR_EACH_VEC( m_vecItemPanels, i )
{
if ( m_vecItemPanels[i]->GetItem() == NULL )
return;
msg.Body().add_item_id( m_vecItemPanels[i]->GetItem()->GetItemID() );
}
// Send if off
GCClientSystem()->BSendMessage( msg );
m_bWaitingForGCResponse = true;
m_nFoundItemID.Purge();
m_timerResponse.Start( 5.f );
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_LetterSend" );
return;
}
BaseClass::OnCommand( command );
}
@@ -0,0 +1,225 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef COLLECTION_CRAFTING_PANEL_H
#define COLLECTION_CRAFTING_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "backpack_panel.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "tf_gcmessages.h"
#include "econ_gcmessages.h"
#include "tf_imagepanel.h"
#include "tf_controls.h"
#include "item_selection_panel.h"
#include "drawing_panel.h"
#include "local_steam_shared_object_listener.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CCollectionCraftingSelectionPanel : public CItemCriteriaSelectionPanel
{
DECLARE_CLASS_SIMPLE( CCollectionCraftingSelectionPanel, CItemCriteriaSelectionPanel );
public:
CCollectionCraftingSelectionPanel( Panel *pParent ) : BaseClass( pParent, NULL ) {}
void SetCorrespondingItems( CCopyableUtlVector< const CEconItemView* >& vecSelectedItems )
{
m_vecCorrespondingItems = vecSelectedItems;
}
void ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
vgui::Label* pWeaponLabel = dynamic_cast<vgui::Label*>( FindChildByName( "ItemSlotLabel" ) );
if ( pWeaponLabel )
{
pWeaponLabel->SetVisible( false );
}
}
//-----------------------------------------------------------------------------
virtual const char *GetSelectionInvalidReason( const IEconItemInterface *pTestItem, const IEconItemInterface *pSourceItem ) const
{
return GetCollectionCraftingInvalidReason( pTestItem, pSourceItem );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *GetItemNotSelectableReason( const CEconItemView *pItem ) const
{
if ( !pItem )
return NULL;
const CEconItemView* pSourceItem = m_vecCorrespondingItems.Count() ? m_vecCorrespondingItems[0] : NULL;
FOR_EACH_VEC( m_vecCorrespondingItems, i )
{
if ( pItem->GetItemID() == m_vecCorrespondingItems[i]->GetItemID() )
{
return "#TF_StrangeCount_Transfer_Self";
}
}
return GetSelectionInvalidReason( pItem, pSourceItem );
}
virtual bool ShouldDeleteOnClose( void ) OVERRIDE{ return false; }
protected:
const char * m_pszTitleToken;
CUtlVector< const CEconItemView* > m_vecCorrespondingItems;
};
//-----------------------------------------------------------------------------
// A panel to let users choose 10 weapons to craft up within collections
//-----------------------------------------------------------------------------
class CCollectionCraftingPanel : public vgui::EditablePanel, public CGameEventListener, public CLocalSteamSharedObjectListener
{
public:
DECLARE_CLASS_SIMPLE( CCollectionCraftingPanel, vgui::EditablePanel );
CCollectionCraftingPanel( vgui::Panel *parent, CItemModelPanelToolTip* pTooltip );
~CCollectionCraftingPanel( void );
virtual const char *GetResFile( void ) { return "Resource/UI/econ/CollectionCraftingDialog.res"; }
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
virtual void PerformLayout() OVERRIDE;
virtual void FireGameEvent( IGameEvent *event ) OVERRIDE;
virtual void OnCommand( const char *command ) OVERRIDE;
virtual void SetVisible( bool bVisible ) OVERRIDE;
virtual void SOCreated( const CSteamID & steamIDOwner, const GCSDK::CSharedObject *pObject, GCSDK::ESOCacheEvent eEvent ) OVERRIDE;
virtual void Show( CUtlVector< const CEconItemView* >& vecStartingItems );
void SetWaitingForItem( eEconItemOrigin eOrigin );
virtual int GetInputItemCount() { return COLLECTION_CRAFTING_ITEM_COUNT; }
virtual int GetOutputItemCount() { return 0; } // For Ui Display Purposes
MESSAGE_FUNC_PTR( OnItemPanelMousePressed, "ItemPanelMousePressed", panel );
MESSAGE_FUNC_PARAMS( OnSelectionReturned, "SelectionReturned", data );
protected:
virtual void SetItemPanelCount( );
virtual void CreateSelectionPanel();
virtual void CreateItemPanels();
void SelectPanel( int nPanel );
void UpdateOKButton();
void SetItem( const CEconItemView* pItem, int nIndex );
virtual void OnThink() OVERRIDE;
CItemModelPanelToolTip *m_pMouseOverTooltip;
DHANDLE<CCollectionCraftingSelectionPanel> m_hSelectionPanel;
CExButton *m_pOKButton;
CExButton *m_pNextItemButton;
EditablePanel* m_pTradeUpContainer;
CItemModelPanel* m_pSelectingItemModelPanel;
CUtlVector< EditablePanel* > m_vecItemContainers;
CUtlVector< ImagePanel* > m_vecImagePanels;
CUtlVector< CItemModelPanel* > m_vecItemPanels;
CUtlVector< EditablePanel* > m_vecOutputItemContainers;
CUtlVector< ImagePanel* > m_vecOutputImagePanels;
CUtlVector< CItemModelPanel* > m_vecOutputItemPanels;
CUtlVector< CUtlString > m_vecBoxTopNames;
CUtlVector< CUtlString > m_vecStampNames;
CUtlVector< CUtlString > m_vecResultStrings;
struct LocalizedPanelAction_t
{
CUtlString m_strPanel;
bool m_bShowForEnglish;
};
CUtlVector< LocalizedPanelAction_t > m_vecLocalizedPanels;
CBaseModelPanel *m_pModelPanel;
ImagePanel* m_pStampPanel;
CExButton* m_pStampButton;
CDrawingPanel *m_pDrawingPanel;
CTFItemInspectionPanel *m_pInspectPanel;
CItemModelPanel* m_pCosmeticResultItemModelPanel;
CItemModelPanel* m_pItemNamePanel;
KeyValues* m_pKVItemPanels;
bool m_bWaitingForGCResponse;
RealTimeCountdownTimer m_timerResponse;
CUtlVector<itemid_t> m_nFoundItemID;
bool m_bEnvelopeReadyToSend;
bool m_bShowing;
bool m_bShowImmediately;
eEconItemOrigin m_eEconItemOrigin;
CPanelAnimationVarAliasType( int, m_iButtonsStartX, "buttons_start_x", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iButtonsStartY, "buttons_start_y", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iButtonsStepX, "buttons_step_x", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iButtonsStepY, "buttons_step_y", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iOutputItemStartX, "output_start_x", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iOutputItemStartY, "output_start_y", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iOutputItemStepX, "output_step_x", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iOutputItemStepY, "output_step_y", "0", "proportional_int" );
CPanelAnimationVarAliasType( float, m_flSlideInTime, "slide_in_time", "1.0", "float" );
CPanelAnimationVarAliasType( int, m_iBGContainerTargetY, "bg_target_y", "0", "proportional_int" );
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CStatClockCraftingSelectionPanel : public CCollectionCraftingSelectionPanel
{
DECLARE_CLASS_SIMPLE( CStatClockCraftingSelectionPanel, CCollectionCraftingSelectionPanel );
public:
CStatClockCraftingSelectionPanel( Panel *pParent ) : BaseClass( pParent ) {}
//-----------------------------------------------------------------------------
virtual const char *GetSelectionInvalidReason( const IEconItemInterface *pTestItem, const IEconItemInterface *pSourceItem ) const
{
return GetCraftCommonStatClockInvalidReason( pTestItem, pSourceItem ); // FIX ME
}
};
//-----------------------------------------------------------------------------
// A panel to let users choose 10 weapons to craft up within collections
//-----------------------------------------------------------------------------
class CCraftCommonStatClockPanel : public CCollectionCraftingPanel
{
public:
DECLARE_CLASS_SIMPLE( CCraftCommonStatClockPanel, CCollectionCraftingPanel );
CCraftCommonStatClockPanel( vgui::Panel *parent, CItemModelPanelToolTip* pTooltip );
~CCraftCommonStatClockPanel( void );
virtual const char *GetResFile( void ) { return "Resource/UI/econ/MannCoTrade_CommonStatClock.res"; }
virtual void OnCommand( const char *command ) OVERRIDE;
virtual int GetInputItemCount() { return CRAFT_COMMON_STATCLOCK_ITEM_COUNT; }
virtual int GetOutputItemCount() { return 1; }
virtual void Show( CUtlVector< const CEconItemView* >& vecStartingItems );
protected:
virtual void CreateSelectionPanel();
CEconItemView m_outputItem;
};
#endif // COLLECTION_CRAFTING_PANEL_H
File diff suppressed because it is too large Load Diff
+202
View File
@@ -0,0 +1,202 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CRAFTING_PANEL_H
#define CRAFTING_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "backpack_panel.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "tf_gcmessages.h"
#include "econ_gcmessages.h"
#include "tf_imagepanel.h"
#include "tf_controls.h"
#include "item_selection_panel.h"
class CImageButton;
// Crafting slots on crafting page
#define CRAFTING_SLOTS_INPUT_ROWS 3
#define CRAFTING_SLOTS_INPUT_COLUMNS 4
#define CRAFTING_SLOTS_INPUTPANELS (CRAFTING_SLOTS_INPUT_ROWS * CRAFTING_SLOTS_INPUT_COLUMNS)
#define CRAFTING_SLOTS_OUTPUT_ROWS 1
#define CRAFTING_SLOTS_OUTPUT_COLUMNS 4
#define CRAFTING_SLOTS_COUNT (CRAFTING_SLOTS_INPUTPANELS + (CRAFTING_SLOTS_OUTPUT_ROWS * CRAFTING_SLOTS_OUTPUT_COLUMNS))
#define RECIPE_CUSTOM -2
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CRecipeButton : public CExButton
{
private:
DECLARE_CLASS_SIMPLE( CRecipeButton, CExButton );
public:
CRecipeButton( vgui::Panel *parent, const char *name, const char *text, vgui::Panel *pActionSignalTarget = NULL, const char *cmd = NULL )
: CExButton( parent, name, text, pActionSignalTarget, cmd )
{
}
virtual void ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
SetEnabled( m_iRecipeDefIndex != -1 );
}
void SetDefIndex( int iIndex )
{
m_iRecipeDefIndex = iIndex;
SetEnabled( m_iRecipeDefIndex != -1 );
}
void OnCursorEntered( void )
{
PostActionSignal( new KeyValues("RecipePanelEntered") );
BaseClass::OnCursorEntered();
}
void OnCursorExited( void )
{
PostActionSignal( new KeyValues("RecipePanelExited") );
BaseClass::OnCursorExited();
}
public:
int m_iRecipeDefIndex;
};
//-----------------------------------------------------------------------------
// An inventory screen that handles displaying the crafting screen
//-----------------------------------------------------------------------------
class CCraftingPanel : public CBaseLoadoutPanel
{
DECLARE_CLASS_SIMPLE( CCraftingPanel, CBaseLoadoutPanel );
public:
CCraftingPanel( vgui::Panel *parent, const char *panelName );
~CCraftingPanel( void );
virtual const char *GetResFile( void ) { return "Resource/UI/CraftingPanel.res"; }
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void PerformLayout( void );
virtual void OnShowPanel( bool bVisible, bool bReturningFromArmory );
virtual void OnCommand( const char *command );
void CreateRecipeFilterButtons( void );
void UpdateRecipeFilter( void );
virtual int GetNumItemPanels( void ) { return CRAFTING_SLOTS_COUNT; };
bool IsInputItemPanel( int iSlot ) { return (iSlot < CRAFTING_SLOTS_INPUTPANELS); }
virtual void PositionItemPanel( CItemModelPanel *pPanel, int iIndex );
int GetItemPanelIndex( CItemModelPanel *pItemPanel );
void UpdateSelectedRecipe( bool bClearInputItems );
void UpdateRecipeItems( bool bClearInputItems );
void UpdateCraftButton( void );
const char *GetItemTextForCriteria( const CItemSelectionCriteria *pCriteria );
CEconItemDefinition *GetItemDefFromCriteria( const CItemSelectionCriteria *pCriteria );
virtual void AddNewItemPanel( int iPanelIndex );
virtual void UpdateModelPanels( void );
void SetButtonToRecipe( int iButton, int iDefIndex, wchar_t *pszText );
bool CheckForUntradableItems( void );
void Craft( void );
void OnCraftResponse( EGCMsgResponse eResponse, CUtlVector<uint64> *vecCraftedIndices, int iRecipeUsed );
void ShowCraftFinish( void );
virtual void OnTick( void );
void CleanupPostCraft( bool bClearInputItems );
MESSAGE_FUNC_PTR( OnItemPanelMousePressed, "ItemPanelMousePressed", panel );
MESSAGE_FUNC_PTR( OnRecipePanelEntered, "RecipePanelEntered", panel );
MESSAGE_FUNC_PTR( OnRecipePanelExited, "RecipePanelExited", panel );
MESSAGE_FUNC( OnCancelSelection, "CancelSelection" );
MESSAGE_FUNC_PARAMS( OnSelectionReturned, "SelectionReturned", data );
MESSAGE_FUNC( OnClosing, "Closing" );
virtual ConVar *GetExplanationConVar( void );
private:
// Items in the input model panels
itemid_t m_InputItems[CRAFTING_SLOTS_INPUTPANELS];
const CItemSelectionCriteria *m_ItemPanelCriteria[CRAFTING_SLOTS_INPUTPANELS];
CExButton *m_pCraftButton;
CExButton *m_pUpgradeButton;
CExLabel *m_pFreeAccountLabel;
vgui::EditablePanel *m_pRecipeListContainer;
vgui::ScrollableEditablePanel *m_pRecipeListContainerScroller;
vgui::EditablePanel *m_pSelectedRecipeContainer;
KeyValues *m_pRecipeButtonsKV;
CUtlVector<CRecipeButton*> m_pRecipeButtons;
KeyValues *m_pRecipeFilterButtonsKV;
CUtlVector<CImageButton*> m_pRecipeFilterButtons;
int m_iCurrentlySelectedRecipe;
int m_iCurrentRecipeTotalInputs;
int m_iCurrentRecipeTotalOutputs;
recipecategories_t m_iRecipeCategoryFilter;
CUtlVector<itemid_t> m_vecNewlyCraftedItems;
double m_flAbortCraftingAt;
bool m_bWaitingForCraftItems;
int m_iRecipeIndexTried;
int m_iNewRecipeIndex;
bool m_bEventLogging;
int m_iCraftingAttempts;
CTFTextToolTip *m_pToolTip;
vgui::EditablePanel *m_pToolTipEmbeddedPanel;
CCraftingItemSelectionPanel *m_pSelectionPanel;
int m_iSelectingForSlot;
CPanelAnimationVarAliasType( int, m_iItemCraftingOffcenterX, "item_crafting_offcenter_x", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iFilterOffcenterX, "filter_xoffset", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iFilterYPos, "filter_ypos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iFilterDeltaX, "filter_xdelta", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iFilterDeltaY, "filter_ydelta", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iOutputItemYPos, "output_item_ypos", "0", "proportional_int" );
};
//-----------------------------------------------------------------------------
// Purpose: A dialog used to show the current state of a crafting request.
//-----------------------------------------------------------------------------
class CCraftingStatusDialog : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CCraftingStatusDialog, vgui::EditablePanel );
public:
CCraftingStatusDialog( vgui::Panel *pParent, const char *pElementName );
virtual void ApplySchemeSettings( vgui::IScheme *scheme );
virtual void OnCommand( const char *command );
virtual void OnTick( void );
void UpdateSchemeForVersion( bool bRecipe );
void ShowStatusUpdate( bool bAnimateEllipses, bool bAllowed, bool bShowOnExit );
private:
bool m_bShowOnExit;
bool m_bAnimateEllipses;
int m_iNumEllipses;
bool m_bShowNewRecipe;
CItemModelPanel *m_pRecipePanel;
};
CCraftingStatusDialog *OpenCraftingStatusDialog( vgui::Panel *pParent, const char *pszText, bool bAnimateEllipses, bool bAllowClose, bool bShowOnExit );
CCraftingStatusDialog *OpenNewRecipeFoundDialog( vgui::Panel *pParent, const CEconCraftingRecipeDefinition *pRecipeDef );
void CloseCraftingStatusDialog( void );
#endif // CRAFTING_PANEL_H
+388
View File
@@ -0,0 +1,388 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "crate_detail_panels.h"
#include "vgui_controls/TextImage.h"
#include "econ_gcmessages.h"
#include "gc_clientsystem.h"
#include "econ_ui.h"
#include <vgui/ISurface.h>
#include "econ_item_inventory.h"
#include "econ/tool_items/tool_items.h"
#define SHUFFLE_TIME 5.f
float CInputStringForItemBackpackOverlayDialog::m_sflNextShuffleTime = 0.f;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CInputStringForItemBackpackOverlayDialog::CInputStringForItemBackpackOverlayDialog( vgui::Panel *pParent, CEconItemView *pItem, CEconItemView *pChosenKey )
: vgui::EditablePanel( pParent, "InputStringForItemBackpackOverlayDialog" )
, m_Item( *pItem )
, m_pPreviewModelPanel( NULL )
, m_pTextEntry( NULL )
, m_pItemModelPanelKVs( NULL )
, m_bUpdateRecieved( false )
{
if ( pChosenKey )
{
m_UseableKey = *pChosenKey;
}
m_pPreviewModelPanel = new CItemModelPanel( this, "preview_model" );
m_pTextEntry = new vgui::TextEntry( this, "TextEntryControl" );
m_pShuffleButton = new CExButton( this, "ShuffleButton", "Shuffle" );
m_pRareLootLabel = new CExLabel( this, "RareLootLabel", "#Econ_Revolving_Loot_List_Rare_Item" );
m_pProgressBar = new vgui::ProgressBar( this, "ShuffleProgress" );
m_pGetKeyButton = new CExButton( this, "GetKeyButton", "getkey" );
m_pUseKeyButton = new CExButton( this, "UseKeyButton", "usekey" );
m_pMouseOverItemPanel = vgui::SETUP_PANEL( new CItemModelPanel( this, "mouseoveritempanel" ) );
m_pMouseOverTooltip = new CItemModelPanelToolTip( this );
m_pMouseOverTooltip->SetupPanels( this, m_pMouseOverItemPanel );
ListenForGameEvent( "inventory_updated" );
}
CInputStringForItemBackpackOverlayDialog::~CInputStringForItemBackpackOverlayDialog()
{
if ( m_pItemModelPanelKVs )
{
m_pItemModelPanelKVs->deleteThis();
m_pItemModelPanelKVs = NULL;
}
m_vecContentsPanels.PurgeAndDeleteElements();
}
void CInputStringForItemBackpackOverlayDialog::FireGameEvent( IGameEvent *event )
{
// If we're not visible, ignore all events
if ( !IsVisible() )
return;
// Something caused our inventory to update. Assuming it was from our shuffle
// then we need to update ourselves.
const char *type = event->GetName();
if ( Q_strcmp( "inventory_updated", type ) == 0 )
{
m_bUpdateRecieved = true;
}
}
void CInputStringForItemBackpackOverlayDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/econ/InputStringForItemBackpackOverlayDialog.res" );
CCrateLootListWrapper itemWrapper( &m_Item );
const IEconLootList *pLootList = itemWrapper.GetEconLootList();
// Set the crate footer text. The crate itself specifies what to use.
if ( pLootList->GetLootListFooterLocalizationKey() )
{
m_pRareLootLabel->SetText( pLootList->GetLootListFooterLocalizationKey() );
}
else
{
const char *pszRareLootListFooterLocalizationKey = m_Item.GetItemDefinition()->GetDefinitionString( "loot_list_rare_item_footer", "#Econ_Revolving_Loot_List_Rare_Item" );
m_pRareLootLabel->SetText( pszRareLootListFooterLocalizationKey );
}
// Use the gradient border for the tooltip
m_pMouseOverItemPanel->SetBorder( pScheme->GetBorder("LoadoutItemPopupBorder") );
m_pPreviewModelPanel->SetItem( &m_Item );
m_pPreviewModelPanel->SetActAsButton( false, false ); // Dont mess around with the mouse
m_pTextEntry->RequestFocus();
}
void CInputStringForItemBackpackOverlayDialog::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
// Pull out the model panel KVs for this panel
KeyValues *pItemKV = inResourceData->FindKey( "modelpanels_kv" );
if ( pItemKV )
{
if ( m_pItemModelPanelKVs )
{
m_pItemModelPanelKVs->deleteThis();
}
m_pItemModelPanelKVs = new KeyValues( "modelpanels_kv" );
pItemKV->CopySubkeys( m_pItemModelPanelKVs );
}
CreateItemPanels();
}
void CInputStringForItemBackpackOverlayDialog::CreateItemPanels()
{
CCrateLootListWrapper itemWrapper( &m_Item );
const IEconLootList *pLootList = itemWrapper.GetEconLootList();
class CItemDefLootListIterator : public IEconLootList::IEconLootListIterator
{
public:
CItemDefLootListIterator( CUtlVector< item_definition_index_t > *pVecItemDefs )
: m_pVecItemDefs( pVecItemDefs )
{}
virtual void OnIterate( item_definition_index_t unItemDefIndex ) OVERRIDE
{
const CEconItemDefinition *pItemDef = GetItemSchema()->GetItemDefinition( unItemDefIndex );
if ( pItemDef && pItemDef->BValidForShuffle() )
{
m_pVecItemDefs->AddToTail( unItemDefIndex );
}
}
private:
CUtlVector< item_definition_index_t > * const m_pVecItemDefs;
};
// Get the drops from the item
CUtlVector< item_definition_index_t > vecItemDefs;
CItemDefLootListIterator it( &vecItemDefs );
pLootList->EnumerateUserFacingPotentialDrops( &it );
if ( !m_pItemModelPanelKVs )
return;
if ( m_vecContentsPanels.Count() != vecItemDefs.Count() )
{
m_vecContentsPanels.PurgeAndDeleteElements();
FOR_EACH_VEC( vecItemDefs, i )
{
// Create new panel
CItemModelPanel* pItemPanel = m_vecContentsPanels[ m_vecContentsPanels.AddToTail( new CItemModelPanel( this, CFmtStr( "item_preview_%d", i ) ) ) ];
pItemPanel->ApplySettings( m_pItemModelPanelKVs );
pItemPanel->InvalidateLayout( true );
pItemPanel->SetActAsButton( false, true ); // Lets us get mouse enter/exit evens for tooltips
pItemPanel->SetTooltip( m_pMouseOverTooltip, "" ); // Tooltip panel to use
}
}
// Create the panels and set the items into them
FOR_EACH_VEC( vecItemDefs, i )
{
const item_definition_index_t &itemDef = vecItemDefs[i];
CItemModelPanel* pItemPanel = m_vecContentsPanels[i];
CEconItemView item;
item.SetItemDefIndex( itemDef );
item.SetItemQuality( AE_UNIQUE ); // Unique by default
item.SetItemLevel( 0 ); // Hide this?
item.SetInitialized( true );
item.SetItemOriginOverride( kEconItemOrigin_Invalid );
pItemPanel->SetItem( &item );
}
}
void CInputStringForItemBackpackOverlayDialog::PerformLayout( void )
{
BaseClass::PerformLayout();
// Find out how wide these panels will be side by side
const int nBuffer = 5;
int nTotalWide = 0;
const int nCount = m_vecContentsPanels.Count();
if ( nCount )
{
const int nWide = m_vecContentsPanels.Head()->GetWide();
nTotalWide = (nCount * nWide) + ( (nCount - 1) * nBuffer );
}
// Find out how much space the panels take up within the parent
int nParentWide = GetWide();
int nDiff = nParentWide - nTotalWide;
// How far we need to offset from the left edge
int nStartOffset = nDiff / 2;
// Place all the panels side by side
FOR_EACH_VEC( m_vecContentsPanels, i )
{
CItemModelPanel* pItemPanel = m_vecContentsPanels[ i ];
const int nWide = pItemPanel->GetWide();
pItemPanel->SetPos( nStartOffset + i * (nWide + nBuffer), YRES(150) );
pItemPanel->SetVisible( true );
}
// Which button to show
m_pUseKeyButton->SetVisible( m_UseableKey.IsValid() );
m_pGetKeyButton->SetVisible( !m_UseableKey.IsValid() );
}
void CInputStringForItemBackpackOverlayDialog::OnCommand( const char *command )
{
if ( !Q_strnicmp( command, "cancel", 6 ) )
{
TFModalStack()->PopModal( this );
SetVisible( false );
MarkForDeletion();
}
else if ( !Q_strnicmp( command, "shuffle", 7 ) )
{
// let the GC know
if ( m_pTextEntry && Plat_FloatTime() >= m_sflNextShuffleTime )
{
// Set the next time they can send a request to shuffle
m_sflNextShuffleTime = Plat_FloatTime() + SHUFFLE_TIME;
enum { kMaxCodeStringSize = 32 };
char szText[ kMaxCodeStringSize ] = { 0 };
m_pTextEntry->GetText( &szText[0], sizeof( szText ) );
GCSDK::CProtoBufMsg<CMsgGCShuffleCrateContents> msg( k_EMsgGCShuffleCrateContents );
msg.Body().set_crate_item_id( m_Item.GetID() );
msg.Body().set_user_code_string( szText );
GCClientSystem()->BSendMessage( msg );
m_pProgressBar->SetProgress( 0.f );
m_pProgressBar->SetVisible( true );
m_pTextEntry->SetVisible( false );
vgui::surface()->PlaySound( "ui/itemcrate_shuffle.wav" );
}
}
else if ( !Q_strnicmp( command, "getkey", 6 ) )
{
static CSchemaAttributeDefHandle pAttrDef_DecodedBy( "decoded by itemdefindex" );
uint32 iDecodableItemDef = 0;
if ( m_Item.FindAttribute( pAttrDef_DecodedBy, &iDecodableItemDef ) )
{
// casting to the proper type since our econ system is dumb
const float& value_as_float = (float&)iDecodableItemDef;
EconUI()->CloseEconUI();
EconUI()->OpenStorePanel( (int)value_as_float, false );
// close ourselves
TFModalStack()->PopModal( this );
SetVisible( false );
MarkForDeletion();
}
}
else if ( !Q_strnicmp( command, "usekey", 6 ) )
{
if ( m_UseableKey.IsValid() )
{
// Use the key
ApplyTool( GetParent(), &m_UseableKey, &m_Item );
// close ourselves
TFModalStack()->PopModal( this );
SetVisible( false );
MarkForDeletion();
}
}
}
void CInputStringForItemBackpackOverlayDialog::FindUsableKey()
{
static CSchemaAttributeDefHandle pAttrDef_DecodedBy( "decoded by itemdefindex" );
uint32 iDecodableItemDef = 0;
if ( m_Item.FindAttribute( pAttrDef_DecodedBy, &iDecodableItemDef ) )
{
const float& value_as_float = (float&)iDecodableItemDef;
iDecodableItemDef = (float)value_as_float;
CPlayerInventory *pInventory = InventoryManager()->GetLocalInventory();
if ( !pInventory )
return;
for ( int i = 0; i < pInventory->GetItemCount(); i++ )
{
CEconItemView *pItem = pInventory->GetItem(i);
if ( pItem->GetItemDefIndex() == iDecodableItemDef )
{
m_UseableKey = *pItem;
}
}
}
}
void CInputStringForItemBackpackOverlayDialog::OnThink()
{
float flDelta = m_sflNextShuffleTime - Plat_FloatTime();
// If we're ready, show "Shuffle"
if ( flDelta < 0 )
{
// Show the text entry, show the progress bar
m_pProgressBar->SetVisible( false );
m_pTextEntry->SetVisible( true );
// Re-enable the shuffle/use buttons
m_pShuffleButton->SetEnabled( m_pTextEntry->GetTextLength() != 0 );
m_pUseKeyButton->SetEnabled( true );
// Say "Shuffle"
m_pShuffleButton->SetText( "#ShuffleContents" );
// We got a inventory update message, update
if ( m_bUpdateRecieved )
{
CreateItemPanels();
m_bUpdateRecieved = false;
}
}
else
{
// Show the progress bar, hide the text field
m_pProgressBar->SetVisible( true );
m_pTextEntry->SetVisible( false );
// Dont allow clicking the shuffle or use key button
m_pShuffleButton->SetEnabled( false );
m_pUseKeyButton->SetEnabled( false );
// Say "Shuffling..."
m_pShuffleButton->SetText( "#ShufflingContents" );
// Set progress
float flProgress = ( SHUFFLE_TIME - flDelta ) / SHUFFLE_TIME;
m_pProgressBar->SetProgress( flProgress );
}
}
void CInputStringForItemBackpackOverlayDialog::Show()
{
SetVisible( true );
MakePopup();
MoveToFront();
SetKeyBoardInputEnabled( true );
SetMouseInputEnabled( true );
TFModalStack()->PushModal( this );
// If a key wasnt passed in, find the first one in the
// player's inventory
if ( !m_UseableKey.IsValid() )
{
FindUsableKey();
}
// Which button to show
m_pUseKeyButton->SetVisible( m_UseableKey.IsValid() );
m_pGetKeyButton->SetVisible( !m_UseableKey.IsValid() );
// Put the current gen code of the crate into the text field
static CSchemaAttributeDefHandle pAttrDef_DecodedBy( "crate generation code" );
const char *pszAttrGenCode;
if ( FindAttribute_UnsafeBitwiseCast<CAttribute_String>( &m_Item, pAttrDef_DecodedBy, &pszAttrGenCode ) )
{
m_pTextEntry->SetText( pszAttrGenCode );
}
}
+62
View File
@@ -0,0 +1,62 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CRATE_DETAIL_PANELS_H
#define CRATE_DETAIL_PANELS_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_controls.h"
#include "item_model_panel.h"
#include "econ_item_view.h"
#include <vgui_controls/TextEntry.h>
#include <vgui_controls/ProgressBar.h>
class CInputStringForItemBackpackOverlayDialog : public vgui::EditablePanel, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CInputStringForItemBackpackOverlayDialog, vgui::EditablePanel );
public:
CInputStringForItemBackpackOverlayDialog( vgui::Panel *pParent, CEconItemView *pItem, CEconItemView *pChosenKey = NULL );
~CInputStringForItemBackpackOverlayDialog();
virtual void FireGameEvent( IGameEvent *event ) OVERRIDE;
virtual void ApplySchemeSettings( vgui::IScheme *pScheme ) OVERRIDE;
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
virtual void PerformLayout( void ) OVERRIDE;
virtual void OnCommand( const char *command ) OVERRIDE;
virtual void OnThink() OVERRIDE;
void Show();
protected:
CItemModelPanel *GetPreviewModelPanel() { return m_pPreviewModelPanel; }
CEconItemView m_Item;
private:
void CreateItemPanels();
void FindUsableKey();
vgui::ProgressBar *m_pProgressBar;
CExLabel *m_pRareLootLabel;
CExButton *m_pUseKeyButton;
CExButton *m_pGetKeyButton;
CExButton *m_pShuffleButton;
CItemModelPanel *m_pPreviewModelPanel;
vgui::TextEntry *m_pTextEntry;
CUtlVector< CItemModelPanel* > m_vecContentsPanels;
KeyValues *m_pItemModelPanelKVs;
CItemModelPanelToolTip *m_pMouseOverTooltip;
CItemModelPanel *m_pMouseOverItemPanel;
static float m_sflNextShuffleTime;
bool m_bUpdateRecieved;
CEconItemView m_UseableKey;
};
#endif // CRATE_DETAIL_PANELS_H
+335
View File
@@ -0,0 +1,335 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "drawing_panel.h"
#include "softline.h"
#include <vgui/IScheme.h>
#include <vgui/IVGui.h>
#include "voice_status.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
extern ConVar cl_mute_all_comms;
Color g_DrawPanel_TeamColors[TF_TEAM_COUNT] =
{
COLOR_TF_SPECTATOR, // unassigned
COLOR_TF_SPECTATOR, // spectator
COLOR_TF_RED, // red
COLOR_TF_BLUE, // blue
};
DECLARE_BUILD_FACTORY( CDrawingPanel );
CDrawingPanel::CDrawingPanel( Panel *parent, const char*name ) : Panel( parent, name )
{
m_bDrawingLines = false;
m_fLastMapLine = 0;
m_iMouseX = 0;
m_iMouseY = 0;
m_iPanelType = DRAWING_PANEL_TYPE_NONE;
m_bTeamColors = false;
m_nWhiteTexture = vgui::surface()->CreateNewTextureID();
vgui::surface()->DrawSetTextureFile( m_nWhiteTexture, "vgui/white", true, false );
ListenForGameEvent( "cl_drawline" );
}
void CDrawingPanel::SetVisible( bool bState )
{
ClearAllLines();
BaseClass::SetVisible( bState );
}
void CDrawingPanel::ReadColor( const char* pszToken, Color& color )
{
if ( pszToken && *pszToken )
{
int r = 0, g = 0, b = 0, a = 255;
if ( sscanf( pszToken, "%d %d %d %d", &r, &g, &b, &a ) >= 3 )
{
// it's a direct color
color = Color( r, g, b, a );
}
else
{
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
color = pScheme->GetColor( pszToken, Color( 0, 0, 0, 0 ) );
}
}
}
void CDrawingPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
ReadColor( inResourceData->GetString( "linecolor", "" ), m_colorLine );
m_bTeamColors = inResourceData->GetBool( "team_colors", false );
}
void CDrawingPanel::Paint()
{
for ( int iIndex = 0; iIndex < ARRAYSIZE( m_vecDrawnLines ); iIndex++ )
{
//Draw the lines
for ( int i = 0; i < m_vecDrawnLines[iIndex].Count(); i++ )
{
if ( !m_vecDrawnLines[iIndex][i].bSetBlipCentre )
{
Vector vecBlipPos;
vecBlipPos.x = m_vecDrawnLines[iIndex][i].worldpos.x;
vecBlipPos.y = m_vecDrawnLines[iIndex][i].worldpos.y;
vecBlipPos.z = 0;
//Msg("drawing line with blippos %f, %f\n", vecBlipPos.x, vecBlipPos.y);
m_vecDrawnLines[iIndex][i].blipcentre = m_vecDrawnLines[iIndex][i].worldpos;
//Msg(" which is blipcentre=%f, %f\n", m_MapLines[i].blipcentre.x, m_MapLines[i].blipcentre.y);
m_vecDrawnLines[iIndex][i].bSetBlipCentre = true;
}
float x = m_vecDrawnLines[iIndex][i].blipcentre.x;
float y = m_vecDrawnLines[iIndex][i].blipcentre.y;
if ( m_vecDrawnLines[iIndex][i].bLink )
{
if ( i > 1 )
{
m_vecDrawnLines[iIndex][i].linkpos = m_vecDrawnLines[iIndex][i-1].worldpos;
if ( !m_vecDrawnLines[iIndex][i].bSetLinkBlipCentre )
{
Vector vecBlipPos2;
vecBlipPos2.x = m_vecDrawnLines[iIndex][i].linkpos.x;
vecBlipPos2.y = m_vecDrawnLines[iIndex][i].linkpos.y;
vecBlipPos2.z = 0;
m_vecDrawnLines[iIndex][i].linkblipcentre = m_vecDrawnLines[iIndex][i].linkpos;
m_vecDrawnLines[iIndex][i].bSetLinkBlipCentre = true;
}
float x2 = m_vecDrawnLines[iIndex][i].linkblipcentre.x;
float y2 = m_vecDrawnLines[iIndex][i].linkblipcentre.y;
int alpha = 255;
if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY )
{
float t = gpGlobals->curtime - m_vecDrawnLines[iIndex][i].created_time;
if ( t < DRAWN_LINE_SOLID_TIME )
{
}
else if ( t < DRAWN_LINE_SOLID_TIME + DRAWN_LINE_FADE_TIME )
{
alpha = 255 - ( ( t - DRAWN_LINE_SOLID_TIME ) / DRAWN_LINE_FADE_TIME ) * 255.0f;
}
else
{
continue;
}
}
//Msg("drawing line from %f,%f to %f,%f\n", x, y, x2, y2);
vgui::surface()->DrawSetTexture( m_nWhiteTexture );
vgui::Vertex_t start, end;
Color drawColor = m_colorLine;
if ( m_bTeamColors )
{
C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iIndex );
if ( pPlayer )
{
drawColor = g_DrawPanel_TeamColors[ pPlayer->GetTeamNumber() ];
}
}
// draw main line
vgui::surface()->DrawSetColor( Color( drawColor.r(), drawColor.g(), drawColor.b(), alpha ) );
start.Init( Vector2D( x, y ), Vector2D( 0, 0 ) );
end.Init( Vector2D( x2, y2 ), Vector2D( 1, 1 ) );
SoftLine::DrawPolygonLine( start, end );
// draw translucent ones around it to give it some softness
vgui::surface()->DrawSetColor( Color( drawColor.r(), drawColor.g(), drawColor.b(), 0.5f * alpha ) );
start.Init( Vector2D( x - 0.50f, y - 0.50f ), Vector2D( 0, 0 ) );
end.Init( Vector2D( x2 - 0.50f, y2 - 0.50f ), Vector2D( 1, 1 ) );
SoftLine::DrawPolygonLine( start, end );
start.Init( Vector2D( x + 0.50f, y - 0.50f ), Vector2D( 0, 0 ) );
end.Init( Vector2D( x2 + 0.50f, y2 - 0.50f ), Vector2D( 1, 1 ) );
SoftLine::DrawPolygonLine( start, end );
start.Init( Vector2D( x - 0.50f, y + 0.50f ), Vector2D( 0, 0 ) );
end.Init( Vector2D( x2 - 0.50f, y2 + 0.50f ), Vector2D( 1, 1 ) );
SoftLine::DrawPolygonLine( start, end );
start.Init( Vector2D( x + 0.50f, y + 0.50f ), Vector2D( 0, 0 ) );
end.Init( Vector2D( x2 + 0.50f, y2 + 0.50f ), Vector2D( 1, 1 ) );
SoftLine::DrawPolygonLine( start, end );
}
}
}
}
}
void CDrawingPanel::OnMousePressed( vgui::MouseCode code )
{
if ( code != MOUSE_LEFT )
return;
SendMapLine( m_iMouseX, m_iMouseY, true );
m_bDrawingLines = true;
}
void CDrawingPanel::OnMouseReleased( vgui::MouseCode code )
{
if ( code != MOUSE_LEFT )
return;
m_bDrawingLines = false;
}
void CDrawingPanel::OnCursorExited()
{
//Msg("CDrawingPanel::OnCursorExited\n");
m_bDrawingLines = false;
}
void CDrawingPanel::OnThink()
{
if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY )
{
// clean up any segments that have faded out
for ( int iIndex = 0; iIndex < ARRAYSIZE( m_vecDrawnLines ); iIndex++ )
{
for ( int i = m_vecDrawnLines[iIndex].Count() - 1; i >= 0; i-- )
{
if ( gpGlobals->curtime - m_vecDrawnLines[iIndex][i].created_time > DRAWN_LINE_SOLID_TIME + DRAWN_LINE_FADE_TIME )
{
m_vecDrawnLines[iIndex].Remove( i );
}
}
}
}
}
void CDrawingPanel::OnCursorMoved( int x, int y )
{
//Msg("CDrawingPanel::OnCursorMoved %d,%d\n", x, y);
m_iMouseX = x;
m_iMouseY = y;
const float flLineInterval = 1.f / 60.f;
if ( m_bDrawingLines && gpGlobals->curtime >= m_fLastMapLine + flLineInterval )
{
SendMapLine( x, y, false );
}
}
void CDrawingPanel::SendMapLine( int x, int y, bool bInitial )
{
if ( engine->IsPlayingDemo() )
return;
int iIndex = GetLocalPlayerIndex();
int nMaxLines = 750; // 12.5 seconds of drawing at 60fps
if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY )
{
nMaxLines = 120; // 2 seconds of drawing at 60fps
}
// Stop adding lines after this much
if ( m_vecDrawnLines[iIndex].Count() >= nMaxLines )
return;
int linetype = bInitial ? 0 : 1;
m_fLastMapLine = gpGlobals->curtime;
// short circuit add it to your own list
MapLine line;
line.worldpos.x = x;
line.worldpos.y = y;
line.created_time = gpGlobals->curtime;
if ( linetype == 1 ) // links to a previous
{
line.bLink = true;
}
m_vecDrawnLines[iIndex].AddToTail( line );
if ( m_iPanelType == DRAWING_PANEL_TYPE_MATCH_SUMMARY )
{
// notify the server of this!
KeyValues *kv = new KeyValues( "cl_drawline" );
kv->SetInt( "panel", m_iPanelType );
kv->SetInt( "line", linetype );
kv->SetFloat( "x", (float)x / (float)GetWide() );
kv->SetFloat( "y", (float)y / (float)GetTall() );
engine->ServerCmdKeyValues( kv );
}
}
void CDrawingPanel::ClearLines( int iIndex )
{
m_vecDrawnLines[iIndex].Purge();
}
void CDrawingPanel::ClearAllLines()
{
for ( int iIndex = 0; iIndex < ARRAYSIZE( m_vecDrawnLines ); iIndex++ )
{
m_vecDrawnLines[iIndex].Purge();
}
}
void CDrawingPanel::FireGameEvent( IGameEvent *event )
{
if ( FStrEq( event->GetName(), "cl_drawline" ) )
{
int iIndex = event->GetInt( "player" );
// if this is NOT the local player (we've already stored our own data)
if ( ( iIndex != GetLocalPlayerIndex() ) || engine->IsPlayingDemo() )
{
// If a player is muted for voice, also mute them for lines because jerks gonna jerk.
if ( cl_mute_all_comms.GetBool() && ( iIndex != 0 ) )
{
if ( GetClientVoiceMgr() && GetClientVoiceMgr()->IsPlayerBlocked( iIndex ) )
{
ClearLines( iIndex );
return;
}
}
int iPanelType = event->GetInt( "panel" );
// if this message is about our panel type
if ( iPanelType == m_iPanelType )
{
int iLineType = event->GetInt( "line" );
float x = event->GetFloat( "x" );
float y = event->GetFloat( "y" );
MapLine line;
line.worldpos.x = (int)( x * GetWide() );
line.worldpos.y = (int)( y * GetTall() );
line.created_time = gpGlobals->curtime;
if ( iLineType == 1 ) // links to a previous
{
line.bLink = true;
}
m_vecDrawnLines[iIndex].AddToTail( line );
}
}
}
}
+84
View File
@@ -0,0 +1,84 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DRAWING_PANEL_H
#define DRAWING_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Panel.h>
#define DRAWN_LINE_SOLID_TIME 15.0f
#define DRAWN_LINE_FADE_TIME 3.0f
class MapLine
{
public:
MapLine()
{
worldpos.Init( 0, 0 );
linkpos.Init( 0, 0 );
created_time = 0;
bSetLinkBlipCentre = false;
bSetBlipCentre = false;
blipcentre.Init( 0, 0 );
linkblipcentre.Init( 0, 0 );
bLink = false;
}
Vector2D worldpos; // blip in world space
Vector2D blipcentre; // blip in map texture space
Vector2D linkpos; // link blip in world space
Vector2D linkblipcentre; // link blip in map texture space
bool bLink;
bool bSetBlipCentre; // have we calculated the blip in map texture space yet?
bool bSetLinkBlipCentre; // have we calculated the link blip in map texture space yet?
float created_time;
};
class CDrawingPanel : public vgui::Panel, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CDrawingPanel, vgui::Panel );
public:
CDrawingPanel( Panel *parent, const char *name );
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
void SendMapLine( int x, int y, bool bInitial );
virtual void OnMouseReleased( vgui::MouseCode code );
virtual void OnMousePressed( vgui::MouseCode code );
virtual void OnCursorExited();
virtual void OnCursorMoved( int x, int y );
virtual void Paint();
virtual void OnThink();
virtual void SetVisible( bool bState ) OVERRIDE;
void ClearLines( int iIndex );
void ClearAllLines();
const CUtlVector<MapLine>& GetLines( int iIndex ) const { return m_vecDrawnLines[iIndex]; }
void SetType( int iPanelType ){ m_iPanelType = iPanelType; }
virtual void FireGameEvent( IGameEvent *event );
private:
void ReadColor( const char* pszToken, Color& color );
bool m_bDrawingLines;
float m_fLastMapLine;
int m_iMouseX, m_iMouseY;
int m_nWhiteTexture;
Color m_colorLine;
CUtlVector<MapLine> m_vecDrawnLines[MAX_PLAYERS+1];
int m_iPanelType;
bool m_bTeamColors;
};
#endif // DRAWING_PANEL_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,267 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DYNAMIC_RECIPE_SUBPANEL_H
#define DYNAMIC_RECIPE_SUBPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "backpack_panel.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "tf_gcmessages.h"
#include "econ_gcmessages.h"
#include "tf_imagepanel.h"
#include "tf_controls.h"
#include "item_selection_panel.h"
#include "econ_dynamic_recipe.h"
class CImageButton;
#define DYNAMIC_RECIPE_INPUT_ROWS 4
#define DYNAMIC_RECIPE_INPUT_COLS 3
#define DYNAMIC_RECIPE_INPUT_COUNT ( DYNAMIC_RECIPE_INPUT_ROWS * DYNAMIC_RECIPE_INPUT_COLS )
#define DYNAMIC_RECIPE_OUTPUT_ROWS 4
#define DYNAMIC_RECIPE_OUTPUT_COLS 3
#define DYNAMIC_RECIPE_OUTPUT_COUNT ( DYNAMIC_RECIPE_OUTPUT_ROWS * DYNAMIC_RECIPE_OUTPUT_COLS )
#define DYNAMIC_RECIPE_BACKPACK_ROWS 4
#define DYNAMIC_RECIPE_BACKPACK_COLS 4
#define DYNAMIC_RECIPE_PACKPACK_COUNT_PER_PAGE ( DYNAMIC_RECIPE_BACKPACK_ROWS * DYNAMIC_RECIPE_BACKPACK_COLS )
class CRecipeComponentItemModelPanel;
class CRecipeComponentItemModelPanel : public CItemModelPanel
{
public:
DECLARE_CLASS_SIMPLE( CRecipeComponentItemModelPanel, CItemModelPanel );
CRecipeComponentItemModelPanel( vgui::Panel *parent, const char *name );
void AddRecipe( itemid_t nRecipe );
virtual void DeleteRecipes();
virtual void SetItem( const CEconItemView *pItem ) OVERRIDE;
void SetRecipeItem( itemid_t nRecipeItem, int nPageNumber );
void AddDefaultItem( CEconItemView *pItem );
CEconItemView* GetRecipeItem( int nPageNumber ) const;
itemid_t GetRecipeIndex( int nPageNumber ) const;
bool IsSlotAvailable( int nPageNumber );
CEconItemView* GetDefaultItem() const { return m_nPageNumber < m_vecDefaultItems.Count() ? m_vecDefaultItems[ m_nPageNumber ] : NULL; }
void UpdateDisplayItem();
void SetPageNumber( int nPageNumber );
int GetPageNumber() const { return m_nPageNumber; }
protected:
struct RecipeItem_t
{
itemid_t m_nRecipeIndex;
CEconItemView* m_pRecipeItem;
};
void UpdateRecipeItem( RecipeItem_t* pRecipeItem );
virtual void SetBlankState();
CUtlVector< CEconItemView* > m_vecDefaultItems;
CUtlVector< RecipeItem_t > m_vecRecipes;
int m_nPageNumber;
};
class CInputPanelItemModelPanel : public CRecipeComponentItemModelPanel
{
public:
CInputPanelItemModelPanel( vgui::Panel *parent, const char *name, const CEconItemView* pDynamicRecipeItem )
: CRecipeComponentItemModelPanel( parent, name )
, m_pDynamicRecipeItem( pDynamicRecipeItem )
{}
virtual void DeleteRecipes();
void AddComponentInfo( const CEconItemAttributeDefinition *pComponentAttrib );
bool MatchesAttribCriteria( itemid_t itemID ) const;
bool MatchesAttribCriteria( itemid_t itemID, int nPageNumber ) const;
const CEconItemAttributeDefinition * GetAttrib( int nPageNumber ) const;
void SetDynamicRecipeItem( const CEconItemView* pDynamicRecipeItem ) { m_pDynamicRecipeItem = pDynamicRecipeItem; }
protected:
virtual void SetBlankState() OVERRIDE;
private:
CUtlVector< const CEconItemAttributeDefinition* > m_vecAttrDef;
const CEconItemView* m_pDynamicRecipeItem;
};
//-----------------------------------------------------------------------------
// An inventory screen that handles displaying the crafting screen
//-----------------------------------------------------------------------------
class CDynamicRecipePanel : public CBackpackPanel
{
DECLARE_CLASS_SIMPLE( CDynamicRecipePanel, CBackpackPanel );
public:
#ifdef STAGING_ONLY
void Debug_GiveRequiredInputs() const;
CExButton *m_pDevGiveInputsButton;
#endif
CDynamicRecipePanel( vgui::Panel *parent, const char *panelName, CEconItemView* pRecipeItem );
~CDynamicRecipePanel( void );
void SetNewRecipe( CEconItemView* pNewRecipeItem );
void ConsumeItem( );
void InitItemPanels();
virtual const char *GetResFile( void ) { return "Resource/UI/DynamicRecipePanel.res"; }
virtual void ApplySchemeSettings( vgui::IScheme *pScheme ) OVERRIDE;
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
virtual void PerformLayout( void ) OVERRIDE;
virtual void OnCommand( const char *command ) OVERRIDE;
virtual void OnKeyCodePressed( vgui::KeyCode code ) OVERRIDE;
void OnButtonChecked( KeyValues *pData ) OVERRIDE;
virtual void OpenContextMenu() OVERRIDE {}
virtual int GetNumItemPanels( void ) OVERRIDE;
virtual void AddNewItemPanel( int iPanelIndex ) OVERRIDE;
void Craft();
virtual void OnTick( void ) OVERRIDE;
virtual void OnShowPanel( bool bVisible, bool bReturningFromArmory ) OVERRIDE;
void OnCraftResponse( itemid_t nNewToolID, EGCMsgResponse eResponse );
private:
bool IsInputPanel( int iPanelIndex ) const;
bool IsOutputPanel( int iPanelIndex) const;
bool IsBackpackPanel( int iPanelIndex) const;
bool IsInvPanelOnThisPage( unsigned nIndex ) const;
int GetNumBackpackPanelsPerPage() const { return DYNAMIC_RECIPE_BACKPACK_ROWS * DYNAMIC_RECIPE_BACKPACK_COLS; }
virtual int GetNumPages() OVERRIDE;
virtual void SetCurrentPage( int nNewPage ) OVERRIDE;
int GetFirstBackpackIndex() const { return DYNAMIC_RECIPE_INPUT_COUNT + DYNAMIC_RECIPE_OUTPUT_COUNT; }
void SetCurrentInputPage( int nNewPage );
int GetNumInputPages() const;
int GetNumInputPanelsPerPage() const { return DYNAMIC_RECIPE_INPUT_COUNT; }
int GetNumOutputPage() const;
int GetNumOutputPanelsPerPage() const { return DYNAMIC_RECIPE_OUTPUT_COUNT; }
class CRecipeComponentAttributeCounter : public CEconItemSpecificAttributeIterator
{
public:
CRecipeComponentAttributeCounter()
: m_nInputCount( 0 )
{}
~CRecipeComponentAttributeCounter() { Reset(); }
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_DynamicRecipeComponent& value ) OVERRIDE;
int GetInputCount() const { return m_nInputCount; }
int GetOutputCount() const { return m_vecOutputItems.Count(); }
CEconItemView* GetOutputItem( int i );
CEconItemView* GetInputItem( int i );
const CEconItemAttributeDefinition* GetInputAttrib( int i );
void Reset();
private:
struct InputComponent_t
{
CEconItemView m_ItemView;
const CEconItemAttributeDefinition* m_pAttrib;
};
typedef CUtlVector< CCopyableUtlVector<InputComponent_t> > InputComponentVec;
static int LeastCommonInputSortFunc( const CCopyableUtlVector<InputComponent_t> *p1, const CCopyableUtlVector<InputComponent_t> *p2 );
InputComponent_t* GetInputComponent( int i );
InputComponentVec m_vecInputItems;
CUtlVector< CEconItemView > m_vecOutputItems;
CUtlVector< CEconItem* > m_vecTempEconItems;
int m_nInputCount;
};
class CDynamicRecipeItemMatchFind : public CEconItemSpecificAttributeIterator
{
public:
CDynamicRecipeItemMatchFind( const CEconItemView* pSourceItem, const CEconItemView* pItemTomatch )
: m_bMatchesAny( false )
, m_pSourceItem( pSourceItem )
, m_pItemToMatch( pItemTomatch )
{}
virtual bool OnIterateAttributeValue( const CEconItemAttributeDefinition *pAttrDef, const CAttribute_DynamicRecipeComponent& value ) OVERRIDE;
bool MatchesAnyAttributes() const { return m_bMatchesAny; }
private:
const CEconItemView* m_pSourceItem;
const CEconItemView* m_pItemToMatch;
bool m_bMatchesAny;
};
CEconItemView* m_pDynamicRecipeItem;
CRecipeComponentAttributeCounter m_RecipeIterator;
bool AllRecipePanelsFilled( void );
bool CheckForUntradableItems( void );
bool WarnAboutPartialCompletion( void );
void FindPossibleBackpackItems();
virtual void PositionItemPanel( CItemModelPanel *pPanel, int iIndex );
void PopulatePanelsForCurrentPage();
virtual void UpdateModelPanels( void );
virtual void SetBorderForItem( CItemModelPanel *pItemPanel, bool bMouseOver );
void SetRecipeComponentIntoPanel( itemid_t nSrcRecipeIndex, CRecipeComponentItemModelPanel* pSrcPanel, int nSrcPage, CRecipeComponentItemModelPanel* pDstPanel, int nDstPage );
bool InputPanelCanAcceptItem( CItemModelPanel* pPanel, itemid_t nItemID );
CTFTextToolTip *m_pToolTip;
vgui::EditablePanel *m_pToolTipEmbeddedPanel;
CExButton *m_pRecipeCraftButton;
CExLabel *m_pNoMatchesLabel;
CExLabel *m_pUntradableOutputsLabel;
CExLabel *m_pInputsLabel;
CExLabel *m_pOutputsLabel;
vgui::Label *m_pCurInputPageLabel;
CExButton *m_pNextInputPageButton;
CExButton *m_pPrevInputPageButton;
CItemModelPanel *m_pMouseOverItemPanel;
vgui::CheckButton *m_pShowUntradableItemsCheckbox;
CUtlVector<CInputPanelItemModelPanel*> m_vecRecipeInputModelPanels;
CUtlVector<CRecipeComponentItemModelPanel*> m_vecBackpackModelPanels;
CUtlVector<CItemModelPanel*> m_vecRecipeOutputModelPanels;
vgui::EditablePanel *m_pRecipeContainer;
vgui::EditablePanel *m_pInventoryContainer;
unsigned m_nNumRecipeItems;
bool m_bAllRecipePanelsFilled;
bool m_bInputPanelsDirty;
bool m_bShowUntradable;
int m_nInputPage;
int m_nOutputPage;
float m_flAbortCraftingAt;
MESSAGE_FUNC_PTR( OnItemPanelMouseDoublePressed, "ItemPanelMouseDoublePressed", panel );
MESSAGE_FUNC_PTR( OnItemPanelEntered, "ItemPanelEntered", panel );
MESSAGE_FUNC_PTR( OnItemPanelExited, "ItemPanelExited", panel );
MESSAGE_FUNC( OnRecipeCompleted, "RecipeCompleted" );
virtual bool AllowDragging( CItemModelPanel *panel ) OVERRIDE;
virtual void StartDrag( int x, int y ) OVERRIDE;
virtual void StopDrag( bool bSucceeded ) OVERRIDE;
virtual bool CanDragTo( CItemModelPanel *pItemPanel, int iPanelIndex ) OVERRIDE;
virtual void HandleDragTo( CItemModelPanel *pItemPanel, int iPanelIndex ) OVERRIDE;
void ReturnRecipeItemToBackpack( itemid_t nItemID, CRecipeComponentItemModelPanel* pSrcPanel, int nSrcPage );
CPanelAnimationVarAliasType( int, m_iItemCraftingOffcenterX, "item_crafting_offcenter_x", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iOutputItemYPos, "output_item_ypos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iInventoryXPos, "inventory_xpos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iInventoryYPos, "inventory_ypos", "0", "proportional_int" );
friend void ConfirmDestroyItems( bool bConfirmed, void* pContext );
};
#endif // DYNAMIC_RECIPE_SUBPANEL_H
@@ -0,0 +1,88 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "halloween_offering_panel.h"
#include "cdll_client_int.h"
#include "ienginevgui.h"
#include "econ_item_tools.h"
#include "econ_ui.h"
#include <vgui_controls/AnimationController.h>
#include "clientmode_tf.h"
#include "softline.h"
#include "drawing_panel.h"
#include "tf_item_inventory.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CHalloweenOfferingPanel::CHalloweenOfferingPanel( vgui::Panel *parent, CItemModelPanelToolTip* pTooltip )
: BaseClass( parent, pTooltip )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CHalloweenOfferingPanel::~CHalloweenOfferingPanel( void )
{
}
//-----------------------------------------------------------------------------
void CHalloweenOfferingPanel::CreateSelectionPanel()
{
CHalloweenOfferingSelectionPanel *pSelectionPanel = new CHalloweenOfferingSelectionPanel( this );
m_hSelectionPanel = (CCollectionCraftingSelectionPanel*)pSelectionPanel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHalloweenOfferingPanel::OnCommand( const char *command )
{
if ( FStrEq( "envelopesend", command ) )
{
GCSDK::CProtoBufMsg<CMsgCraftHalloweenOffering> msg( k_EMsgGCCraftHalloweenOffering );
// Find the Garygoyle 'tool' item for this
static CSchemaItemDefHandle pItemDef_Gargoyle( "Activated Halloween Pass" );
Assert( pItemDef_Gargoyle );
if ( !pItemDef_Gargoyle )
return;
// Find out if the user owns this item or not and place in the proper bucket
CPlayerInventory *pLocalInv = TFInventoryManager()->GetLocalInventory();
if ( !pLocalInv )
return;
const CEconItemView *pRefItem = pLocalInv->FindFirstItembyItemDef( pItemDef_Gargoyle->GetDefinitionIndex() );
if ( !pRefItem )
return;
msg.Body().set_tool_id( pRefItem->GetItemID() );
FOR_EACH_VEC( m_vecItemPanels, i )
{
if ( m_vecItemPanels[ i ]->GetItem() == NULL )
return;
msg.Body().add_item_id( m_vecItemPanels[ i ]->GetItem()->GetItemID() );
}
// Send if off
GCClientSystem()->BSendMessage( msg );
m_bWaitingForGCResponse = true;
m_nFoundItemID.Purge();
m_timerResponse.Start( 5.f );
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "CollectionCrafting_LetterSend" );
return;
}
BaseClass::OnCommand( command );
}
@@ -0,0 +1,54 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef HALLOWEEN_OFFERING_PANEL_H
#define HALLOWEEN_OFFERING_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "collection_crafting_panel.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CHalloweenOfferingSelectionPanel : public CCollectionCraftingSelectionPanel
{
DECLARE_CLASS_SIMPLE( CHalloweenOfferingSelectionPanel, CCollectionCraftingSelectionPanel );
public:
CHalloweenOfferingSelectionPanel( Panel *pParent ) : BaseClass( pParent ) {}
//-----------------------------------------------------------------------------
virtual const char *GetSelectionInvalidReason( const IEconItemInterface *pTestItem, const IEconItemInterface *pSourceItem ) const
{
return GetHalloweenOfferingInvalidReason( pTestItem, pSourceItem );
}
};
//-----------------------------------------------------------------------------
// A panel to let users choose 10 weapons to craft up within collections
//-----------------------------------------------------------------------------
class CHalloweenOfferingPanel : public CCollectionCraftingPanel
{
public:
DECLARE_CLASS_SIMPLE( CHalloweenOfferingPanel, CCollectionCraftingPanel );
CHalloweenOfferingPanel( vgui::Panel *parent, CItemModelPanelToolTip* pTooltip );
~CHalloweenOfferingPanel( void );
virtual const char *GetResFile( void ) { return "Resource/UI/econ/HalloweenOfferingDialog.res"; }
virtual void OnCommand( const char *command ) OVERRIDE;
virtual int GetInputItemCount() { return HALLOWEEN_OFFERING_ITEM_COUNT; }
protected:
virtual void CreateSelectionPanel();
};
#endif // HALLOWEEN_OFFERING_PANEL_H
+489
View File
@@ -0,0 +1,489 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "item_ad_panel.h"
#include "econ_item_system.h"
#include "item_model_panel.h"
#include "econ_store.h"
#include "econ_ui.h"
#include "store/store_panel.h"
#include "tf_controls.h"
#include "econ_item_description.h"
#include "vgui/IInput.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBaseAdPanel::CBaseAdPanel( Panel *parent, const char *panelName )
: BaseClass( parent, panelName )
{}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseAdPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
m_flPresentTime = inResourceData->GetFloat( "present_time", 10.f );
}
bool CBaseAdPanel::CheckForRequiredSteamComponents( const char* pszSteamRequried, const char* pszOverlayRequired )
{
// Make sure we've got the appropriate connections to Steam
if ( !steamapicontext || !steamapicontext->SteamUtils() )
{
OpenStoreStatusDialog( NULL, pszSteamRequried, true, false );
return false;
}
if ( !steamapicontext->SteamUtils()->IsOverlayEnabled() )
{
OpenStoreStatusDialog( NULL, pszOverlayRequired, true, false );
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CItemAdPanel::CItemAdPanel( Panel *parent, const char *panelName, item_definition_index_t itemDefIndex )
: BaseClass( parent, panelName )
, m_ItemDefIndex( itemDefIndex )
, m_bShowMarketButton( true )
{
SetDialogVariable( "price", "..." );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemAdPanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( GetItemDef()->GetAdResFile() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemAdPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
m_bShowMarketButton = inResourceData->GetBool( "show_market", true ); // Default to showing market
if ( !m_bShowMarketButton )
{
// Tick every second as we try to get our price from the store
vgui::ivgui()->AddTickSignal( GetVPanel(), 1000 );
}
const CTFItemDefinition* pItemDef = GetItemDef();
CItemModelPanel* pItemImage = FindControl< CItemModelPanel >( "ItemIcon" );
if ( pItemImage )
{
CEconItemView adItem;
adItem.Init( pItemDef->GetDefinitionIndex(), AE_UNIQUE, 1, 1 );
pItemImage->InvalidateLayout( true, true );
pItemImage->SetItem( &adItem );
KeyValuesAD modelpanelKV( "modelpanel_kv" );
KeyValues *itemKV = new KeyValues( "itemmodelpanel" );
itemKV->SetBool( "inventory_image_type", true );
itemKV->SetBool( "use_item_rendertarget", false );
itemKV->SetBool( "allow_rot", false );
modelpanelKV->AddSubKey( itemKV );
pItemImage->ApplySettings( modelpanelKV );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemAdPanel::PerformLayout()
{
BaseClass::PerformLayout();
const CTFItemDefinition* pItemDef = GetItemDef();
// Get the ad text for the item. If it's not there, juse use the description text.
SetDialogVariable( "item_name", g_pVGuiLocalize->Find( pItemDef->GetItemBaseName() ) );
const char* pszAdtext = pItemDef->GetAdTextToken() ? pItemDef->GetAdTextToken() : pItemDef->GetItemDesc();
CExScrollingEditablePanel* pScrollableItemText = FindControl< CExScrollingEditablePanel >( "ScrollableItemText", true );
if ( pszAdtext && pScrollableItemText )
{
pScrollableItemText->SetDialogVariable( "item_ad_text", g_pVGuiLocalize->Find( pszAdtext ) );
Label* pAdLabel = pScrollableItemText->FindControl< Label >( "ItemAdText", true );
if ( pAdLabel )
{
int nWide, nTall;
pAdLabel->GetContentSize( nWide, nTall );
pAdLabel->SetTall( nTall );
}
pScrollableItemText->InvalidateLayout( true );
}
CExButton* pBuyButton = FindControl< CExButton >( "BuyButton", true );
CExButton* pMarketButton = FindControl< CExButton >( "MarketButton", true );
if ( pBuyButton && pMarketButton )
{
pBuyButton->SetVisible( !m_bShowMarketButton );
pMarketButton->SetVisible( m_bShowMarketButton );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemAdPanel::OnTick()
{
const CTFItemDefinition* pItemDef = GetItemDef();
bool bStoreIsReady = EconUI()->GetStorePanel() && EconUI()->GetStorePanel()->GetPriceSheet() && EconUI()->GetStorePanel()->GetCart() && steamapicontext && steamapicontext->SteamUser() && pItemDef;
if ( bStoreIsReady )
{
// Get the price of the item
const ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency();
const econ_store_entry_t *pEntry = EconUI()->GetStorePanel()->GetPriceSheet()->GetEntry( pItemDef->GetDefinitionIndex() );
if ( pEntry )
{
item_price_t unPrice = pEntry->GetCurrentPrice( eCurrency );
// Set that price into the button
wchar_t wzLocalizedPrice[ kLocalizedPriceSizeInChararacters ];
MakeMoneyString( wzLocalizedPrice, ARRAYSIZE( wzLocalizedPrice ), unPrice, eCurrency );
SetDialogVariable( "price", wzLocalizedPrice );
// Don't need to tick anymore
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const CTFItemDefinition* CItemAdPanel::GetItemDef() const
{
return (CTFItemDefinition*)ItemSystem()->GetItemSchema()->GetItemDefinition( m_ItemDefIndex );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemAdPanel::OnCommand( const char *command )
{
if ( FStrEq( "purchase", command ) )
{
if ( !CheckForRequiredSteamComponents( "#StoreUpdate_SteamRequired", "#MMenu_OverlayRequired" ) )
return;
const CTFItemDefinition* pItemDef = GetItemDef();
if ( pItemDef )
{
if ( EconUI()->GetStorePanel() && EconUI()->GetStorePanel()->GetPriceSheet() && EconUI()->GetStorePanel()->GetCart() && steamapicontext && steamapicontext->SteamUser() )
{
// Add a the item to the users cart and checkout
EconUI()->GetStorePanel()->GetCart()->EmptyCart();
AddItemToCartHelper( NULL, pItemDef->GetDefinitionIndex(), kCartItem_Purchase );
EconUI()->GetStorePanel()->InitiateCheckout( true );
}
}
}
else if ( FStrEq( "market", command ) )
{
if ( !CheckForRequiredSteamComponents( "#StoreUpdate_SteamRequired", "#MMenu_OverlayRequired" ) )
return;
const CTFItemDefinition* pItemDef = GetItemDef();
if ( pItemDef && steamapicontext && steamapicontext->SteamFriends() )
{
const char *pszPrefix = "";
if ( GetUniverse() == k_EUniverseBeta )
{
pszPrefix = "beta.";
}
static char pszItemName[256];
g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find ( pItemDef->GetItemBaseName() ) , pszItemName, sizeof(pszItemName) );
char szURL[512];
V_snprintf( szURL, sizeof(szURL), "http://%ssteamcommunity.com/market/listings/%d/%s", pszPrefix, engine->GetAppID(), pszItemName );
steamapicontext->SteamFriends()->ActivateGameOverlayToWebPage( szURL );
}
}
}
DECLARE_BUILD_FACTORY( CCyclingAdContainerPanel );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCyclingAdContainerPanel::CCyclingAdContainerPanel( Panel *parent, const char *panelName )
: BaseClass( parent, panelName )
, m_pAdsContainer( NULL )
, m_pKVItems( NULL )
, m_nCurrentIndex( 0 )
, m_nXPos( 0 )
, m_nTargetIndex( 0 )
, m_nTransitionStartOffsetX( 0 )
, m_bTransitionRight( true )
, m_bSettingsApplied( false )
, m_bNeedsToCreatePanels( false )
{
m_pAdsContainer = new EditablePanel( this, "AdsContainer" );
m_pFadePanel = new EditablePanel( this, "FadeTransition" );
m_pNextButton = new CExButton( this, "NextButton", ">", this, "next" );
m_pPrevButton = new CExButton( this, "PrevButton", "<", this, "prev" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCyclingAdContainerPanel::~CCyclingAdContainerPanel()
{
if ( m_pKVItems )
{
m_pKVItems->deleteThis();
m_pKVItems = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCyclingAdContainerPanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/econ/CyclingAdContainer.res" );
m_bSettingsApplied = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCyclingAdContainerPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
KeyValues* pKVItems = inResourceData->FindKey( "items" );
if ( pKVItems )
{
SetItemKVs( pKVItems );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCyclingAdContainerPanel::CreatePanels()
{
if ( ItemSystem()->GetItemSchema()->GetVersion() == 0 )
return;
m_vecPossibleAds.Purge();
FOR_EACH_TRUE_SUBKEY( m_pKVItems, pKVItem )
{
const char* pszItemName = pKVItem->GetString( "item" );
const CEconItemDefinition *pDef = ItemSystem()->GetItemSchema()->GetItemDefinitionByName( pszItemName );
if ( pDef )
{
AdData_t& adData = m_vecPossibleAds[ m_vecPossibleAds.AddToTail() ];
adData.m_pAdPanel = new CItemAdPanel( m_pAdsContainer, "ad", pDef->GetDefinitionIndex() );
adData.m_pAdPanel->InvalidateLayout( true, true ); // Default settings
adData.m_pAdPanel->ApplySettings( pKVItem );
adData.m_pAdPanel->InvalidateLayout();
}
else
{
AssertMsg( 0, "Invalid item def '%s'!", pszItemName );
}
}
m_bNeedsToCreatePanels = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCyclingAdContainerPanel::PerformLayout()
{
BaseClass::PerformLayout();
PresentIndex( 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCyclingAdContainerPanel::OnThink()
{
BaseClass::OnThink();
if ( m_bNeedsToCreatePanels && m_bSettingsApplied )
{
CreatePanels();
PresentIndex( 0 );
}
UpdateAdPanelPositions();
// See if it's time to auto-cycle to the next ad
if ( m_ShowTimer.HasStarted() && m_ShowTimer.IsElapsed() && m_vecPossibleAds.Count() > 1 )
{
m_ShowTimer.Invalidate();
PresentIndex( m_nTargetIndex + 1 );
}
int nMouseX, nMouseY;
vgui::input()->GetCursorPos( nMouseX, nMouseY );
bool bControlsVisible = IsWithin( nMouseX, nMouseY ) && m_vecPossibleAds.Count() > 1;
m_pPrevButton->SetVisible( bControlsVisible );
m_pNextButton->SetVisible( bControlsVisible );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCyclingAdContainerPanel::SetItemKVs( KeyValues* pKVItems )
{
if ( pKVItems )
{
if ( m_pKVItems )
{
m_pKVItems->deleteThis();
m_pKVItems = NULL;
}
m_pKVItems = pKVItems->MakeCopy();
}
m_bNeedsToCreatePanels = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCyclingAdContainerPanel::OnCommand( const char *command )
{
if ( FStrEq( "next", command ) )
{
PresentIndex( m_nTargetIndex + 1 );
}
else if ( FStrEq( "prev", command ) )
{
PresentIndex( m_nTargetIndex - 1 );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCyclingAdContainerPanel::PresentIndex( int nIndex )
{
if ( m_vecPossibleAds.IsEmpty() )
return;
if ( m_nCurrentIndex == nIndex )
return;
// Figure out which way we want to ransition
m_bTransitionRight = nIndex > m_nCurrentIndex;
// Wrap if needed
if ( nIndex >= m_vecPossibleAds.Count() )
{
nIndex = 0;
}
else if ( nIndex < 0 )
{
nIndex = m_vecPossibleAds.Count() - 1;
}
m_nTargetIndex = nIndex;
// If they click more times while transitioning out, just change the target. If we're
// into transitioning in to the next panel, then we need to start the whole thing over.
if ( !IsTransitioningOut() )
{
m_nTransitionStartOffsetX = m_nXPos;
float flTransitionTime = 1.f;
m_TransitionTimer.Start( flTransitionTime );
m_ShowTimer.Start( flTransitionTime + m_vecPossibleAds[ m_nCurrentIndex ].m_pAdPanel->GetPresentTime() );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCyclingAdContainerPanel::UpdateAdPanelPositions()
{
// Figure out how far along a transition we are
float flPercent = Clamp( m_TransitionTimer.GetElapsedTime() / m_TransitionTimer.GetCountdownDuration(), 0.f, 1.f );
flPercent = Gain( flPercent, 0.8f );
// At a certain point, we're no longer transitioning out the old -- we're transitioning in the new
const float flTransitionCutOff = m_TransitionTimer.GetCountdownDuration() / 2.f;
bool bTransitionOut = flPercent < flTransitionCutOff;
int nStartX = 0;
int nTargetX = 0;
float flFadeAmount = 0.f;
if ( bTransitionOut )
{
nStartX = m_nTransitionStartOffsetX;
nTargetX = m_bTransitionRight ? -100 : 100;
flFadeAmount = RemapValClamped( flPercent, 0.f, flTransitionCutOff * 0.75f, 0.f, 255.f );
}
else
{
// Once we've passed the middle, show the target
m_nCurrentIndex = m_nTargetIndex;
nStartX = m_bTransitionRight ? 100 : -100;
nTargetX = 0;
flFadeAmount = RemapValClamped( flPercent, flTransitionCutOff * 1.25f, 1.f, 255.f, 0.f );
}
// Alpha fades up entirely near the middle to cover the swap
m_pFadePanel->SetAlpha( flFadeAmount );
m_nXPos = RemapVal( flPercent, 0.f, 1.f, nStartX, nTargetX );
FOR_EACH_VEC( m_vecPossibleAds, i )
{
m_vecPossibleAds[i].m_pAdPanel->SetPos( m_nXPos, m_vecPossibleAds[i].m_pAdPanel->GetYPos() );
m_vecPossibleAds[i].m_pAdPanel->SetVisible( i == m_nCurrentIndex );
}
}
float CCyclingAdContainerPanel::GetTransitionProgress() const
{
float flPercent = Clamp( m_TransitionTimer.GetElapsedTime() / m_TransitionTimer.GetCountdownDuration(), 0.f, 1.f );
return Gain( flPercent, 0.8f );
}
bool CCyclingAdContainerPanel::IsTransitioningOut() const
{
const float flTransitionCutOff = m_TransitionTimer.GetCountdownDuration() / 2.f;
return GetTransitionProgress() < flTransitionCutOff;
}
+113
View File
@@ -0,0 +1,113 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ITEM_AD_PANEL_H
#define ITEM_AD_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/VGUI.h>
#include "vgui_controls/EditablePanel.h"
using namespace vgui;
class CExButton;
class CBaseAdPanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CBaseAdPanel, EditablePanel );
public:
CBaseAdPanel( Panel *parent, const char *panelName );
virtual ~CBaseAdPanel() {}
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
float GetPresentTime() const { return m_flPresentTime; }
static bool CheckForRequiredSteamComponents( const char* pszSteamRequried, const char* pszOverlayRequired );
private:
float m_flPresentTime;
};
class CItemAdPanel : public CBaseAdPanel
{
DECLARE_CLASS_SIMPLE( CItemAdPanel, CBaseAdPanel );
public:
CItemAdPanel( Panel *parent, const char *panelName, item_definition_index_t itemDefIndex );
virtual ~CItemAdPanel() {}
virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE;
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
virtual void PerformLayout() OVERRIDE;
virtual void OnTick() OVERRIDE;
virtual void OnCommand( const char *command ) OVERRIDE;
private:
const CTFItemDefinition* GetItemDef() const;
bool m_bShowMarketButton;
item_definition_index_t m_ItemDefIndex;
};
class CCyclingAdContainerPanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CCyclingAdContainerPanel, EditablePanel );
public:
CCyclingAdContainerPanel( Panel *parent, const char *panelName );
virtual ~CCyclingAdContainerPanel();
virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE;
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
virtual void PerformLayout() OVERRIDE;
virtual void OnCommand( const char *command ) OVERRIDE;
virtual void OnThink() OVERRIDE;
void SetItemKVs( KeyValues* pKVItems );
private:
void CreatePanels();
void PresentIndex( int nIndex );
void UpdateAdPanelPositions();
float GetTransitionProgress() const;
bool IsTransitioningOut() const;
EditablePanel* m_pAdsContainer;
EditablePanel* m_pFadePanel;
CExButton* m_pPrevButton;
CExButton* m_pNextButton;
bool m_bNeedsToCreatePanels;
bool m_bSettingsApplied;
struct AdData_t
{
~AdData_t()
{
delete m_pAdPanel;
}
CBaseAdPanel* m_pAdPanel;
KeyValues* m_pSettingsKVs;
};
KeyValues *m_pKVItems;
CUtlVector< AdData_t > m_vecPossibleAds;
int m_nTargetIndex;
int m_nCurrentIndex;
int m_nTransitionStartOffsetX;
bool m_bTransitionRight;
int m_nXPos;
RealTimeCountdownTimer m_TransitionTimer;
RealTimeCountdownTimer m_ShowTimer;
};
#endif // ITEM_AD_PANEL_H
+792
View File
@@ -0,0 +1,792 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "vgui_controls/EditablePanel.h"
#include "tf_controls.h"
#include "tf_gamerules.h"
#include "tf_shareddefs.h"
#include "vgui/ISurface.h"
#include "c_tf_player.h"
#include "gamestringpool.h"
#include "iclientmode.h"
#include "tf_item_inventory.h"
#include "ienginevgui.h"
#include <vgui/ILocalize.h>
#include "vgui_controls/TextImage.h"
#include "vgui_controls/ComboBox.h"
#include "vgui/IInput.h"
#include "item_model_panel.h"
#include "hudelement.h"
#include "item_quickswitch.h"
#include "econ_gcmessages.h"
#include "gc_clientsystem.h"
#include "loadout_preset_panel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#define MAX_QUICKSWITCH_SLOTS 11
extern ConVar tf_respawn_on_loadoutchanges;
extern const char *g_szEquipSlotHeader[CLASS_LOADOUT_POSITION_COUNT];
int g_SlotsToLoadoutSlotsPerClass[TF_LAST_NORMAL_CLASS][MAX_QUICKSWITCH_SLOTS] =
{
//TF_CLASS_UNDEFINED = 0,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
// TF_CLASS_SCOUT,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_PRIMARY,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
// TF_CLASS_SNIPER,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_PRIMARY,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
// TF_CLASS_SOLDIER,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_PRIMARY,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
// TF_CLASS_DEMOMAN,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_PRIMARY,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
// TF_CLASS_MEDIC,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_PRIMARY,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
// TF_CLASS_HEAVYWEAPONS,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_PRIMARY,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
// TF_CLASS_PYRO,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_PRIMARY,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
#ifdef STAGING_ONLY
// TF_CLASS_SPY,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_PDA,
LOADOUT_POSITION_PDA2,
LOADOUT_POSITION_PDA3,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
},
#else
// TF_CLASS_SPY,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_PDA,
LOADOUT_POSITION_PDA2,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
#endif
// TF_CLASS_ENGINEER,
{
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_PRIMARY,
LOADOUT_POSITION_SECONDARY,
LOADOUT_POSITION_MELEE,
LOADOUT_POSITION_PDA,
LOADOUT_POSITION_PDA2,
LOADOUT_POSITION_HEAD,
LOADOUT_POSITION_MISC,
LOADOUT_POSITION_ACTION,
LOADOUT_POSITION_INVALID,
LOADOUT_POSITION_INVALID,
},
};
DECLARE_HUDELEMENT( CItemQuickSwitchPanel );
void IN_QuickSwitchDown( const CCommand &args )
{
// quickswitch disabled in training
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
return;
}
CItemQuickSwitchPanel *pQSPanel = GET_HUDELEMENT( CItemQuickSwitchPanel );
if ( pQSPanel )
{
pQSPanel->OpenQS();
}
}
void IN_QuickSwitchUp( const CCommand &args )
{
// quickswitch disabled in training
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
return;
}
CItemQuickSwitchPanel *pQSPanel = GET_HUDELEMENT( CItemQuickSwitchPanel );
if ( pQSPanel )
{
pQSPanel->CloseQS();
}
}
static ConCommand openquickswitch( "+quickswitch", IN_QuickSwitchDown );
static ConCommand closequickswitch( "-quickswitch", IN_QuickSwitchUp );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CItemQuickSwitchPanel::CItemQuickSwitchPanel( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "ItemQuickSwitchPanel" )
{
Panel *pParent = g_pClientMode->GetViewport();
SetParent( pParent );
SetMouseInputEnabled( true );
SetKeyBoardInputEnabled( false );
m_pItemContainer = vgui::SETUP_PANEL( new vgui::EditablePanel( this, "itemcontainer" ) );
m_pItemContainerScroller = vgui::SETUP_PANEL( new vgui::ScrollableEditablePanel( this, m_pItemContainer, "itemcontainerscroller" ) );
m_pItemKV = NULL;
m_pWeaponLabel = NULL;
m_pEquipYourClassLabel = NULL;
m_pLoadoutPresetPanel = NULL;
m_iClass = TF_CLASS_UNDEFINED;
m_iSlot = 0;
SetVisible( false );
ListenForGameEvent( "inventory_updated" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CItemQuickSwitchPanel::~CItemQuickSwitchPanel()
{
if ( m_pItemKV )
{
m_pItemKV->deleteThis();
m_pItemKV = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CItemQuickSwitchPanel::IsValid( void )
{
return ( m_iClass >= TF_FIRST_NORMAL_CLASS && m_iClass < TF_LAST_NORMAL_CLASS ) &&
( m_iSlot > LOADOUT_POSITION_INVALID && m_iSlot < CLASS_LOADOUT_POSITION_COUNT );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CItemQuickSwitchPanel::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
{
if ( !IsVisible() )
return 1; // key not handled
if ( !down )
return 1; // key not handled
int iSlot = 0;
// convert slot1, slot2 etc to 1,2,3,4
if ( pszCurrentBinding && ( !Q_strncmp( pszCurrentBinding, "slot", 4 ) && Q_strlen( pszCurrentBinding ) > 4 ) )
{
const char *pszNum = pszCurrentBinding + 4;
iSlot = atoi( pszNum );
if ( ( iSlot < 1 ) || ( iSlot >= MAX_QUICKSWITCH_SLOTS ) )
{
// invalid bind
iSlot = 0;
}
}
if ( iSlot > 0 )
{
int iLoadoutSlot = g_SlotsToLoadoutSlotsPerClass[m_iClass][iSlot];
if ( iLoadoutSlot != LOADOUT_POSITION_INVALID )
{
// is it the slot we're already viewing?
if ( iLoadoutSlot != m_iSlot )
{
m_iSlot = iLoadoutSlot;
if ( IsValid() )
{
UpdateModelPanels();
InvalidateLayout( true );
}
}
}
else
{
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( pLocalPlayer )
{
pLocalPlayer->EmitSound( "Player.DenyWeaponSelection" );
}
}
return 0;
}
return 1; // key not handled
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CItemQuickSwitchPanel::CalculateClassAndSlot( void )
{
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pPlayer )
return false;
// Get the current class
m_iClass = pPlayer->GetPlayerClass()->GetClassIndex();
if ( m_iClass < TF_FIRST_NORMAL_CLASS || m_iClass >= TF_LAST_NORMAL_CLASS )
return false;
if ( m_pLoadoutPresetPanel )
{
m_pLoadoutPresetPanel->SetClass( m_iClass );
}
if ( pPlayer->IsAlive() )
{
// Get the current weapon slot
CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
if ( !pWpn )
return false;
m_iSlot = pWpn->GetAttributeContainer()->GetItem()->GetStaticData()->GetLoadoutSlot( m_iClass );
if ( m_iSlot == LOADOUT_POSITION_INVALID )
return false;
}
else
{
m_iClass = pPlayer->m_Shared.GetDesiredPlayerClassIndex();
m_iSlot = g_SlotsToLoadoutSlotsPerClass[m_iClass][1]; // use the first slot if we're dead
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::OpenQS( void )
{
if ( !CalculateClassAndSlot() )
return;
m_bLoadoutHasChanged = false;
UpdateModelPanels();
SetVisible( true );
RequestFocus();
MakePopup();
SetKeyBoardInputEnabled( false );
// Force layout now so that we can position the cursor properly
InvalidateLayout( true );
// It takes a few frames before this panel appears the first time, which means
// we need to delay until it appears before we can pop the mouse to the right spot.
vgui::ivgui()->AddTickSignal( GetVPanel() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::OnTick( void )
{
BaseClass::OnTick();
// Move the mouse cursor onto the first entry in the panel that's not our active weapon
if ( vgui::surface()->IsCursorVisible() )
{
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
int x,y,w,h;
if ( m_pItemPanels.Count() > 1 )
{
vgui::ipanel()->GetAbsPos( m_pItemPanels[1]->GetVPanel(), x, y );
m_pItemPanels[1]->GetSize( w, h );
}
else
{
vgui::ipanel()->GetAbsPos( GetVPanel(), x, y );
GetSize( w, h );
}
::input->SetFullscreenMousePos( x + (w * 0.5), y + (h * 0.5) );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::CloseQS( void )
{
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
SetVisible( false );
if ( m_bLoadoutHasChanged )
{
if ( tf_respawn_on_loadoutchanges.GetBool() )
{
// Tell the GC to tell server that we should respawn if we're in a respawn room
GCSDK::CGCMsg< GCSDK::MsgGCEmpty_t > msg( k_EMsgGCRespawnPostLoadoutChange );
GCClientSystem()->BSendMessage( msg );
}
// Send the preset panel a msg so it can save the change
CEconItemView *pCurItemData = TFInventoryManager()->GetItemInLoadoutForClass( m_iClass, m_iSlot );
if ( pCurItemData )
{
KeyValues *pLoadoutChangedMsg = new KeyValues( "LoadoutChanged" );
pLoadoutChangedMsg->SetInt( "slot", m_iSlot );
pLoadoutChangedMsg->SetUint64( "itemid", pCurItemData->GetItemID() );
PostMessage( m_pLoadoutPresetPanel, pLoadoutChangedMsg );
}
m_bLoadoutHasChanged = false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/ItemQuickSwitch.res" );
m_pWeaponLabel = dynamic_cast<vgui::Label*>( FindChildByName("ItemSlotLabel") );
m_pEquipYourClassLabel = dynamic_cast<vgui::Label*>( FindChildByName("EquipLabel") );
m_pNoItemsToEquipLabel = dynamic_cast<vgui::Label*>( FindChildByName("NoItemsLabel") );
m_pEquippedLabel = dynamic_cast<CExLabel*>( m_pItemContainer->FindChildByName("CurrentlyEquippedBackground") );
m_pLoadoutPresetPanel = dynamic_cast<CLoadoutPresetPanel*>( FindChildByName( "loadout_preset_panel" ) );
if ( m_pEquippedLabel )
{
m_pEquippedLabel->SetMouseInputEnabled( false );
}
if ( m_pLoadoutPresetPanel )
{
m_pLoadoutPresetPanel->EnableVerticalDisplay( true );
}
m_pItemContainerScroller->GetScrollbar()->SetAutohideButtons( true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
KeyValues *pItemKV = inResourceData->FindKey( "itemskv" );
if ( pItemKV )
{
if ( m_pItemKV )
{
m_pItemKV->deleteThis();
}
m_pItemKV = new KeyValues( "itemkv" );
pItemKV->CopySubkeys( m_pItemKV );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::PerformLayout( void )
{
BaseClass::PerformLayout();
if ( !IsValid() )
return;
// Need to lay these out before we start making item panels inside them
m_pItemContainer->InvalidateLayout( true );
m_pItemContainerScroller->InvalidateLayout( true );
// Position the item panels
for ( int i = 0; i < m_pItemPanels.Count(); i++ )
{
if ( m_pItemKV )
{
m_pItemPanels[i]->ApplySettings( m_pItemKV );
m_pItemPanels[i]->InvalidateLayout();
}
int iYDelta = m_pItemPanels[0]->GetTall() + m_iItemPanelYDelta;
// Once we've setup our first item, we know how large to make the container
if ( i == 0 )
{
m_pItemContainer->SetSize( m_pItemContainer->GetWide(), iYDelta * m_pItemPanels.Count() );
}
// Always indent the top one to make it look better.
m_pItemPanels[i]->SetPos( m_iItemPanelXPos, m_iItemPanelYDelta + (iYDelta * i) );
}
// Now that the container has been sized, tell the scroller to re-evaluate
m_pItemContainerScroller->InvalidateLayout();
m_pItemContainerScroller->GetScrollbar()->InvalidateLayout();
// Force the class label to layout & resize, so we can align our title
if ( m_pEquipYourClassLabel && m_pWeaponLabel )
{
m_pWeaponLabel->InvalidateLayout( true );
m_pWeaponLabel->SizeToContents();
int iXPos, iYPos;
m_pWeaponLabel->GetPos( iXPos, iYPos );
iXPos = ( GetWide() - m_pWeaponLabel->GetWide() ) * 0.5;
m_pWeaponLabel->SetPos( iXPos, m_pWeaponLabel->GetTall() );
m_pEquipYourClassLabel->SetPos( iXPos, iYPos - m_pEquipYourClassLabel->GetTall() );
}
// If it's visible, put the no items to equip at the bottom
if ( m_pNoItemsToEquipLabel->IsVisible() )
{
int iYDelta = 0;
if ( m_pItemPanels.Count() )
{
iYDelta = m_pItemPanels[0]->GetTall() + m_iItemPanelYDelta;
}
m_pNoItemsToEquipLabel->SetPos( m_iItemPanelXPos, m_iItemPanelYDelta + (iYDelta * (m_pItemPanels.Count()+1)) );
}
UpdateEquippedItem();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::UpdateEquippedItem( void )
{
if ( !m_pEquippedLabel )
return;
bool bEquipped = false;
CEconItemView *pCurItemData = TFInventoryManager()->GetItemInLoadoutForClass( m_iClass, m_iSlot );
if ( pCurItemData )
{
if ( pCurItemData->IsValid() )
{
for ( int i = 0; i < m_pItemPanels.Count(); i++ )
{
CEconItemView *pItem = m_pItemPanels[i]->GetItem();
if ( pItem && ( *pItem == *pCurItemData ) )
{
int x,y;
m_pItemPanels[i]->GetPos( x, y );
m_pEquippedLabel->SetPos( x + XRES(3), y + YRES(2) );
bEquipped = true;
}
}
}
else if ( !TFInventoryManager()->SlotContainsBaseItems( GEconItemSchema().GetEquipTypeFromClassIndex( m_iClass ), m_iSlot ) )
{
for ( int i = 0; i < m_pItemPanels.Count(); i++ )
{
CEconItemView *pItem = m_pItemPanels[i]->GetItem();
if ( !pItem )
{
int x,y;
m_pItemPanels[i]->GetPos( x, y );
m_pEquippedLabel->SetPos( x + XRES(3), y + YRES(2) );
bEquipped = true;
}
}
}
}
if ( m_pEquippedLabel->IsVisible() != bEquipped )
{
m_pEquippedLabel->SetVisible( bEquipped );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::UpdateModelPanels( void )
{
if ( !IsValid() )
return;
TFPlayerClassData_t *pData = GetPlayerClassData( m_iClass );
SetDialogVariable( "loadoutclass", g_pVGuiLocalize->Find( pData->m_szLocalizableName ) );
if ( m_pWeaponLabel )
{
m_pWeaponLabel->SetText( g_szEquipSlotHeader[m_iSlot] );
}
// What items can go in this slot?
extern equip_region_mask_t GenerateEquipRegionConflictMask( int iClass, int iUpToSlot, int iIgnoreSlot );
const equip_region_mask_t unUsedEquipRegionMask = GenerateEquipRegionConflictMask( m_iClass, m_iSlot, LOADOUT_POSITION_INVALID );
CEquippableItemsForSlotGenerator equippableItems( m_iClass, m_iSlot, unUsedEquipRegionMask, CEquippableItemsForSlotGenerator::kSlotGenerator_None );
int iButton = 0;
FOR_EACH_VEC( equippableItems.GetDisplayItems(), i )
{
// For quick-switch, only show items that are equippable and would show up as such in our regular
// loadout.
if ( equippableItems.GetDisplayItems()[i].m_eDisplayType == CEquippableItemsForSlotGenerator::kSlotDisplay_Normal )
{
SetButtonToItem( iButton++, equippableItems.GetDisplayItems()[i].m_pEconItemView );
}
}
if ( !TFInventoryManager()->SlotContainsBaseItems( GEconItemSchema().GetEquipTypeFromClassIndex( m_iClass ), m_iSlot ) )
{
SetButtonToItem( iButton++, NULL );
}
if ( m_pNoItemsToEquipLabel )
{
m_pNoItemsToEquipLabel->SetVisible( iButton == 0 );
}
// Delete excess items
for ( int i = m_pItemPanels.Count() - 1; i >= iButton; i-- )
{
m_pItemPanels[i]->MarkForDeletion();
m_pItemPanels.Remove( i );
}
InvalidateLayout();
// Move the scrollbar to the top
m_pItemContainerScroller->GetScrollbar()->SetValue( 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::SetButtonToItem( int iButton, CEconItemView *pItem )
{
CItemModelPanel *pItemPanel;
if ( iButton < m_pItemPanels.Count() )
{
pItemPanel = m_pItemPanels[iButton];
}
else
{
const char *pszCommand = VarArgs( "itempanel%d", iButton );
pItemPanel = new CItemModelPanel( m_pItemContainer, pszCommand );
if ( m_pItemKV )
{
pItemPanel->ApplySettings( m_pItemKV );
}
pItemPanel->MakeReadyForUse();
pItemPanel->SetActAsButton( true, true );
pItemPanel->SendPanelEnterExits( true );
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
pItemPanel->SetBorder( pScheme->GetBorder( "EconItemBorder" ) );
m_pItemPanels.AddToTail( pItemPanel );
}
pItemPanel->SetNoItemText( "#SelectNoItemSlot" );
pItemPanel->SetItem( pItem );
pItemPanel->AddActionSignalTarget( this );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::OnItemPanelEntered( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( pItemPanel )
{
pItemPanel->SetPaintBorderEnabled( true );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::OnItemPanelExited( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( pItemPanel )
{
pItemPanel->SetPaintBorderEnabled( false );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::OnIPMouseReleased( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( !pItemPanel )
return;
itemid_t iIndex = INVALID_ITEM_ID;
CEconItemView *pItemData = pItemPanel->GetItem();
if ( pItemData && pItemData->IsValid() )
{
iIndex = pItemData->GetItemID();
}
TFInventoryManager()->EquipItemInLoadout( m_iClass, m_iSlot, iIndex );
m_bLoadoutHasChanged = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::FireGameEvent( IGameEvent *event )
{
if ( !IsVisible() )
return;
const char * type = event->GetName();
if ( Q_strcmp( type, "inventory_updated" ) == 0 )
{
UpdateEquippedItem();
}
else
{
CHudElement::FireGameEvent( event );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemQuickSwitchPanel::OnItemPresetLoaded()
{
m_bLoadoutHasChanged = true;
}
+72
View File
@@ -0,0 +1,72 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef ITEM_QUICKSWITCH_H
#define ITEM_QUICKSWITCH_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/ScrollableEditablePanel.h"
class CLoadoutPresetPanel;
class CItemQuickSwitchPanel : public vgui::EditablePanel, public CHudElement
{
DECLARE_CLASS_SIMPLE( CItemQuickSwitchPanel, vgui::EditablePanel );
public:
CItemQuickSwitchPanel( const char *pElementName );
virtual ~CItemQuickSwitchPanel();
void OpenQS( void );
void CloseQS( void );
bool ShouldDraw( void ) { return IsVisible(); }
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void PerformLayout( void );
virtual void OnTick( void );
void UpdateEquippedItem( void );
bool CalculateClassAndSlot();
void UpdateModelPanels( void );
void SetButtonToItem( int iButton, CEconItemView *pItem );
bool IsValid( void );
virtual void FireGameEvent( IGameEvent *event );
int HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding );
MESSAGE_FUNC( OnItemPresetLoaded, "ItemPresetLoaded" );
MESSAGE_FUNC_PTR( OnIPMouseReleased, "ItemPanelMouseReleased", panel );
MESSAGE_FUNC_PTR( OnItemPanelEntered, "ItemPanelEntered", panel );
MESSAGE_FUNC_PTR( OnItemPanelExited, "ItemPanelExited", panel );
private:
int m_iClass; // Class of the player we're selecting an item for
int m_iSlot; // Slot on the player that we're selecting an item for
bool m_bLoadoutHasChanged;
vgui::EditablePanel *m_pItemContainer;
vgui::ScrollableEditablePanel *m_pItemContainerScroller;
vgui::Label *m_pWeaponLabel;
vgui::Label *m_pEquipYourClassLabel;
vgui::Label *m_pNoItemsToEquipLabel;
vgui::Label *m_pEquippedLabel;
CLoadoutPresetPanel *m_pLoadoutPresetPanel;
KeyValues *m_pItemKV;
CUtlVector<CItemModelPanel *> m_pItemPanels;
CPanelAnimationVarAliasType( int, m_iItemPanelXPos, "itempanel_xpos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iItemPanelYDelta, "itempanel_ydelta", "0", "proportional_int" );
};
#endif // ITEM_QUICKSWITCH_H
+301
View File
@@ -0,0 +1,301 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "item_slot_panel.h"
#include "tf_item_inventory.h"
#include "item_selection_panel.h"
#include "tf_gcmessages.h"
#include "gc_clientsystem.h"
#define NUM_MAX_SLOTS 1
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CItemSlotPanel::CItemSlotPanel( vgui::Panel *parent )
: CBaseLoadoutPanel( parent, "item_slot_panel" )
{
m_pItem = NULL;
m_pSelectionPanel = NULL;
m_iCurrentSlotIndex = 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CItemSlotPanel::~CItemSlotPanel()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
LoadControlSettings( "Resource/UI/ItemSlotPanel.res" );
BaseClass::ApplySchemeSettings( pScheme );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::PerformLayout( void )
{
BaseClass::PerformLayout();
for ( int i = 0; i < m_pItemModelPanels.Count(); i++ )
{
if ( !m_itemSlots[i].m_bHasSlot )
{
m_pItemModelPanels[i]->SetVisible( false );
continue;
}
int iCenter = GetWide() * 0.5;
int iButtonX = (i % GetNumColumns());
int iButtonY = (i / GetNumColumns());
int iXPos = (iCenter + m_iItemBackpackOffcenterX) + (iButtonX * m_pItemModelPanels[i]->GetWide()) + (m_iItemBackpackXDelta * iButtonX);
int iYPos = m_iItemYPos + (iButtonY * m_pItemModelPanels[i]->GetTall() ) + (m_iItemBackpackYDelta * iButtonY);
m_pItemModelPanels[i]->SetPos( iXPos, iYPos );
m_pItemModelPanels[i]->SetVisible( true );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::OnItemPanelMouseReleased( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( pItemPanel && IsVisible() )
{
for ( int i = 0; i < m_pItemModelPanels.Count(); i++ )
{
if ( m_pItemModelPanels[i] == pItemPanel )
{
OnCommand( VarArgs("change%d", i) );
return;
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::OnSelectionReturned( KeyValues *data )
{
if ( data )
{
uint64 ulIndex = data->GetUint64( "itemindex", INVALID_ITEM_ID );
if ( ulIndex != INVALID_ITEM_ID )
{
CEconItemView *pItemData = TFInventoryManager()->GetLocalTFInventory()->GetInventoryItemByItemID( ulIndex );
if ( pItemData )
{
m_pItemModelPanels[ m_iCurrentSlotIndex ]->SetItem( pItemData );
itemid_t ulOriginalID = pItemData->GetSOCData()->GetOriginalID();
m_itemSlots[ m_iCurrentSlotIndex ].m_ulOriginalID = ulOriginalID;
// tell GC to update the slot attribute
GCSDK::CProtoBufMsg<CMsgSetItemSlotAttribute> msg( k_EMsgGC_ClientSetItemSlotAttribute );
msg.Body().set_item_id( m_pItem->GetItemID() );
msg.Body().set_slot_item_original_id( ulOriginalID );
msg.Body().set_slot_index( m_iCurrentSlotIndex + 1 );
//EconUI()->Gamestats_ItemTransaction( IE_ITEM_USED_TOOL, m_pToolModelPanel->GetItem(), "applied_upgrade_card", m_pToolModelPanel->GetItem()->GetItemDefIndex() );
GCClientSystem()->BSendMessage( msg );
}
}
}
PostMessage( GetParent(), new KeyValues("SelectionEnded") );
// It'll have deleted itself, so we don't need to clean it up
m_pSelectionPanel = NULL;
OnCancelSelection();
// find the selected item and give it the focus
CItemModelPanel *pSelection = GetFirstSelectedItemModelPanel( true );
if( !pSelection )
{
m_pItemModelPanels[0]->SetSelected( true );
pSelection = m_pItemModelPanels[0];
}
pSelection->RequestFocus();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::OnCancelSelection( void )
{
if ( m_pSelectionPanel )
{
m_pSelectionPanel->SetVisible( false );
m_pSelectionPanel->MarkForDeletion();
m_pSelectionPanel = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::OnCommand( const char *command )
{
if ( !V_stricmp( command, "ok" ) )
{
SetVisible( false );
return;
}
else if ( V_stristr( command, "change" ) )
{
const char *pszNum = command+6;
if ( pszNum && pszNum[0] )
{
int iSlot = atoi(pszNum);
if ( iSlot >= 0 && iSlot < m_itemSlots.Count() )
{
if ( m_iCurrentSlotIndex != iSlot )
{
m_iCurrentSlotIndex = iSlot;
}
m_selectionCriteria = CItemSelectionCriteria();
m_selectionCriteria.SetTags( m_itemSlots[m_iCurrentSlotIndex].m_slotCriteriaAttribute.tags().c_str() );
m_selectionCriteria.SetIgnoreEnabledFlag( true );
// Create the selection screen. It removes itself on close.
m_pSelectionPanel = new CItemCriteriaSelectionPanel( this, &m_selectionCriteria );
m_pSelectionPanel->InvalidateLayout( false, true ); // need to ApplySchemeSettings now so it doesn't override our SetDialogVariable below later
m_pSelectionPanel->ShowPanel( 0, true );
m_pSelectionPanel->SetDialogVariable( "loadoutclass", g_pVGuiLocalize->Find( "#EditSlots_SelectItemPanel" ) );
PostMessage( GetParent(), new KeyValues("SelectionStarted") );
}
}
return;
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::UpdateModelPanels( void )
{
// For now, fill them out with the local player's currently wielded items
for ( int i = 0; i < m_pItemModelPanels.Count(); i++ )
{
CEconItemView *pItemData = TFInventoryManager()->GetLocalTFInventory()->GetInventoryItemByOriginalID( m_itemSlots[i].m_ulOriginalID );
m_pItemModelPanels[i]->SetItem( pItemData );
m_pItemModelPanels[i]->SetShowQuantity( true );
m_pItemModelPanels[i]->SetSelected( false );
SetBorderForItem( m_pItemModelPanels[i], false );
}
// Now layout again to position our item buttons
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CItemSlotPanel::GetNumItemPanels( void )
{
return NUM_MAX_SLOTS;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::OnShowPanel( bool bVisible, bool bReturningFromArmory )
{
if ( bVisible )
{
if ( m_pSelectionPanel )
{
m_pSelectionPanel->SetVisible( false );
m_pSelectionPanel->MarkForDeletion();
m_pSelectionPanel = NULL;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::AddNewItemPanel( int iPanelIndex )
{
BaseClass::AddNewItemPanel( iPanelIndex );
m_itemSlots.AddToTail();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CItemSlotPanel::SetItem( CEconItem* pItem )
{
if ( !pItem )
{
SetVisible( false );
return;
}
OnCancelSelection();
m_pItem = pItem;
static CSchemaAttributeDefHandle s_itemSlotCriteriaAttributes[] =
{
CSchemaAttributeDefHandle( "item slot criteria 1" ),
};
COMPILE_TIME_ASSERT( ARRAYSIZE( s_itemSlotCriteriaAttributes ) == NUM_MAX_SLOTS );
static CSchemaAttributeDefHandle s_itemInSlotAttributes[] =
{
CSchemaAttributeDefHandle( "item in slot 1" ),
};
COMPILE_TIME_ASSERT( ARRAYSIZE( s_itemInSlotAttributes ) == NUM_MAX_SLOTS );
for ( int i=0; i<ARRAYSIZE( s_itemSlotCriteriaAttributes ); ++i )
{
m_itemSlots[i].m_bHasSlot = false;
if ( m_pItem->FindAttribute( s_itemSlotCriteriaAttributes[i], &m_itemSlots[i].m_slotCriteriaAttribute ) )
{
m_itemSlots[i].m_bHasSlot = true;
m_itemSlots[i].m_ulOriginalID = INVALID_ITEM_ID;
m_pItem->FindAttribute( s_itemInSlotAttributes[i], &m_itemSlots[i].m_ulOriginalID );
}
}
UpdateModelPanels();
}
+54
View File
@@ -0,0 +1,54 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ITEM_SLOT_PANEL_H
#define ITEM_SLOT_PANEL_H
#include "base_loadout_panel.h"
class CItemCriteriaSelectionPanel;
//-----------------------------------------------------------------------------
// A loadout screen that handles modifying the loadout of a specific item
//-----------------------------------------------------------------------------
class CItemSlotPanel : public CBaseLoadoutPanel
{
DECLARE_CLASS_SIMPLE( CItemSlotPanel, CBaseLoadoutPanel );
public:
CItemSlotPanel( vgui::Panel *parent );
~CItemSlotPanel();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout( void );
virtual void AddNewItemPanel( int iPanelIndex ) OVERRIDE;
virtual void UpdateModelPanels( void ) OVERRIDE;
virtual int GetNumItemPanels( void ) OVERRIDE;
virtual void OnShowPanel( bool bVisible, bool bReturningFromArmory ) OVERRIDE;
MESSAGE_FUNC_PTR( OnItemPanelMouseReleased, "ItemPanelMouseReleased", panel );
MESSAGE_FUNC_PARAMS( OnSelectionReturned, "SelectionReturned", data );
MESSAGE_FUNC( OnCancelSelection, "CancelSelection" );
virtual void OnCommand( const char *command );
void SetItem( CEconItem* pItem );
private:
CEconItem *m_pItem;
struct ItemSlot_t
{
CAttribute_ItemSlotCriteria m_slotCriteriaAttribute;
itemid_t m_ulOriginalID;
bool m_bHasSlot;
};
CUtlVector< ItemSlot_t > m_itemSlots;
int m_iCurrentSlotIndex;
CItemSelectionCriteria m_selectionCriteria;
CItemCriteriaSelectionPanel *m_pSelectionPanel;
};
#endif // ITEM_SLOT_PANEL_H
@@ -0,0 +1,250 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#include "loadout_preset_panel.h"
#include "tf_item_inventory.h"
#include "econ/econ_item_preset.h"
#include "econ/econ_item_system.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
using namespace vgui;
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CLoadoutPresetPanel );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CLoadoutPresetPanel::CLoadoutPresetPanel( vgui::Panel *pParent, const char *pName )
: EditablePanel( pParent, "loadout_preset_panel" )
{
V_memset( m_pPresetButtons, 0, sizeof( m_pPresetButtons ) );
m_iClass = TF_CLASS_UNDEFINED;
m_pPresetButtonKv = NULL;
m_bDisplayVertical = false;
// Create all buttons
for ( int i = 0; i < MAX_PRESETS; ++i )
{
CFmtStr fmtTokenName( "TF_ItemPresetName%i", i );
CFmtStr fmtButtonName( "LoadPresetButton%i", i );
wchar_t *pwszPresetName = g_pVGuiLocalize->Find( fmtTokenName.Access() );
m_pPresetButtons[i] = new CExButton( this, fmtButtonName.Access(), pwszPresetName, this );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadoutPresetPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/LoadoutPresetPanel.res" );
m_aDefaultColors[LOADED][FG][DEFAULT] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetDefaultColorFg", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[LOADED][FG][ARMED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetArmedColorFg", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[LOADED][FG][DEPRESSED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetDepressedColorFg", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[LOADED][BG][DEFAULT] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetDefaultColorBg", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[LOADED][BG][ARMED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetArmedColorBg", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[LOADED][BG][DEPRESSED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Econ.Button.PresetDepressedColorBg", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[NOTLOADED][FG][DEFAULT] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.TextColor", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[NOTLOADED][FG][ARMED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.ArmedTextColor", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[NOTLOADED][FG][DEPRESSED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.DepressedTextColor", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[NOTLOADED][BG][DEFAULT] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.BgColor", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[NOTLOADED][BG][ARMED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.ArmedBgColor", Color( 255, 255, 255, 255 ) );
m_aDefaultColors[NOTLOADED][BG][DEPRESSED] = vgui::scheme()->GetIScheme( GetScheme() )->GetColor( "Button.DepressedBgColor", Color( 255, 255, 255, 255 ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadoutPresetPanel::ApplySettings( KeyValues *pInResourceData )
{
BaseClass::ApplySettings( pInResourceData );
KeyValues *pPresetButtonKv = pInResourceData->FindKey( "presetbutton_kv" );
if ( pPresetButtonKv && !m_pPresetButtonKv )
{
m_pPresetButtonKv = new KeyValues( "presetbutton_kv" );
pPresetButtonKv->CopySubkeys( m_pPresetButtonKv );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadoutPresetPanel::PerformLayout()
{
BaseClass::PerformLayout();
if ( !m_pPresetButtons[0] )
return;
const int nBuffer = XRES( 2 );
for ( int i = 0; i < MAX_PRESETS; ++i )
{
if ( m_pPresetButtonKv )
{
m_pPresetButtons[i]->ApplySettings( m_pPresetButtonKv );
}
// Display buttons vertically or horizontally?
// NOTE: Button width and height will be valid here, since we've just applied settings
if ( m_bDisplayVertical )
{
const int nButtonHeight = m_pPresetButtons[0]->GetTall();
m_pPresetButtons[i]->SetPos( 0, i * ( nButtonHeight + nBuffer ) );
}
else
{
const int nButtonWidth = m_pPresetButtons[0]->GetWide();
const int nStartX = 0.5f * ( GetWide() - MAX_PRESETS * ( nButtonWidth + nBuffer ) );
m_pPresetButtons[i]->SetPos( nStartX + i * ( nButtonWidth + nBuffer ), 0 );
}
m_pPresetButtons[i]->SetVisible( true );
}
vgui::ivgui()->AddTickSignal( GetVPanel(), 150 );
UpdatePresetButtonStates();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadoutPresetPanel::SetClass( int iClass )
{
m_iClass = iClass;
if ( iClass != TF_CLASS_UNDEFINED )
{
UpdatePresetButtonStates();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadoutPresetPanel::EnableVerticalDisplay( bool bVertical )
{
m_bDisplayVertical = bVertical;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadoutPresetPanel::LoadPreset( int iPresetIndex )
{
TFInventoryManager()->LoadPreset( m_iClass, iPresetIndex );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadoutPresetPanel::OnCommand( const char *command )
{
if ( !V_strnicmp( command, "loadpreset_", 11 ) )
{
const int iPresetIndex = atoi( command + 11 );
LoadPreset( iPresetIndex );
}
else
{
BaseClass::OnCommand( command );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadoutPresetPanel::OnTick()
{
UpdatePresetButtonStates();
}
//-----------------------------------------------------------------------------
// Purpose: Processes some keypresses for the loadout panel
//-----------------------------------------------------------------------------
bool CLoadoutPresetPanel::HandlePresetKeyPressed( vgui::KeyCode code )
{
ButtonCode_t nButtonCode = GetBaseButtonCode( code );
if( nButtonCode == KEY_XBUTTON_LEFT_SHOULDER )
{
if( GetSelectedPresetID() > 0 )
LoadPreset( GetSelectedPresetID() - 1 );
return true;
}
else if( nButtonCode == KEY_XBUTTON_RIGHT_SHOULDER )
{
if( GetSelectedPresetID() < MAX_PRESETS - 1 )
LoadPreset( GetSelectedPresetID() + 1 );
return true;
}
else
{
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
equipped_preset_t CLoadoutPresetPanel::GetSelectedPresetID() const
{
if ( !InventoryManager()->GetLocalInventory() )
return INVALID_PRESET_INDEX;
const uint32 unAccountID = InventoryManager()->GetLocalInventory()->GetOwner().GetAccountID();
const CEconItemPerClassPresetData soSearch( unAccountID, m_iClass );
GCSDK::CSharedObjectCache *pSOCache = InventoryManager()->GetLocalInventory()->GetSOC();
if ( !pSOCache )
return INVALID_PRESET_INDEX;
const CEconItemPerClassPresetData *pExistingPerClassData = assert_cast<CEconItemPerClassPresetData *>( pSOCache->FindSharedObject( soSearch ) );
if ( !pExistingPerClassData )
return INVALID_PRESET_INDEX;
return pExistingPerClassData->GetActivePreset();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadoutPresetPanel::UpdatePresetButtonStates()
{
const equipped_preset_t unEquippedPresetID = GetSelectedPresetID();
for ( int i = 0; i < MAX_PRESETS; ++i )
{
if ( i == unEquippedPresetID )
{
m_pPresetButtons[i]->SetDefaultColor( m_aDefaultColors[LOADED][FG][DEFAULT], m_aDefaultColors[LOADED][BG][DEFAULT] );
m_pPresetButtons[i]->SetArmedColor( m_aDefaultColors[LOADED][FG][ARMED], m_aDefaultColors[LOADED][BG][ARMED] );
m_pPresetButtons[i]->SetDepressedColor( m_aDefaultColors[LOADED][FG][DEPRESSED], m_aDefaultColors[LOADED][BG][DEPRESSED] );
}
else
{
m_pPresetButtons[i]->SetDefaultColor( m_aDefaultColors[NOTLOADED][FG][DEFAULT], m_aDefaultColors[NOTLOADED][BG][DEFAULT] );
m_pPresetButtons[i]->SetArmedColor( m_aDefaultColors[NOTLOADED][FG][ARMED], m_aDefaultColors[NOTLOADED][BG][ARMED] );
m_pPresetButtons[i]->SetDepressedColor( m_aDefaultColors[NOTLOADED][FG][DEPRESSED], m_aDefaultColors[NOTLOADED][BG][DEPRESSED] );
}
CFmtStr fmtCmd( "loadpreset_%i", i );
m_pPresetButtons[i]->SetCommand( fmtCmd.Access() );
}
}
@@ -0,0 +1,64 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef LOADOUT_PRESET_PANEL_H
#define LOADOUT_PRESET_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
#include "vgui_controls/PHandle.h"
#include "class_loadout_panel.h"
class CExButton;
class CSelectedItemPreset;
//-----------------------------------------------------------------------------
// A loadout preset panel, which allows combinations of items to be saved and
// restored via the GC.
//-----------------------------------------------------------------------------
class CLoadoutPresetPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CLoadoutPresetPanel, vgui::EditablePanel );
public:
CLoadoutPresetPanel( vgui::Panel *pParent, const char *pName ); // name is ignored but needed for DECLARE_BUILD_FACTORY()
void SetClass( int iClass );
void EnableVerticalDisplay( bool bVertical );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *pInResourceData );
virtual void PerformLayout();
virtual void OnCommand( const char *command );
virtual void OnTick() OVERRIDE;
bool HandlePresetKeyPressed( vgui::KeyCode code );
private:
equipped_preset_t GetSelectedPresetID() const;
void UpdatePresetButtonStates();
void LoadPreset( int iPresetIndex );
enum PresetsConsts_t
{
MAX_PRESETS = 4,
};
int m_iClass;
KeyValues *m_pPresetButtonKv;
CExButton *m_pPresetButtons[ MAX_PRESETS ];
bool m_bDisplayVertical;
enum PresetButtonColors_t
{
LOADED = 0, NOTLOADED,
FG = 0, BG,
DEFAULT = 0, ARMED, DEPRESSED
};
Color m_aDefaultColors[2][2][3]; // [LOADED|NOTLOADED][FG|BG][DEFAULT|ARMED|DEPRESSED]
};
#endif // LOADOUT_PRESET_PANEL_H
+214
View File
@@ -0,0 +1,214 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "modelimagepanel.h"
#include "iconrenderreceiver.h"
#include "materialsystem/imaterialvar.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "renderparm.h"
using namespace vgui;
const char *g_pszModelImagePanelRTName = "_rt_ModelImagePanel";
static vgui::DHANDLE<CModelImagePanel> s_hModelImageLockPanel;
#ifdef STAGING_ONLY
ConVar tf_modelimagepanel_ignore_cache( "tf_modelimagepanel_ignore_cache", "0" );
#endif
DECLARE_BUILD_FACTORY( CModelImagePanel );
CModelImagePanel::CModelImagePanel( vgui::Panel *pParent, const char *pName )
: BaseClass( pParent, pName )
{
m_pCachedIcon = NULL;
m_pCachedMaterial = NULL;
m_iCachedTextureID = -1;
}
CModelImagePanel::~CModelImagePanel()
{
InvalidateImage();
}
void CModelImagePanel::PerformLayout()
{
BaseClass::PerformLayout();
InvalidateImage();
}
void CModelImagePanel::OnSizeChanged( int wide, int tall )
{
BaseClass::OnSizeChanged( wide, tall );
InvalidateImage();
}
void CModelImagePanel::Paint()
{
// don't do anything for invalid model
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
{
return;
}
// check lock panel
if ( s_hModelImageLockPanel )
{
// waiting for async copy to finish
if ( s_hModelImageLockPanel->m_pCachedIcon && s_hModelImageLockPanel->m_pCachedIcon->GetTexture() )
{
s_hModelImageLockPanel = NULL;
}
}
if ( m_pCachedIcon )
{
if ( m_pCachedIcon->GetTexture() )
{
if ( !m_pCachedMaterial && g_pMaterialSystem )
{
const char *pszTextureName = m_pCachedIcon->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_pCachedMaterial, pMaterial );
bool bFound = false;
IMaterialVar *pVar = m_pCachedMaterial->FindVar( "$basetexture", &bFound );
if ( bFound && pVar )
{
pVar->SetTextureValue( m_pCachedIcon->GetTexture() );
m_pCachedMaterial->RefreshPreservingMaterialVars();
}
}
if ( m_iCachedTextureID == -1 )
{
m_iCachedTextureID = g_pMatSystemSurface->DrawGetTextureId( m_pCachedIcon->GetTexture() );
g_pMatSystemSurface->DrawSetTextureMaterial( m_iCachedTextureID, m_pCachedMaterial );
}
}
else
{
// still waiting for texture
BaseClass::Paint();
return;
}
}
// just draw the texture if we got one.
if ( m_iCachedTextureID != -1 )
{
surface()->DrawSetTexture( m_iCachedTextureID );
surface()->DrawSetColor( 255, 255, 255, 255 );
const int iWidth = GetWide();
const int iHeight = GetTall();
const int iMappingWitdh = m_pCachedMaterial->GetMappingWidth();
const int iMappingHeight = m_pCachedMaterial->GetMappingHeight();
float flTexW, flTexH;
if ( iWidth > iMappingWitdh || iHeight > iMappingHeight )
{
float flScale = iWidth > iHeight ? (float)iMappingWitdh / iWidth : (float)iMappingHeight / iHeight;
flTexW = ( flScale * iWidth ) / iMappingWitdh;
flTexH = ( flScale * iHeight ) / iMappingHeight;
}
else
{
flTexW = (float)( iWidth - 1 ) / iMappingWitdh;
flTexH = (float)( iHeight - 1 ) / iMappingHeight;
}
surface()->DrawTexturedSubRect( 0, 0, iWidth, iHeight, 0.f, 0.f, flTexW, flTexH );
return;
}
// can't find available cache render target, don't do anything
if ( s_hModelImageLockPanel != NULL && s_hModelImageLockPanel != this )
{
BaseClass::Paint();
return;
}
CMatRenderContextPtr pRenderContext( materials );
// 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 );
g_pMatSystemSurface->Set3DPaintTempRenderTarget( g_pszModelImagePanelRTName );
BaseClass::Paint();
// copy the rendered weapon skin from the render target
Assert( m_pCachedIcon == NULL );
CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_RootMDL.m_MDL.GetMDL() ), g_pMDLCache );
char buffer[_MAX_PATH];
CUtlString strMDLName = V_GetFileName( studioHdr.pszName() );
V_sprintf_safe( buffer, "proc/icon/mdl_%s_body%d_skin%d_w%d_h%d", strMDLName.StripExtension().Get(), m_RootMDL.m_MDL.m_nBody, m_RootMDL.m_MDL.m_nSkin, GetWide(), GetTall() );
SafeAssign( &m_pCachedIcon, new CIconRenderReceiver() );
// If the icon still exists in the material system, don't bother regenerating it.
if ( materials->IsTextureLoaded( buffer )
#ifdef STAGING_ONLY
&& !tf_modelimagepanel_ignore_cache.GetBool()
#endif
)
{
ITexture* resTexture = materials->FindTexture( buffer, TEXTURE_GROUP_RUNTIME_COMPOSITE, false, 0 );
if ( resTexture && resTexture->IsError() == false )
{
m_pCachedIcon->OnAsyncCreateComplete( resTexture, NULL );
}
}
else
{
// No icon available yet, need to create it.
ITexture *pRenderTarget = g_pMaterialSystem->FindTexture( g_pszModelImagePanelRTName, TEXTURE_GROUP_RENDER_TARGET );
if ( pRenderTarget )
{
pRenderContext->AsyncCreateTextureFromRenderTarget( pRenderTarget, buffer, IMAGE_FORMAT_RGBA8888, false, TEXTUREFLAGS_IMMEDIATE_CLEANUP, m_pCachedIcon, NULL );
// make this panel lock the render target
s_hModelImageLockPanel = this;
}
}
g_pMatSystemSurface->Reset3DPaintTempRenderTarget();
}
void CModelImagePanel::SetMDL( MDLHandle_t handle, void *pProxyData /*= NULL*/ )
{
BaseClass::SetMDL( handle, pProxyData );
InvalidateImage();
}
void CModelImagePanel::SetMDL( const char *pMDLName, void *pProxyData /*= NULL*/ )
{
BaseClass::SetMDL( pMDLName, pProxyData );
}
void CModelImagePanel::SetMDLBody( unsigned int nBody )
{
SetBody( nBody );
InvalidateImage();
}
void CModelImagePanel::SetMDLSkin( int nSkin )
{
SetSkin( nSkin );
InvalidateImage();
}
void CModelImagePanel::InvalidateImage()
{
SafeRelease( &m_pCachedIcon );
SafeRelease( &m_pCachedMaterial );
m_iCachedTextureID = -1;
}
+43
View File
@@ -0,0 +1,43 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef MODELIMAGEPANEL_H
#define MODELIMAGEPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "basemodel_panel.h"
class CIconRenderReceiver;
class CModelImagePanel : public CBaseModelPanel
{
DECLARE_CLASS_SIMPLE( CModelImagePanel, CBaseModelPanel );
public:
// Constructor, Destructor.
CModelImagePanel( vgui::Panel *pParent, const char *pName );
virtual ~CModelImagePanel();
virtual void PerformLayout() OVERRIDE;
virtual void Paint() OVERRIDE;
virtual void OnSizeChanged( int wide, int tall ) OVERRIDE;
virtual void SetMDL( MDLHandle_t handle, void *pProxyData = NULL ) OVERRIDE;
virtual void SetMDL( const char *pMDLName, void *pProxyData = NULL ) OVERRIDE;
void SetMDLBody( unsigned int nBody );
void SetMDLSkin( int nSkin );
void InvalidateImage();
private:
CIconRenderReceiver *m_pCachedIcon;
IMaterial *m_pCachedMaterial;
int m_iCachedTextureID;
};
#endif // MODELIMAGEPANEL_H
File diff suppressed because it is too large Load Diff
+265
View File
@@ -0,0 +1,265 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef QUEST_ITEM_PANEL_H
#define QUEST_ITEM_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "econ_item_inventory.h"
#include "tf_controls.h"
using namespace vgui;
class CScrollableQuestList;
class CItemModelPanel;
//-----------------------------------------------------------------------------
// Simple tooltip class that looks into the moused-over panel's dialog variables
// for "tiptext" and uses that value as its string to present.
//-----------------------------------------------------------------------------
class CQuestTooltip : public CTFTextToolTip
{
DECLARE_CLASS_SIMPLE( CQuestTooltip, CTFTextToolTip );
public:
CQuestTooltip( vgui::Panel *parent, const char *text = NULL )
: BaseClass( parent, text )
{}
virtual void ShowTooltip( Panel *pCurrentPanel ) OVERRIDE;
virtual void PositionWindow( Panel *pTipPanel ) OVERRIDE;
private:
};
//-----------------------------------------------------------------------------
// Can pass various input events to other panels
//-----------------------------------------------------------------------------
class CInputProxyPanel : public EditablePanel
{
public:
enum EInputTypes
{
INPUT_MOUSE_ENTER = 0,
INPUT_MOUSE_EXIT,
INPUT_MOUSE_PRESS,
INPUT_MOUSE_DOUBLE_PRESS,
INPUT_MOUSE_RELEASED,
INPUT_MOUSE_WHEEL,
INPUT_MOUSE_MOVE,
NUM_INPUT_TYPES,
};
DECLARE_CLASS_SIMPLE( CInputProxyPanel, EditablePanel );
CInputProxyPanel( Panel *parent, const char *pszPanelName );
void AddPanelForCommand( EInputTypes eInputType, Panel* pPanel, const char* pszCommand );
MESSAGE_FUNC_INT_INT( OnCursorMoved, "OnCursorMoved", x, y );
virtual void OnCursorEntered();
virtual void OnCursorExited();
virtual void OnMousePressed(MouseCode code);
virtual void OnMouseDoublePressed(MouseCode code);
virtual void OnMouseReleased(MouseCode code);
virtual void OnMouseWheeled(int delta);
private:
struct CommandPair_t
{
Panel* m_pPanel;
const char* m_pszCommand;
};
CUtlVector< CommandPair_t > m_vecRedirectPanels[NUM_INPUT_TYPES];
};
//-----------------------------------------------------------------------------
// Contains a panel that animates into place when it needs to show or hide
//-----------------------------------------------------------------------------
class CQuestStatusPanel : public EditablePanel
{
public:
DECLARE_CLASS_SIMPLE( CQuestStatusPanel, EditablePanel );
CQuestStatusPanel( Panel *parent, const char *pszPanelName );
void SetShow( bool bShow );
virtual void OnThink() OVERRIDE;
private:
EditablePanel* m_pMovingContainer;
RealTimeCountdownTimer m_transitionTimer;
bool m_bShouldBeVisible;
CPanelAnimationVarAliasType( int, m_iVisibleY, "visible_y", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iHiddenY, "hidden_y", "40", "proportional_int" );
};
//-----------------------------------------------------------------------------
// An representation of a single quest
//-----------------------------------------------------------------------------
class CQuestItemPanel : public EditablePanel, CGameEventListener
{
public:
enum EItemPanelState_t
{
STATE_NORMAL = 0,
STATE_UNIDENTIFIED,
STATE_IDENTIFYING,
STATE_COMPLETED,
STATE_TURNING_IN__WAITING_FOR_GC,
STATE_TURNING_IN__GC_RESPONDED,
STATE_SHOW_ACCEPTED,
NUM_STATES,
};
DECLARE_CLASS_SIMPLE( CQuestItemPanel, EditablePanel );
CQuestItemPanel( Panel *parent, const char *pszPanelName, CEconItemView* pQuestItem, CScrollableQuestList* pQuestList );
virtual ~CQuestItemPanel();
virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE;
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
virtual void PerformLayout( void ) OVERRIDE;
virtual void OnCommand( const char *command ) OVERRIDE;
virtual void OnThink() OVERRIDE;
virtual void FireGameEvent( IGameEvent *event ) OVERRIDE;
virtual void OnSizeChanged(int wide, int tall) OVERRIDE {}
virtual void OnMouseReleased(MouseCode code) OVERRIDE;
const CEconItemView* GetItem() { return m_hQuestItem; }
void SetItem( CEconItemView* pItem );
void QuestCompletedResponse();
EItemPanelState_t GetState() const { return m_eState; }
void SetSelected( bool bSelected, bool bImmediate );
bool IsSelected() const { return !m_bCollapsed; }
bool IsCursorOverMainContainer() const;
MESSAGE_FUNC( OnCollapsedGlowStart, "CollapsedGlowStart" );
MESSAGE_FUNC( OnCollapsedGlowEnd, "CollapsedGlowEnd" );
MESSAGE_FUNC( OnDiscardQuest, "DiscardQuest" );
MESSAGE_FUNC( OnEquipLoaners, "EquipLoaners" );
void OnCompleteQuest();
void OnConfirmDelete( bool bConfirm );
void OnConfirmEquipLoaners( bool bConfirm );
protected:
bool HasAllControls() const { return m_bHasAllControls; }
void LoadResFileForCurrentItem();
void OnIdentify();
void SetupObjectivesPanels( bool bRecreate );
bool IsUnacknowledged();
void SetState( EItemPanelState_t eState );
void CaptureAndEncodeStrings();
const wchar_t* GetDecodedString( const char* pszKeyName, float flPercentDecoded );
void UpdateInvalidReasons();
EItemPanelState_t m_eState;
CEconItemViewHandle m_hQuestItem;
EditablePanel *m_pQuestPaperContainer;
EditablePanel *m_pFrontFolderContainer;
ImagePanel *m_pFrontFolderImage;
EditablePanel *m_pBackFolderContainer;
ImagePanel *m_pBackFolderImage;
ImagePanel *m_pEncodedImage;
EditablePanel *m_pMainContainer;
CQuestStatusPanel *m_pEncodedStatus;
CQuestStatusPanel *m_pInactiveStatus;
CQuestStatusPanel *m_pReadyToTurnInStatus;
Label *m_pFlavorText;
Label *m_pObjectiveExplanationLabel;
Label *m_pExpirationLabel;
EditablePanel *m_pTurnInContainer;
EditablePanel *m_pTurnInDimmer;
Button *m_pTurnInButton;
EditablePanel *m_pTurnInSpinnerContainer;
CExButton *m_pTitleButton;
EditablePanel *m_pIdentifyDimmer;
EditablePanel *m_pIdentifyContainer;
CExButton *m_pIdentifyButton;
ImagePanel *m_pPhotoStatic;
ImagePanel *m_pAcceptedImage;
Label *m_pTurningInLabel;
class CExScrollingEditablePanel *m_pFlavorScrollingContainer;
CExButton *m_pFindServerButton;
// loaners
EditablePanel *m_pLoanerContainerPanel;
CExButton *m_pRequestLoanerItemsButton;
CExButton *m_pEquipLoanerItemsButton;
CItemModelPanel *m_pLoanerItemModelPanel[2];
CExButton *m_pDiscardButton;
int m_nPaperXPos;
int m_nPaperYPos;
int m_nPaperXShakePos;
int m_nPaperYShakePos;
bool m_bHasAllControls;
CUtlString m_strItemTrackerResFile;
CUtlString m_strQuickPlayMap;
CUtlString m_strMatchmakingGroupName;
CUtlString m_strMatchmakingCategoryName;
CUtlString m_strMatchmakingMapName;
// Sound effects
CUtlString m_strExpandSound;
CUtlString m_strCollapseSound;
CUtlString m_strTurnInSound;
CUtlString m_strTurnInSuccessSound;
CUtlString m_strDecodeSound;
// Animation
CUtlString m_strReset;
CUtlString m_strAnimExpand;
CUtlString m_strAnimCollapse;
CUtlString m_strTurningIn;
CUtlString m_strHighlightOn;
CUtlString m_strHighlightOff;
class CItemTrackerPanel *m_pItemTrackerPanel;
CScrollableQuestList *m_pQuestList;
RealTimeCountdownTimer m_StateTimer;
KeyValues *m_pKVItemTracker;
struct FolderPair_t
{
CUtlString m_strFront;
CUtlString m_strBack;
};
CUtlVector< FolderPair_t > m_vecFoldersImages;
CUtlString m_strEncodedText;
CUtlString m_strExpireText;
const char *m_pszCompleteSound;
bool m_bCollapsed;
KeyValues *m_pKVCipherStrings;
CPanelAnimationVarAliasType( int, m_iFrontPaperHideHeight, "front_paper_hide_height", "1000", "proportional_int" ); // Default to a large value so it wont be visible
CPanelAnimationVarAliasType( int, m_iUnidentifiedHeight, "unidentified_height", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iObjectiveInset, "objective_inset", "200", "proportional_int" );
//CPanelAnimationVarAliasType( int, m_iScrollingContainerHeight, "scrolling_container_height", "200", "proportional_int" );
enum EDecodeStyle
{
DECODE_STYLE_CYPHER = 0,
DECODE_STYLE_PANEL_FADE,
};
CPanelAnimationVarAliasType( EDecodeStyle, m_eDecodeStyle, "decode_style", "0", "int" );
};
#endif // QUEST_ITEM_PANEL_H
File diff suppressed because it is too large Load Diff
+132
View File
@@ -0,0 +1,132 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef QUEST_LOG_PANEL_H
#define QUEST_LOG_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
#include <game/client/iviewport.h>
#include "quest_item_panel.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Creates the quest log if it doesnt exists, and gives you a pointer to it
//-----------------------------------------------------------------------------
class CQuestLogPanel *GetQuestLog();
//-----------------------------------------------------------------------------
// A scrollable list of quest items
//-----------------------------------------------------------------------------
class CScrollableQuestList : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CScrollableQuestList, EditablePanel );
public:
CScrollableQuestList( Panel *parent, const char *pszPanelName );
virtual ~CScrollableQuestList();
virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE;
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
virtual void PerformLayout( void ) OVERRIDE;
virtual void OnThink() OVERRIDE;
virtual void OnCommand( const char *command ) OVERRIDE;
void DirtyQuestLayout() { m_bQuestsLayoutDirty = true; }
void PopulateQuestLists();
void QuestCompletedResponse();
bool AnyQuestItemPanelsInState( CQuestItemPanel::EItemPanelState_t eState ) const;
void PositionQuestItemPanels();
void SetSelected( CQuestItemPanel *pItem, bool bImmediately );
void SetCompletingPanel( const CQuestItemPanel *pItem ) { m_pCompletingPanel = pItem; }
const CQuestItemPanel *GetCompletingPanel() const { return m_pCompletingPanel; }
void UpdateEmptyMessage();
protected:
bool m_bQuestsLayoutDirty;
EditablePanel *m_pContainer;
CUtlVector< CQuestItemPanel* > m_vecQuestItemPanels;
CQuestItemPanel* m_spCompletingPanel;
const CQuestItemPanel* m_pCompletingPanel;
CUtlString m_pszNoQuests;
CUtlString m_pszNeedAPass;
CUtlString m_pszNotPossible;
CPanelAnimationVarAliasType( int, m_iEntryStep, "entry_step", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iEntryStartingX, "entry_x", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iEntryStartingY, "entry_y", "0", "proportional_int" );
};
//-----------------------------------------------------------------------------
// The default quest log panel
//-----------------------------------------------------------------------------
class CQuestLogPanel : public EditablePanel, public IViewPortPanel, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CQuestLogPanel, EditablePanel );
public:
CQuestLogPanel( IViewPort *pViewPort );
virtual ~CQuestLogPanel();
void AttachToGameUI();
virtual const char *GetName( void ) OVERRIDE;
virtual void SetData( KeyValues *data ) OVERRIDE {}
virtual void Reset() OVERRIDE { Update(); SetVisible( true ); }
virtual void Update() OVERRIDE { return; }
virtual bool NeedsUpdate( void ) OVERRIDE { return false; }
virtual bool HasInputElements( void ) OVERRIDE { return true; }
virtual void ShowPanel( bool bShow ) OVERRIDE;
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
vgui::VPANEL GetVPanel( void ){ return BaseClass::GetVPanel(); }
virtual bool IsVisible() OVERRIDE { return BaseClass::IsVisible(); }
virtual void SetParent( vgui::VPANEL parent ) OVERRIDE { BaseClass::SetParent( parent ); }
virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE;
virtual void PerformLayout() OVERRIDE;
virtual void OnCommand( const char *pCommand ) OVERRIDE;
virtual void FireGameEvent( IGameEvent *event ) OVERRIDE;
virtual void SetVisible( bool bState ) OVERRIDE;
virtual void OnKeyCodePressed( KeyCode code ) OVERRIDE;
virtual void OnKeyCodeTyped(KeyCode code) OVERRIDE;
virtual GameActionSet_t GetPreferredActionSet() { return GAME_ACTION_SET_NONE; }
void QuestCompletedResponse();
void UpdateQuestsItemPanels();
void MarkQuestsDirty();
void UpdateBadgeProgressPanels();
bool AnyQuestItemPanelsInState( CQuestItemPanel::EItemPanelState_t eState ) const;
MESSAGE_FUNC( OnCompleteQuest, "CompleteQuest" );
private:
CScrollableQuestList *m_pQuestList;
class CItemModelPanel *m_pMouseOverItemPanel;
class CItemModelPanelToolTip *m_pMouseOverTooltip;
EditablePanel *m_pProgressPanel;
class CQuestTooltip *m_pToolTip;
EditablePanel *m_pToolTipEmbeddedPanel;
ButtonCode_t m_iQuestLogKey;
bool m_bWaitingForComplete;
bool m_bInventoryDirty;
Button *m_pDebugButton;
};
#endif // QUEST_LOG_PANEL_H
@@ -0,0 +1,533 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "quest_notification_panel.h"
#include "vgui/ISurface.h"
#include "ienginevgui.h"
#include "hudelement.h"
#include "iclientmode.h"
#include "basemodel_panel.h"
#include "tf_item_inventory.h"
#include "quest_log_panel.h"
#include "econ_controls.h"
#include "c_tf_player.h"
#include <vgui_controls/AnimationController.h>
#include "engine/IEngineSound.h"
#include "econ_item_system.h"
#include "tf_hud_item_progress_tracker.h"
#include "tf_spectatorgui.h"
#include "econ_quests.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
ConVar tf_quest_notification_line_delay( "tf_quest_notification_line_delay", "1.2", FCVAR_ARCHIVE );
extern ISoundEmitterSystemBase *soundemitterbase;
CQuestNotificationPanel *g_pQuestNotificationPanel = NULL;
DECLARE_HUDELEMENT( CQuestNotificationPanel );
CQuestNotification::CQuestNotification( CEconItem *pItem )
: m_hItem( pItem )
{}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CQuestNotification::Present( CQuestNotificationPanel* pNotificationPanel )
{
m_timerDialog.Start( tf_quest_notification_line_delay.GetFloat() );
return 0.f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CQuestNotification_Speaking::CQuestNotification_Speaking( CEconItem *pItem )
: CQuestNotification( pItem )
{
m_pszSoundToSpeak = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CQuestNotification_Speaking::Present( CQuestNotificationPanel* pNotificationPanel )
{
CQuestNotification::Present( pNotificationPanel );
if ( m_hItem )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer )
return 0.f;
CTFPlayer* pTFPlayer = ToTFPlayer( pPlayer );
if ( !pTFPlayer )
return 0.f;
const GameItemDefinition_t *pItemDef = m_hItem->GetItemDefinition();
// Get our quest theme
const CQuestThemeDefinition *pTheme = pItemDef->GetQuestDef()->GetQuestTheme();
if ( pTheme )
{
// Get the sound we need to speak
m_pszSoundToSpeak = GetSoundEntry( pTheme, pTFPlayer->GetPlayerClass()->GetClassIndex() );
float flPresentTime = 0.f;
if ( m_pszSoundToSpeak )
{
flPresentTime = enginesound->GetSoundDuration( m_pszSoundToSpeak ) + m_timerDialog.GetCountdownDuration() + 1.f;
m_timerShow.Start( enginesound->GetSoundDuration( m_pszSoundToSpeak ) + m_timerDialog.GetCountdownDuration() + 1.f );
}
return flPresentTime;
}
}
return 0.f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuestNotification_Speaking::Update( CQuestNotificationPanel* pNotificationPanel )
{
if ( m_timerDialog.IsElapsed() && m_timerDialog.HasStarted() && m_hItem )
{
m_timerDialog.Invalidate();
// Play it!
if ( m_pszSoundToSpeak )
{
vgui::surface()->PlaySound( m_pszSoundToSpeak );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CQuestNotification_Speaking::IsDone() const
{
return m_timerShow.IsElapsed() && m_timerShow.HasStarted();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CQuestNotification_NewQuest::GetSoundEntry( const CQuestThemeDefinition* pTheme, int nClassIndex )
{
return pTheme->GetGiveSoundForClass( nClassIndex );
}
bool CQuestNotification_NewQuest::ShouldPresent() const
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer )
return false;
CTFPlayer* pTFPlayer = ToTFPlayer( pPlayer );
if ( !pTFPlayer )
return false;
IViewPortPanel* pSpecGuiPanel = gViewPortInterface->FindPanelByName( PANEL_SPECGUI );
if ( !pTFPlayer->IsAlive() )
{
if ( !pSpecGuiPanel || !pSpecGuiPanel->IsVisible() )
return false;
}
else
{
// Local player is in a spawn room
if ( pTFPlayer->m_Shared.GetRespawnTouchCount() <= 0 )
return false;
}
return true;
}
CQuestNotification_CompletedQuest::CQuestNotification_CompletedQuest( CEconItem *pItem )
: CQuestNotification_Speaking( pItem )
{
const char *pszSoundName = UTIL_GetRandomSoundFromEntry( "Quest.StatusTickComplete" );
m_PresentTimer.Start( enginesound->GetSoundDuration( pszSoundName ) - 2.f );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CQuestNotification_CompletedQuest::GetSoundEntry( const CQuestThemeDefinition* pTheme, int nClassIndex )
{
return pTheme->GetCompleteSoundForClass( nClassIndex );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CQuestNotification_CompletedQuest::ShouldPresent() const
{
return m_PresentTimer.IsElapsed() && m_PresentTimer.HasStarted();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CQuestNotification_FullyCompletedQuest::GetSoundEntry( const CQuestThemeDefinition* pTheme, int nClassIndex )
{
return pTheme->GetFullyCompleteSoundForClass( nClassIndex );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CQuestNotificationPanel::CQuestNotificationPanel( const char *pszElementName )
: CHudElement( pszElementName )
, EditablePanel( NULL, "QuestNotificationPanel" )
, m_flTimeSinceLastShown( 0.f )
, m_bIsPresenting( false )
, m_mapNotifiedItemIDs( DefLessFunc( itemid_t ) )
, m_bInitialized( false )
, m_pMainContainer( NULL )
{
Panel *pParent = g_pClientMode->GetViewport();
SetParent( pParent );
g_pQuestNotificationPanel = this;
ListenForGameEvent( "player_death" );
ListenForGameEvent( "inventory_updated" );
ListenForGameEvent( "player_initial_spawn" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CQuestNotificationPanel::~CQuestNotificationPanel()
{}
void CQuestNotificationPanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
// Default, load pauling
LoadControlSettings( "Resource/UI/econ/QuestNotificationPanel_Pauling_standard.res" );
m_pMainContainer = FindControl< EditablePanel >( "MainContainer", true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuestNotificationPanel::PerformLayout()
{
BaseClass::PerformLayout();
CExLabel* pNewQuestLabel = FindControl< CExLabel >( "NewQuestText", true );
if ( pNewQuestLabel )
{
const wchar_t *pszText = NULL;
const char *pszTextKey = "#QuestNotification_Accept";
if ( pszTextKey )
{
pszText = g_pVGuiLocalize->Find( pszTextKey );
}
if ( pszText )
{
wchar_t wzFinal[512] = L"";
UTIL_ReplaceKeyBindings( pszText, 0, wzFinal, sizeof( wzFinal ) );
pNewQuestLabel->SetText( wzFinal );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuestNotificationPanel::FireGameEvent( IGameEvent * event )
{
const char *pszName = event->GetName();
if ( FStrEq( pszName, "inventory_updated" ) || FStrEq( pszName, "player_death" ) )
{
CheckForNotificationOpportunities();
}
else if ( FStrEq( pszName, "player_initial_spawn" ) )
{
CTFPlayer *pNewPlayer = ToTFPlayer( UTIL_PlayerByIndex( event->GetInt( "index" ) ) );
if ( pNewPlayer == C_BasePlayer::GetLocalPlayer() )
{
// Reset every round
m_mapNotifiedItemIDs.Purge();
m_vecNotifications.PurgeAndDeleteElements();
m_timerNotificationCooldown.Start( 0 );
m_bInitialized = false;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuestNotificationPanel::Reset()
{
CheckForNotificationOpportunities();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuestNotificationPanel::CheckForNotificationOpportunities()
{
// Suppress making new notifications while in competitive play
if ( TFGameRules() && TFGameRules()->IsCompetitiveMode() )
return;
FOR_EACH_VEC_BACK( m_vecNotifications, i )
{
// Clean up old entires for items that are now gone
if ( m_vecNotifications[i]->GetItemHandle() == NULL )
{
delete m_vecNotifications[i];
m_vecNotifications.Remove( i );
}
}
CPlayerInventory *pInv = InventoryManager()->GetLocalInventory();
Assert( pInv );
if ( pInv )
{
for ( int i = 0 ; i < pInv->GetItemCount(); ++i )
{
CEconItemView *pItem = pInv->GetItem( i );
// Check if this is a quest at all
if ( pItem->GetItemDefinition()->GetQuestDef() == NULL )
continue;
CQuestNotification* pNotification = NULL;
if ( IsUnacknowledged( pItem->GetInventoryPosition() ) )
{
pNotification = new CQuestNotification_NewQuest( pItem->GetSOCData() );
}
else if ( IsQuestItemFullyCompleted( pItem ) ) // Fully completed
{
pNotification = new CQuestNotification_FullyCompletedQuest( pItem->GetSOCData() );
}
else if ( IsQuestItemReadyToTurnIn( pItem ) ) // Ready to turn in
{
pNotification = new CQuestNotification_CompletedQuest( pItem->GetSOCData() );
}
else
{
// Clean up any pending notifications for normal quests
FOR_EACH_VEC_BACK( m_vecNotifications, j )
{
if ( m_vecNotifications[j]->GetItemHandle() == pItem->GetSOCData() )
{
delete m_vecNotifications[j];
m_vecNotifications.Remove( j );
}
}
}
if ( pNotification && !AddNotificationForItem( pItem, pNotification ) )
{
delete pNotification;
pNotification = NULL;
}
}
m_bInitialized = pInv->GetOwner().IsValid();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CQuestNotificationPanel::AddNotificationForItem( const CEconItemView *pItem, CQuestNotification* pNotification )
{
bool bTypeAlreadyInQueue = false;
// Check if there's already a notification of this type
FOR_EACH_VEC_BACK( m_vecNotifications, i )
{
// There's already a quest of this type in queue, no need to add another
if ( m_vecNotifications[i]->GetType() == pNotification->GetType() )
{
bTypeAlreadyInQueue = true;
break;
}
}
// Find the notified bits
auto idx = m_mapNotifiedItemIDs.Find( pItem->GetItemID() );
if ( idx == m_mapNotifiedItemIDs.InvalidIndex() )
{
// Create if missing
idx = m_mapNotifiedItemIDs.Insert( pItem->GetItemID() );
m_mapNotifiedItemIDs[ idx ].SetSize( CQuestNotification::NUM_NOTIFICATION_TYPES );
FOR_EACH_VEC( m_mapNotifiedItemIDs[ idx ], i )
{
m_mapNotifiedItemIDs[ idx ][ i ] = 0.f;
}
}
// Check if we've already done a notification for this type recently
if ( Plat_FloatTime() < m_mapNotifiedItemIDs[ idx ][ pNotification->GetType() ] || m_mapNotifiedItemIDs[ idx ][ pNotification->GetType() ] == NEVER_REPEAT )
{
return false;
}
bool bNotificationUsed = false;
// Don't play completed notifications unless they happen mid-play
if ( !bTypeAlreadyInQueue && ( m_bInitialized || pNotification->GetType() == CQuestNotification::NOTIFICATION_TYPE_NEW_QUEST ) )
{
// Add notification
m_vecNotifications.AddToTail( pNotification );
bNotificationUsed = true;
}
// Mark that we've created a notification of this type for this item
m_mapNotifiedItemIDs[ idx ][ pNotification->GetType() ] = pNotification->GetReplayTime() == NEVER_REPEAT ? NEVER_REPEAT : Plat_FloatTime() + pNotification->GetReplayTime();
return bNotificationUsed;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CQuestNotificationPanel::ShouldDraw()
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer )
return false;
CTFPlayer* pTFPlayer = ToTFPlayer( pPlayer );
if ( !pTFPlayer )
return false;
// Not selected a class, so they haven't joined in
if ( pTFPlayer->IsPlayerClass( 0 ) )
return false;
if ( !CHudElement::ShouldDraw() )
return false;
if ( TFGameRules() && TFGameRules()->IsCompetitiveMode() )
return false;
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuestNotificationPanel::OnThink()
{
if ( !ShouldDraw() )
return;
bool bHasStarted = m_animTimer.HasStarted();
float flShowProgress = bHasStarted ? 1.f : 0.f;
const float flTransitionTime = 0.5f;
Update();
if ( bHasStarted )
{
// Transitions
if ( m_animTimer.GetElapsedTime() < flTransitionTime )
{
flShowProgress = Bias( m_animTimer.GetElapsedTime() / flTransitionTime, 0.75f );
}
else if ( ( m_animTimer.GetRemainingTime() + 1.f ) < flTransitionTime )
{
flShowProgress = Bias( Max( 0.0f, m_animTimer.GetRemainingTime() + 1.f ) / flTransitionTime, 0.25f );
}
}
// Move the main container around
if ( m_pMainContainer )
{
int nY = g_pSpectatorGUI && g_pSpectatorGUI->IsVisible() ? g_pSpectatorGUI->GetTopBarHeight() : 0;
float flXPos = RemapValClamped( flShowProgress, 0.f, 1.f, 0.f, m_pMainContainer->GetWide() + XRES( 4 ) );
m_pMainContainer->SetPos( GetWide() - (int)flXPos, nY );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CQuestNotificationPanel::ShouldPresent()
{
if ( !m_timerNotificationCooldown.IsElapsed() )
return false;
// We need notifications!
if ( m_vecNotifications.IsEmpty() )
return false;
// It's been a few seconds since we were last shown
if ( ( Plat_FloatTime() - m_flTimeSinceLastShown ) < 1.5f )
return false;
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CQuestNotificationPanel::Update()
{
bool bAllowedToShow = ShouldPresent();
if ( bAllowedToShow && !m_bIsPresenting )
{
if ( m_vecNotifications.Head()->ShouldPresent() )
{
float flPresentTime = m_vecNotifications.Head()->Present( this );
m_animTimer.Start( flPresentTime );
m_timerHoldUp.Start( 3.f );
// Notification sound
vgui::surface()->PlaySound( "ui/quest_alert.wav" );
m_bIsPresenting = true;
}
}
else if ( !bAllowedToShow && m_bIsPresenting && m_timerHoldUp.IsElapsed() )
{
m_flTimeSinceLastShown = Plat_FloatTime();
// Play the slide-out animation
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "QuestNotification_Hide" );
m_bIsPresenting = false;
}
else if ( m_bIsPresenting ) // We are presenting a notification
{
if ( m_vecNotifications.Count() )
{
m_vecNotifications.Head()->Update( this );
// Check if the notification is done
if ( m_vecNotifications.Head()->IsDone() )
{
// Start our cooldown
m_timerNotificationCooldown.Start( 1.f );
// We're done with this notification
delete m_vecNotifications.Head();
m_vecNotifications.Remove( 0 );
}
}
}
}
@@ -0,0 +1,180 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef QUEST_NOTIFICATION_PANEL_H
#define QUEST_NOTIFICATION_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/VGUI.h>
#include "hudelement.h"
#include "vgui_controls/EditablePanel.h"
#include <../common/GameUI/cvarslider.h>
#include "vgui_controls/CheckButton.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "econ_item_inventory.h"
using namespace vgui;
#define NEVER_REPEAT -1.f
class CQuestNotificationPanel;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CQuestNotification
{
public:
CQuestNotification( CEconItem *pItem );
enum ENotificationType_t
{
NOTIFICATION_TYPE_NEW_QUEST = 0,
NOTIFICATION_TYPE_COMPLETED,
NOTIFICATION_TYPE_FULLY_COMPLETED,
NUM_NOTIFICATION_TYPES
};
virtual ~CQuestNotification() {}
virtual float Present( CQuestNotificationPanel* pNotificationPanel );
virtual void Update( CQuestNotificationPanel* pNotificationPanel ) = 0;
virtual bool IsDone() const = 0;
virtual bool ShouldPresent() const = 0;
virtual ENotificationType_t GetType() const = 0;
virtual float GetReplayTime() const = 0;
CEconItemHandle& GetItemHandle() { return m_hItem; }
protected:
CEconItemHandle m_hItem;
RealTimeCountdownTimer m_timerDialog;
RealTimeCountdownTimer m_timerShow;
};
//-----------------------------------------------------------------------------
// Notifications where we'll speak
//-----------------------------------------------------------------------------
class CQuestNotification_Speaking : public CQuestNotification
{
public:
CQuestNotification_Speaking( CEconItem *pItem );
virtual ~CQuestNotification_Speaking() {}
virtual float Present( CQuestNotificationPanel* pNotificationPanel ) OVERRIDE;
virtual void Update( CQuestNotificationPanel* pNotificationPanel ) OVERRIDE;
virtual bool IsDone() const OVERRIDE;
protected:
virtual const char *GetSoundEntry( const CQuestThemeDefinition* pTheme, int nClassIndex ) = 0;
const char *m_pszSoundToSpeak;
};
//-----------------------------------------------------------------------------
// New quest notification
//-----------------------------------------------------------------------------
class CQuestNotification_NewQuest : public CQuestNotification_Speaking
{
DECLARE_CLASS_SIMPLE( CQuestNotification_NewQuest, CQuestNotification_Speaking );
public:
CQuestNotification_NewQuest( CEconItem *pItem )
: CQuestNotification_Speaking( pItem )
{}
virtual ~CQuestNotification_NewQuest() {}
virtual bool ShouldPresent() const OVERRIDE;
ENotificationType_t GetType() const { return NOTIFICATION_TYPE_NEW_QUEST; }
virtual float GetReplayTime() const { return 300.f; }
static float k_flReplayTime;
protected:
virtual const char *GetSoundEntry( const CQuestThemeDefinition* pTheme, int nClassIndex ) OVERRIDE;
static CUtlVector< itemid_t > m_vecNotifiedItemIDs;
};
//-----------------------------------------------------------------------------
// Quest complete notification
//-----------------------------------------------------------------------------
class CQuestNotification_CompletedQuest : public CQuestNotification_Speaking
{
DECLARE_CLASS_SIMPLE( CQuestNotification_CompletedQuest, CQuestNotification_Speaking );
public:
CQuestNotification_CompletedQuest( CEconItem *pItem );
virtual ~CQuestNotification_CompletedQuest() {}
virtual bool ShouldPresent() const;
ENotificationType_t GetType() const { return NOTIFICATION_TYPE_COMPLETED; }
virtual float GetReplayTime() const { return NEVER_REPEAT; }
protected:
virtual const char *GetSoundEntry( const CQuestThemeDefinition* pTheme, int nClassIndex ) OVERRIDE;
RealTimeCountdownTimer m_PresentTimer;
};
class CQuestNotification_FullyCompletedQuest : public CQuestNotification_CompletedQuest
{
DECLARE_CLASS_SIMPLE( CQuestNotification_FullyCompletedQuest, CQuestNotification_CompletedQuest );
public:
CQuestNotification_FullyCompletedQuest( CEconItem *pItem ) : CQuestNotification_CompletedQuest( pItem )
{
}
virtual ~CQuestNotification_FullyCompletedQuest() {}
ENotificationType_t GetType() const { return NOTIFICATION_TYPE_FULLY_COMPLETED; }
protected:
virtual const char *GetSoundEntry( const CQuestThemeDefinition* pTheme, int nClassIndex ) OVERRIDE;
};
//-----------------------------------------------------------------------------
// The quest notification panel where a character tells the user about quest state
//-----------------------------------------------------------------------------
class CQuestNotificationPanel : public CHudElement, public EditablePanel
{
DECLARE_CLASS_SIMPLE( CQuestNotificationPanel, EditablePanel );
public:
CQuestNotificationPanel( const char *pszElementName );
virtual ~CQuestNotificationPanel();
virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE;
virtual void PerformLayout() OVERRIDE;
virtual void FireGameEvent( IGameEvent * event ) OVERRIDE;
virtual void Reset() OVERRIDE;
virtual bool ShouldDraw() OVERRIDE;
virtual void OnThink() OVERRIDE;
private:
bool ShouldPresent();
void Update();
void CheckForNotificationOpportunities();
bool AddNotificationForItem( const CEconItemView *pItem, CQuestNotification* pNotification );
void SetCharacterImage( const char *pszImageName );
CUtlVector< CQuestNotification* > m_vecNotifications;
float m_flTimeSinceLastShown;
bool m_bIsPresenting;
RealTimeCountdownTimer m_timerHoldUp;
RealTimeCountdownTimer m_timerNotificationCooldown;
RealTimeCountdownTimer m_animTimer;
EditablePanel *m_pMainContainer;
bool m_bInitialized;
CUtlMap< itemid_t, CCopyableUtlVector< float > > m_mapNotifiedItemIDs;
};
#endif // QUEST_NOTIFICATION_PANEL_H
@@ -0,0 +1,305 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "report_player_dialog.h"
#include "gc_clientsystem.h"
#include "ienginevgui.h"
using namespace vgui;
// in seconds
static const float MIN_REPORT_INTERVAL = 300.f;
struct ReportedPlayer_t
{
CSteamID steamID;
float flReportedTime;
};
CUtlVector< ReportedPlayer_t > vecReportedPlayers;
bool CanReportPlayer( CSteamID steamID, bool bVerbose )
{
bool bCanReport = true;
for (int i = 0; i < vecReportedPlayers.Count(); ++i)
{
if ( vecReportedPlayers[i].steamID == steamID )
{
float flTimeSinceLastReported = gpGlobals->curtime - vecReportedPlayers[i].flReportedTime;
bCanReport = flTimeSinceLastReported >= MIN_REPORT_INTERVAL;
if ( !bCanReport && bVerbose )
{
float flCooldownTime = MIN_REPORT_INTERVAL - flTimeSinceLastReported;
ConMsg( "Already reported this player. You can report this player again in %.2f seconds\n", flCooldownTime );
}
break;
}
}
return bCanReport;
}
bool ReportPlayerAccount( CSteamID steamID, int nReason )
{
if ( !steamID.IsValid() )
{
Warning( "Reporting an invalid steam ID\n" );
return false;
}
if ( !CanReportPlayer( steamID, true ) )
{
return false;
}
if ( nReason <= CMsgGC_ReportPlayer_EReason_kReason_INVALID || nReason >= CMsgGC_ReportPlayer_EReason_kReason_COUNT )
{
Assert( !"Invalid report reason" );
return false;
}
GCSDK::CProtoBufMsg< CMsgGC_ReportPlayer > msg( k_EMsgGC_ReportPlayer );
msg.Body().set_account_id_target( steamID.GetAccountID() );
msg.Body().set_reason( (CMsgGC_ReportPlayer_EReason)nReason );
GCClientSystem()->BSendMessage( msg );
ConMsg( "Report sent. Thank you.\n" );
ReportedPlayer_t reportedPlayer;
reportedPlayer.steamID = steamID;
reportedPlayer.flReportedTime = gpGlobals->curtime;
vecReportedPlayers.AddToTail( reportedPlayer );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CReportPlayerDialog::CReportPlayerDialog( vgui::Panel *parent ) : BaseClass( parent, "ReportPlayerDialog" )
{
vgui::VPANEL gameuiPanel = enginevgui->GetPanel( PANEL_GAMEUIDLL );
SetParent( gameuiPanel );
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SourceScheme.res", "Client");
SetScheme(scheme);
SetSize( 320, 270 );
SetTitle( "#GameUI_ReportPlayerCaps", true );
m_pReportButton = new Button( this, "ReportButton", "" );
m_pPlayerList = new ListPanel( this, "PlayerList" );
m_pPlayerList->AddColumnHeader( 0, "Name", "#GameUI_PlayerName", 180 );
m_pPlayerList->AddColumnHeader( 1, "Properties", "#GameUI_Properties", 80 );
m_pPlayerList->SetEmptyListText( "#GameUI_NoOtherPlayersInGame" );
m_pReasonBox = new ComboBox( this, "ReasonBox", 5, false );
LoadControlSettings( "Resource/ReportPlayerDialog.res" );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CReportPlayerDialog::~CReportPlayerDialog()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReportPlayerDialog::Activate()
{
BaseClass::Activate();
m_pPlayerList->DeleteAllItems();
static EUniverse universe = steamapicontext->SteamUtils()->GetConnectedUniverse();
for ( int i = 1; i <= engine->GetMaxClients(); i++ )
{
player_info_t pi;
if ( !engine->GetPlayerInfo( i, &pi ) )
continue;
// no need to add local player
if ( engine->GetLocalPlayer() == i )
continue;
// Already reported
CSteamID steamID( pi.friendsID, universe, k_EAccountTypeIndividual );
if ( !CanReportPlayer( steamID, false ) )
{
continue;
}
char szPlayerIndex[32];
Q_snprintf( szPlayerIndex, sizeof( szPlayerIndex ), "%d", i );
KeyValues *pData = new KeyValues( szPlayerIndex );
pData->SetString( "Name", pi.name );
pData->SetInt( "index", i );
m_pPlayerList->AddItem( pData, 0, false, false );
}
m_pReasonBox->RemoveAll();
KeyValues *pKeyValues = new KeyValues( "data" );
SetDialogVariable( "combo_label", g_pVGuiLocalize->Find( "#GameUI_ReportPlayerReason" ) );
pKeyValues->SetInt( "reason", 0 );
m_pReasonBox->AddItem( g_pVGuiLocalize->Find( "GameUI_ReportPlayer_Choose" ), pKeyValues );
pKeyValues->SetInt( "reason", 1 );
m_pReasonBox->AddItem( g_pVGuiLocalize->Find( "GameUI_ReportPlayer_Cheating" ), pKeyValues );
pKeyValues->SetInt( "reason", 2 );
m_pReasonBox->AddItem( g_pVGuiLocalize->Find( "GameUI_ReportPlayer_Idle" ), pKeyValues );
pKeyValues->SetInt( "reason", 3 );
m_pReasonBox->AddItem( g_pVGuiLocalize->Find( "GameUI_ReportPlayer_Harassment" ), pKeyValues );
pKeyValues->SetInt( "reason", 4 );
m_pReasonBox->AddItem( g_pVGuiLocalize->Find( "GameUI_ReportPlayer_Griefing" ), pKeyValues );
m_pReasonBox->SilentActivateItemByRow( 0 );
pKeyValues->deleteThis();
RefreshPlayerProperties();
m_pPlayerList->SetSingleSelectedItem( m_pPlayerList->GetItemIDFromRow( 0 ) );
OnItemSelected();
}
//-----------------------------------------------------------------------------
// Purpose: walks the players and sets their info display in the list
//-----------------------------------------------------------------------------
void CReportPlayerDialog::RefreshPlayerProperties()
{
for ( int i = 0; i <= m_pPlayerList->GetItemCount(); i++ )
{
KeyValues *pData = m_pPlayerList->GetItem( i );
if ( !pData )
continue;
int playerIndex = pData->GetInt( "index" );
player_info_t pi;
if ( !engine->GetPlayerInfo( playerIndex, &pi ) )
{
pData->SetString( "properties", "Disconnected" );
continue;
}
pData->SetString( "name", pi.name );
if ( pi.fakeplayer )
{
pData->SetString( "properties", "CPU Player" );
}
else
{
pData->SetString( "properties", "" );
}
}
m_pPlayerList->RereadAllItems();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CReportPlayerDialog::IsValidPlayerSelected()
{
bool bIsValidPlayer = false;
if ( m_pPlayerList->GetSelectedItemsCount() > 0 )
{
KeyValues *pData = m_pPlayerList->GetItem( m_pPlayerList->GetSelectedItem( 0 ) );
player_info_t pi;
bIsValidPlayer = engine->GetPlayerInfo( pData->GetInt( "index" ), &pi );
#ifdef _DEBUG
bIsValidPlayer = bIsValidPlayer && pData->GetInt( "index" ) != engine->GetLocalPlayer();
#else
bIsValidPlayer = bIsValidPlayer && !pi.fakeplayer && pData->GetInt( "index" ) != engine->GetLocalPlayer();
#endif
}
return bIsValidPlayer;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReportPlayerDialog::OnCommand( const char *command )
{
if ( !stricmp( command, "Report" ) )
{
ReportPlayer();
}
else
{
BaseClass::OnCommand( command );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReportPlayerDialog::ReportPlayer()
{
for ( int iSelectedItem = 0; iSelectedItem < m_pPlayerList->GetSelectedItemsCount(); iSelectedItem++ )
{
KeyValues *pPlayerData = m_pPlayerList->GetItem( m_pPlayerList->GetSelectedItem( iSelectedItem ) );
if ( !pPlayerData )
return;
Assert( pPlayerData->GetInt( "index" ) );
// INVALID = 0;
// CHEATING = 1;
// IDLE = 2;
// HARASSMENT = 3;
// GRIEFING = 4;
player_info_t pi;
if ( !engine->GetPlayerInfo( pPlayerData->GetInt( "index" ), &pi ) )
return;
CSteamID steamID( pi.friendsID, GetUniverse(), k_EAccountTypeIndividual );
KeyValues *pReasonData = m_pReasonBox->GetActiveItemUserData();
int nReason = ( pReasonData ) ? pReasonData->GetInt( "reason", 0 ) : 0;
ReportPlayerAccount( steamID, nReason );
Close();
return;
}
RefreshPlayerProperties();
OnItemSelected();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReportPlayerDialog::OnItemSelected()
{
RefreshPlayerProperties();
bool bReportButtonEnabled = IsValidPlayerSelected();
if ( !bReportButtonEnabled )
{
m_pReportButton->SetText( "#GameUI_ReportPlayer" );
}
// Reason selected?
KeyValues *pUserData = m_pReasonBox->GetActiveItemUserData();
bReportButtonEnabled = bReportButtonEnabled && pUserData && pUserData->GetInt( "reason", 0 ) > 0;
m_pReportButton->SetEnabled( bReportButtonEnabled );
}
//-----------------------------------------------------------------------------
// Purpose: Called when text changes in combo box
//-----------------------------------------------------------------------------
void CReportPlayerDialog::OnTextChanged( KeyValues *data )
{
Panel *pPanel = reinterpret_cast< vgui::Panel* >( data->GetPtr( "panel" ) );
vgui::ComboBox *pComboBox = dynamic_cast< vgui::ComboBox* >( pPanel );
if ( pComboBox && pComboBox == m_pReasonBox )
{
bool bReportButtonEnabled = IsValidPlayerSelected();
KeyValues *pReasonData = m_pReasonBox->GetActiveItemUserData();
bReportButtonEnabled = bReportButtonEnabled && pReasonData && pReasonData->GetInt( "reason", 0 ) > 0;
m_pReportButton->SetEnabled( bReportButtonEnabled );
}
}
@@ -0,0 +1,56 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef REPORT_PLAYER_DIALOG_H
#define REPORT_PLAYER_DIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/Frame.h"
#include "vgui_controls/ListPanel.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/ComboBox.h"
class CReportPlayerDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CReportPlayerDialog, vgui::Frame );
public:
CReportPlayerDialog( vgui::Panel *parent );
~CReportPlayerDialog();
virtual void Activate();
private:
MESSAGE_FUNC( OnItemSelected, "ItemSelected" );
MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
virtual void OnCommand( const char *command );
void ReportPlayer();
void RefreshPlayerProperties();
bool IsValidPlayerSelected();
void OnKeyCodePressed( vgui::KeyCode code )
{
if ( code == KEY_XBUTTON_B )
{
Close();
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}
vgui::ListPanel *m_pPlayerList;
vgui::Button *m_pReportButton;
vgui::ComboBox *m_pReasonBox;
};
bool ReportPlayerAccount( CSteamID steamID, int nReason );
#endif // REPORT_PLAYER_DIALOG_H
+70
View File
@@ -0,0 +1,70 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "sc_hinticon.h"
#include <vgui/IVGui.h>
#include "inputsystem/iinputsystem.h"
using namespace vgui;
DECLARE_BUILD_FACTORY( CSCHintIcon );
//-----------------------------------------------------------------------------
CSCHintIcon::CSCHintIcon( vgui::Panel *parent, const char* panelName ) :
vgui::Label( parent, panelName, L"" )
, m_bIsActionMapped( false )
, m_actionSetHandle( 0 )
{
m_szActionName[0] = '\0';
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSCHintIcon::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
auto szActionName = inResourceData->GetString( "actionName", "" );
Q_strncpy( m_szActionName, szActionName, nMaxActionNameLength );
auto szActionSet = inResourceData->GetString( "actionSet", nullptr );
if ( szActionSet )
{
m_actionSetHandle = g_pInputSystem->GetActionSetHandle( szActionSet );
}
else
{
m_actionSetHandle = 0;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSCHintIcon::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
const wchar_t* iconText = L"";
m_bIsActionMapped = false;
if ( m_actionSetHandle )
{
auto origin = g_pInputSystem->GetSteamControllerActionOrigin( m_szActionName, m_actionSetHandle );
if ( origin != k_EControllerActionOrigin_None )
{
iconText = g_pInputSystem->GetSteamControllerFontCharacterForActionOrigin( origin );
if ( iconText && iconText[0] )
{
m_bIsActionMapped = true;
}
}
}
SetText( iconText );
}
+39
View File
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Control for displaying a Steam Controller hint icon
//
// $NoKeywords: $
//=============================================================================//
#ifndef SC_HINTICON_H
#define SC_HINTICON_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/IScheme.h>
#include <vgui/KeyCode.h>
#include <KeyValues.h>
#include <vgui/IVGui.h>
#include <vgui_controls/Label.h>
class CSCHintIcon : public vgui::Label
{
public:
DECLARE_CLASS_SIMPLE( CSCHintIcon, vgui::Label );
CSCHintIcon( vgui::Panel *parent, const char *panelName );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
bool IsActionMapped() const { return m_bIsActionMapped; }
private:
bool m_bIsActionMapped;
static const int nMaxActionNameLength = 63;
char m_szActionName[nMaxActionNameLength+1];
ControllerActionSetHandle_t m_actionSetHandle;
};
#endif // SC_HINTICON_H
@@ -0,0 +1,446 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include <vgui/ILocalize.h>
#include "vgui_controls/TextEntry.h"
#include "select_player_dialog.h"
#include "tf_controls.h"
#include "c_playerresource.h"
#include "ienginevgui.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
int CSelectPlayerDialog::SortPartnerInfoFunc( const partner_info_t *pA, const partner_info_t *pB )
{
return Q_stricmp( pA->m_name.Get(), pB->m_name.Get() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CSelectPlayerDialog::CSelectPlayerDialog( vgui::Panel *parent )
: vgui::EditablePanel( parent, "SelectPlayerDialog" )
, m_bAllowSameTeam( true )
, m_bAllowOutsideServer( true )
{
if ( parent == NULL )
{
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
SetScheme(scheme);
SetProportional( true );
}
m_pSelectFromServerButton = NULL;
m_pCancelButton = NULL;
m_pButtonKV = NULL;
m_bReapplyButtonKVs = false;
for ( int i = 0; i < SPDS_NUM_STATES; i++ )
{
m_pStatePanels[i] = new vgui::EditablePanel( this, VarArgs("StatePanel%d",i) );
}
m_pPlayerList = new vgui::EditablePanel( this, "PlayerList" );
m_pPlayerListScroller = new vgui::ScrollableEditablePanel( this, m_pPlayerList, "PlayerListScroller" );
m_iCurrentState = SPDS_SELECTING_PLAYER;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CSelectPlayerDialog::~CSelectPlayerDialog( void )
{
if ( m_pButtonKV )
{
m_pButtonKV->deleteThis();
m_pButtonKV = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerDialog::Reset( void )
{
m_iCurrentState = SPDS_SELECTING_PLAYER;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerDialog::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
KeyValues *pItemKV = inResourceData->FindKey( "button_kv" );
if ( pItemKV )
{
if ( m_pButtonKV )
{
m_pButtonKV->deleteThis();
}
m_pButtonKV = new KeyValues("button_kv");
pItemKV->CopySubkeys( m_pButtonKV );
m_bReapplyButtonKVs = true;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( GetResFile() );
m_pCancelButton = dynamic_cast<CExButton*>( FindChildByName( "CancelButton" ) );
// Find all the sub buttons, and set their action signals to point to this panel
for ( int i = 0; i < SPDS_NUM_STATES; i++ )
{
int iButton = 0;
CExButton *pButton = NULL;
do
{
pButton = dynamic_cast<CExButton*>( m_pStatePanels[i]->FindChildByName( VarArgs("subbutton%d",iButton)) );
if ( pButton )
{
pButton->AddActionSignalTarget( this );
// The second button on the first state is the server button
if ( iButton == 1 )
{
m_pSelectFromServerButton = pButton;
}
iButton++;
}
} while (pButton);
}
UpdateState();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerDialog::PerformLayout( void )
{
BaseClass::PerformLayout();
// Layout the player list buttons
if ( m_pPlayerPanels.Count() )
{
int iButtonH = m_pPlayerPanels[0]->GetTall() + YRES(2);
m_pPlayerList->SetSize( m_pPlayerList->GetWide(), YRES(2) + (iButtonH * m_pPlayerPanels.Count()) );
// These need to all be layout-complete before we can position the player panels,
// because the scrollbar will cause the playerlist entries to move when it lays out.
m_pPlayerList->InvalidateLayout( true );
m_pPlayerListScroller->InvalidateLayout( true );
m_pPlayerListScroller->GetScrollbar()->InvalidateLayout( true );
for ( int i = 0; i < m_pPlayerPanels.Count(); i++ )
{
m_pPlayerPanels[i]->SetPos( 0, YRES(2) + (iButtonH * i) );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerDialog::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "cancel" ) )
{
if ( m_iCurrentState != SPDS_SELECTING_PLAYER )
{
m_iCurrentState = SPDS_SELECTING_PLAYER;
UpdateState();
return;
}
TFModalStack()->PopModal( this );
SetVisible( false );
MarkForDeletion();
if ( GetParent() )
{
PostMessage( GetParent(), new KeyValues("CancelSelection") );
}
return;
}
else if ( !Q_stricmp( command, "friends" ) )
{
m_iCurrentState = SPDS_SELECTING_FROM_FRIENDS;
UpdateState();
return;
}
else if ( !Q_stricmp( command, "server" ) )
{
m_iCurrentState = SPDS_SELECTING_FROM_SERVER;
UpdateState();
return;
}
else if ( !Q_strnicmp( command, "select_player", 13 ) )
{
int iPlayer = atoi( command + 13 ) - 1;
if ( iPlayer >= 0 && iPlayer < m_PlayerInfoList.Count() )
{
m_iCurrentState = SPDS_SELECTING_PLAYER;
OnCommand( "cancel" );
OnSelectPlayer( m_PlayerInfoList[iPlayer].m_steamID );
}
return;
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerDialog::UpdateState( void )
{
for ( int i = 0; i < SPDS_NUM_STATES; i++ )
{
if ( !m_pStatePanels[i] )
continue;
m_pStatePanels[i]->SetVisible( m_iCurrentState == i );
}
if ( m_pSelectFromServerButton )
{
m_pSelectFromServerButton->SetEnabled( engine->IsInGame() );
}
if ( m_iCurrentState == SPDS_SELECTING_PLAYER )
{
m_pCancelButton->SetText( g_pVGuiLocalize->Find( "#Cancel" ) );
}
else
{
m_pCancelButton->SetText( g_pVGuiLocalize->Find( "#TF_Back" ) );
}
switch ( m_iCurrentState )
{
case SPDS_SELECTING_FROM_FRIENDS:
SetupSelectFriends();
break;
case SPDS_SELECTING_FROM_SERVER:
SetupSelectServer( false );
break;
case SPDS_SELECTING_PLAYER:
default:
m_pPlayerListScroller->SetVisible( false );
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerDialog::SetupSelectFriends( void )
{
// @todo optional check to see if friend is on my server
if ( m_bAllowOutsideServer == false )
{
SetupSelectServer( true );
return;
}
m_PlayerInfoList.Purge();
if ( steamapicontext && steamapicontext->SteamFriends() )
{
// Get our game info so we can use that to test if our friends are connected to the same game as us
FriendGameInfo_t myGameInfo;
CSteamID mySteamID = steamapicontext->SteamUser()->GetSteamID();
steamapicontext->SteamFriends()->GetFriendGamePlayed( mySteamID, &myGameInfo );
int iFriends = steamapicontext->SteamFriends()->GetFriendCount( k_EFriendFlagImmediate );
for ( int i = 0; i < iFriends; i++ )
{
CSteamID friendSteamID = steamapicontext->SteamFriends()->GetFriendByIndex( i, k_EFriendFlagImmediate );
FriendGameInfo_t gameInfo;
if ( !AllowOutOfGameFriends() && !steamapicontext->SteamFriends()->GetFriendGamePlayed( friendSteamID, &gameInfo ) )
continue;
// Friends is in-game. Make sure it's TF2.
if ( AllowOutOfGameFriends() || (gameInfo.m_gameID.IsValid() && gameInfo.m_gameID == myGameInfo.m_gameID) )
{
const char *pszName = steamapicontext->SteamFriends()->GetFriendPersonaName( friendSteamID );
int idx = m_PlayerInfoList.AddToTail();
partner_info_t &info = m_PlayerInfoList[idx];
info.m_steamID = friendSteamID;
info.m_name = pszName;
}
}
}
UpdatePlayerList();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerDialog::SetupSelectServer( bool bFriendsOnly )
{
m_PlayerInfoList.Purge();
if ( steamapicontext && steamapicontext->SteamUtils() )
{
for( int iPlayerIndex = 1 ; iPlayerIndex <= MAX_PLAYERS; iPlayerIndex++ )
{
// find all players who are on the local player's team
int iLocalPlayerIndex = GetLocalPlayerIndex();
if( ( iPlayerIndex != iLocalPlayerIndex ) && ( g_PR->IsConnected( iPlayerIndex ) ) )
{
player_info_t pi;
if ( !engine->GetPlayerInfo( iPlayerIndex, &pi ) )
continue;
if ( !pi.friendsID )
continue;
CSteamID steamID( pi.friendsID, 1, GetUniverse(), k_EAccountTypeIndividual );
if ( bFriendsOnly )
{
EFriendRelationship eRelationship = steamapicontext->SteamFriends()->GetFriendRelationship( steamID );
if ( eRelationship != k_EFriendRelationshipFriend )
{
continue;
}
}
if ( g_PR->GetTeam( iPlayerIndex ) != TF_TEAM_RED && g_PR->GetTeam( iPlayerIndex ) != TF_TEAM_BLUE )
continue;
if ( m_bAllowSameTeam == false )
{
if ( GetLocalPlayerTeam() == g_PR->GetTeam( iPlayerIndex ) )
{
continue;
}
}
int idx = m_PlayerInfoList.AddToTail();
partner_info_t &info = m_PlayerInfoList[idx];
info.m_steamID = steamID;
info.m_name = pi.name;
}
}
}
UpdatePlayerList();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerDialog::UpdatePlayerList( void )
{
vgui::Label *pLabelEmpty = dynamic_cast<vgui::Label*>( m_pStatePanels[m_iCurrentState]->FindChildByName("EmptyPlayerListLabel") );
vgui::Label *pLabelQuery = dynamic_cast<vgui::Label*>( m_pStatePanels[m_iCurrentState]->FindChildByName("QueryLabel") );
// If we have no players in our list, show the no-player label.
if ( m_PlayerInfoList.Count() == 0 )
{
if ( pLabelEmpty )
{
pLabelEmpty->SetVisible( true );
}
if ( pLabelQuery )
{
pLabelQuery->SetVisible( false );
}
return;
}
// First, reapply any KVs we have to reapply
if ( m_bReapplyButtonKVs )
{
m_bReapplyButtonKVs = false;
if ( m_pButtonKV )
{
FOR_EACH_VEC( m_pPlayerPanels, i )
{
m_pPlayerPanels[i]->ApplySettings( m_pButtonKV );
}
}
}
// sort by name
m_PlayerInfoList.Sort( &SortPartnerInfoFunc );
// Otherwise, build the player panels from the list of steam IDs
for ( int i = 0; i < m_PlayerInfoList.Count(); i++ )
{
if ( m_pPlayerPanels.Count() <= i )
{
m_pPlayerPanels.AddToTail();
m_pPlayerPanels[i] = new CSelectPlayerTargetPanel( m_pPlayerList, VarArgs("player%d",i) );
m_pPlayerPanels[i]->GetButton()->SetCommand( VarArgs("select_player%d",i+1) );
m_pPlayerPanels[i]->GetButton()->AddActionSignalTarget( this );
m_pPlayerPanels[i]->GetAvatar()->SetShouldDrawFriendIcon( false );
m_pPlayerPanels[i]->GetAvatar()->SetMouseInputEnabled( false );
if ( m_pButtonKV )
{
m_pPlayerPanels[i]->ApplySettings( m_pButtonKV );
m_pPlayerPanels[i]->InvalidateLayout( true );
}
}
m_pPlayerPanels[i]->SetInfo( m_PlayerInfoList[i].m_steamID, m_PlayerInfoList[i].m_name );
}
m_pPlayerListScroller->GetScrollbar()->SetAutohideButtons( true );
m_pPlayerListScroller->GetScrollbar()->SetValue( 0 );
// Remove any extra player panels
for ( int i = m_pPlayerPanels.Count()-1; i >= m_PlayerInfoList.Count(); i-- )
{
m_pPlayerPanels[i]->MarkForDeletion();
m_pPlayerPanels.Remove(i);
}
if ( pLabelEmpty )
{
pLabelEmpty->SetVisible( false );
}
if ( pLabelQuery )
{
pLabelQuery->SetVisible( true );
}
m_pPlayerListScroller->SetVisible( true );
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CSelectPlayerTargetPanel::SetInfo( const CSteamID &steamID, const char *pszName )
{
if ( !steamapicontext || !steamapicontext->SteamFriends() )
return;
m_pAvatar->SetPlayer( steamID, k_EAvatarSize64x64 );
m_pButton->SetText( pszName );
}
+107
View File
@@ -0,0 +1,107 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SELECT_PLAYER_DIALOG_H
#define SELECT_PLAYER_DIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "tf_controls.h"
#include "vgui_avatarimage.h"
// Select Player Dialog states
enum
{
SPDS_SELECTING_PLAYER,
SPDS_SELECTING_FROM_FRIENDS,
SPDS_SELECTING_FROM_SERVER,
SPDS_NUM_STATES,
};
// Button that displays the name & avatar image of a potential target
class CSelectPlayerTargetPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CSelectPlayerTargetPanel, vgui::EditablePanel );
public:
CSelectPlayerTargetPanel( vgui::Panel *parent, const char *name ) : vgui::EditablePanel( parent, name )
{
m_pAvatar = new CAvatarImagePanel( this, "avatar" );
m_pButton = new CExButton( this, "button", "", parent );
}
~CSelectPlayerTargetPanel( void )
{
m_pAvatar->MarkForDeletion();
m_pButton->MarkForDeletion();
}
void SetInfo( const CSteamID &steamID, const char *pszName );
CAvatarImagePanel *GetAvatar( void ) { return m_pAvatar; }
CExButton *GetButton( void ) { return m_pButton; }
private:
// Embedded panels
CAvatarImagePanel *m_pAvatar;
CExButton *m_pButton;
};
//-----------------------------------------------------------------------------
// A dialog that allows users to select who they want to do something with
//-----------------------------------------------------------------------------
class CSelectPlayerDialog : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CSelectPlayerDialog, vgui::EditablePanel );
public:
CSelectPlayerDialog( vgui::Panel *parent );
~CSelectPlayerDialog( void );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout( void );
virtual void OnCommand( const char *command );
void UpdateState( void );
virtual void UpdatePlayerList( void );
virtual void Reset( void );
virtual void SetupSelectFriends( void );
virtual void SetupSelectServer( bool bFriendsOnly );
virtual bool AllowOutOfGameFriends() { return false; }
virtual void OnSelectPlayer( const CSteamID &steamID ) = 0;
protected:
virtual const char *GetResFile() { return "resource/ui/SelectPlayerDialog.res"; }
struct partner_info_t
{
CSteamID m_steamID;
CUtlString m_name;
};
static int SortPartnerInfoFunc( const partner_info_t *pA, const partner_info_t *pB );
vgui::EditablePanel *m_pStatePanels[SPDS_NUM_STATES];
int m_iCurrentState;
CExButton *m_pSelectFromServerButton;
CExButton *m_pCancelButton;
vgui::EditablePanel *m_pPlayerList;
vgui::ScrollableEditablePanel *m_pPlayerListScroller;
CUtlVector<partner_info_t> m_PlayerInfoList;
CUtlVector<CSelectPlayerTargetPanel*> m_pPlayerPanels;
KeyValues *m_pButtonKV;
bool m_bReapplyButtonKVs;
bool m_bAllowSameTeam;
bool m_bAllowOutsideServer;
};
#endif // SELECT_PLAYER_DIALOG_H
+96
View File
@@ -0,0 +1,96 @@
#include "cbase.h"
#include "softline.h"
#include <KeyValues.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
SoftLine::SoftLine(vgui::Panel *parent, const char *panelName, Color col) :
vgui::Panel(parent, panelName)
{
m_Color = col;
m_iCornerType = 0;
}
void SoftLine::Paint()
{
if (m_iCornerType == 1)
DrawSoftLine(1,GetTall() - 2, GetWide() - 2, 1, m_Color);
else
DrawSoftLine(1,1, GetWide() - 2, GetTall() - 2, m_Color);
}
int SoftLine::s_nWhiteTexture = -1;
void SoftLine::DrawSoftLine(float x, float y, float x2, float y2, Color c)
{
vgui::Vertex_t start, end;
if (s_nWhiteTexture == -1)
{
s_nWhiteTexture = vgui::surface()->CreateNewTextureID();
vgui::surface()->DrawSetTextureFile( s_nWhiteTexture, "vgui/white" , true, false);
if (s_nWhiteTexture == -1)
return;
return;
}
// draw main line
vgui::surface()->DrawSetTexture(s_nWhiteTexture);
vgui::surface()->DrawSetColor(c);
//vgui::surface()->DrawLine(x,y,x2,y2);
start.Init(Vector2D(x,y), Vector2D(0,0));
end.Init(Vector2D(x2,y2), Vector2D(1,1));
DrawPolygonLine(start, end);
// draw translucent ones around it to give it some softness
vgui::surface()->DrawSetColor(c);
start.Init(Vector2D(x - 0.50f,y - 0.50f), Vector2D(0,0));
end.Init(Vector2D(x2 - 0.50f,y2 - 0.50f), Vector2D(1,1));
DrawPolygonLine(start, end);
start.Init(Vector2D(x + 0.50f,y - 0.50f), Vector2D(0,0));
end.Init(Vector2D(x2 + 0.50f,y2 - 0.50f), Vector2D(1,1));
DrawPolygonLine(start, end);
start.Init(Vector2D(x - 0.50f,y + 0.50f), Vector2D(0,0));
end.Init(Vector2D(x2 - 0.50f,y2 + 0.50f), Vector2D(1,1));
DrawPolygonLine(start, end);
start.Init(Vector2D(x + 0.50f,y + 0.50f), Vector2D(0,0));
end.Init(Vector2D(x2 + 0.50f,y2 + 0.50f), Vector2D(1,1));
DrawPolygonLine(start, end);
}
// draws a line using polygon calls
void SoftLine::DrawPolygonLine(vgui::Vertex_t start, vgui::Vertex_t end, float width)
{
DrawPolygonLine(start.m_Position.x, start.m_Position.y, end.m_Position.x, end.m_Position.y, width);
}
void SoftLine::DrawPolygonLine(float x, float y, float x2, float y2, float width)
{
// find long edge
Vector2D start(x, y);
Vector2D end(x2, y2);
Vector2D long_edge = end - start;
// normalize and rotate 90 degrees to get our short edge
Vector2D short_edge = long_edge;
short_edge.NormalizeInPlace();
float newx = cos(1.5708f) * short_edge.x - sin(1.5708f) * short_edge.y;
float newy = sin(1.5708f) * short_edge.x - cos(1.5708f) * short_edge.y;
short_edge.x = newx;
short_edge.y = newy;
short_edge *= width;
vgui::Vertex_t points[4] =
{
vgui::Vertex_t( Vector2D(x, y) - short_edge * 0.5f, Vector2D(0,0) ),
vgui::Vertex_t( Vector2D(x, y) - short_edge * 0.5f + long_edge, Vector2D(1,0) ),
vgui::Vertex_t( Vector2D(x, y) + short_edge * 0.5f + long_edge, Vector2D(1,1) ),
vgui::Vertex_t( Vector2D(x, y) + short_edge * 0.5f, Vector2D(0,1) )
};
vgui::surface()->DrawTexturedPolygon(4, points);
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef _INCLUDED_SOFT_LINE_H
#define _INCLUDED_SOFT_LINE_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/VGUI.h>
#include <vgui_controls/Panel.h>
#include <vgui/ISurface.h>
// this is a vgui panel that draws a line between opposite corners
// the line is softened with translucent lines around it
class SoftLine : public vgui::Panel
{
DECLARE_CLASS_SIMPLE( SoftLine, vgui::Panel );
public:
SoftLine(vgui::Panel *parent, const char *panelName, Color col);
virtual void Paint();
void DrawSoftLine(float x, float y, float x2, float y2, Color c);
void SetCornerType(int i) { m_iCornerType = i; }
Color m_Color;
int m_iCornerType;
static int s_nWhiteTexture;
// draws a line between two points using polygon rather than line drawing functions (since line doesn't work sometimes)
static void DrawPolygonLine(float x, float y, float x2, float y2, float width=1.0f);
static void DrawPolygonLine(vgui::Vertex_t start, vgui::Vertex_t end, float width=1.0f);
};
#endif // _INCLUDED_SOFT_LINE_H
+7
View File
@@ -0,0 +1,7 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#include "store/tf_store.h"
+12
View File
@@ -0,0 +1,12 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef TF_STORE_H
#define TF_STORE_H
#ifdef _WIN32
#pragma once
#endif
#endif // TF_STORE_H
@@ -0,0 +1,278 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/tf_store_page_base.h"
//#include "store/v1/tf_store_preview_item.h"
#include "econ_item_inventory.h"
#include "store/store_viewcart.h"
#include "c_tf_freeaccount.h"
#include "rtime.h"
#include "econ_ui.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
extern const char *g_aPlayerClassNames[TF_CLASS_MENU_BUTTONS];
const char *g_szClassFilterStrings[] =
{
"", // Undefined
"#Store_Items_Scout",
"#Store_Items_Sniper",
"#Store_Items_Soldier",
"#Store_Items_Demoman",
"#Store_Items_Medic",
"#Store_Items_HWGuy",
"#Store_Items_Pyro",
"#Store_Items_Spy",
"#Store_Items_Engineer"
};
DECLARE_BUILD_FACTORY( CStorePreviewClassIcon );
ConVar tf_explanations_store( "tf_explanations_store", "0", FCVAR_ARCHIVE, "Whether the user has seen explanations for this panel." );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFStorePageBase::CTFStorePageBase(Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData, const char *pPreviewItemResFile ) : CStorePage(parent, pPageData, pPreviewItemResFile)
{
m_flStartExplanationsAt = 0;
// TF has an option for each class, all class items, all items, and an unowned item option. Let's make sure they all fit.
if ( m_pFilterComboBox )
{
m_pFilterComboBox->SetNumberOfEditLines( 12 );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePageBase::OnPageShow( void )
{
BaseClass::OnPageShow();
// If this is the first time we've opened the store, start the armory explanations
if ( !tf_explanations_store.GetBool() && m_pPageData )
{
m_flStartExplanationsAt = engine->Time() + 0.5;
vgui::ivgui()->AddTickSignal( GetVPanel() );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePageBase::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "show_explanations" ) )
{
if ( !m_flStartExplanationsAt )
{
m_flStartExplanationsAt = engine->Time();
vgui::ivgui()->AddTickSignal( GetVPanel() );
}
RequestFocus();
}
else
{
BaseClass::OnCommand( command );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePageBase::GetFiltersForDef( GameItemDefinition_t *pDef, CUtlVector<int> *pVecFilters )
{
pVecFilters->AddToTail( FILTER_ALL_ITEMS );
// Add item to unowned filter only if it doesn't belong to these categories.
const econ_store_entry_t *pEntry = EconUI()->GetStorePanel()->GetPriceSheet()->GetEntry( pDef->GetDefinitionIndex() );
if( !pEntry->IsListedInCategory( CEconStoreCategoryManager::k_CategoryID_Tools ) &&
!pEntry->IsListedInCategory( CEconStoreCategoryManager::k_CategoryID_Maps ) &&
!pEntry->IsListedInCategory( CEconStoreCategoryManager::k_CategoryID_Bundles ) &&
!pEntry->IsListedInCategory( CEconStoreCategoryManager::k_CategoryID_Collections ) )
{
bool bItemOwned = false;
int iCount = InventoryManager()->GetLocalInventory()->GetItemCount();
for ( int i = 0; i < iCount; i++ )
{
if ( InventoryManager()->GetLocalInventory()->GetItem( i )->GetItemDefIndex() == pDef->GetDefinitionIndex() )
{
bItemOwned = true;
break;
}
}
if ( !bItemOwned )
{
pVecFilters->AddToTail( FILTER_UNOWNED_ITEMS );
}
}
if ( pDef->CanBeUsedByAllClasses() )
pVecFilters->AddToTail( FILTER_ALLCLASS_ITEMS );
for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass < TF_LAST_NORMAL_CLASS; iClass++ )
{
if ( pDef->CanBeUsedByClass( iClass ) )
pVecFilters->AddToTail( iClass );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePageBase::OnItemDetails( vgui::Panel *panel )
{
CStoreItemControlsPanel *pControlsPanel = dynamic_cast< CStoreItemControlsPanel * >( panel );
if ( pControlsPanel )
{
const econ_store_entry_t *pEntry = pControlsPanel->GetItem();
if ( pEntry )
{
SelectItemPanel( pControlsPanel->GetItemModelPanel() );
PostMessage( EconUI()->GetStorePanel(), new KeyValues("ArmoryOpened", "itemdef", pEntry->GetItemDefinitionIndex() ) );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePageBase::ShowPreview( int iClass, const econ_store_entry_t* pEntry )
{
if ( iClass < TF_FIRST_NORMAL_CLASS || iClass >= TF_LAST_NORMAL_CLASS )
{
iClass = TF_CLASS_SCOUT;
}
BaseClass::ShowPreview( iClass, pEntry );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePageBase::UpdateFilterComboBox( void )
{
if ( !m_pFilterComboBox )
return;
wchar_t wzLocalized[256];
wchar_t wszCount[16];
m_pFilterComboBox->RemoveAll();
// All items
KeyValues *pKeyValues = new KeyValues( "data" );
pKeyValues->SetInt( "filter", FILTER_ALL_ITEMS );
m_pFilterComboBox->AddItem( "#Store_ClassFilter_None", pKeyValues );
#if NEWFILTER
// All classes
int nCount = m_pPrimaryFilter->GetCountForFilterItem( FILTER_ALLCLASS_ITEMS );
if ( nCount )
{
pKeyValues->SetInt( "filter", FILTER_ALLCLASS_ITEMS );
_snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", nCount );
g_pVGuiLocalize->ConstructString_safe( wzLocalized, g_pVGuiLocalize->Find( "#Store_ClassFilter_AllClasses" ), 1, wszCount );
m_pFilterComboBox->AddItem( wzLocalized, pKeyValues );
}
// Individual classes
for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass < TF_LAST_NORMAL_CLASS; iClass++ )
{
nCount = m_pPrimaryFilter->GetCountForFilterItem( iClass );
if ( !nCount )
continue;
pKeyValues->SetInt( "filter", iClass );
_snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", nCount );
g_pVGuiLocalize->ConstructString_safe( wzLocalized, g_pVGuiLocalize->Find( g_szClassFilterStrings[iClass] ), 1, wszCount );
m_pFilterComboBox->AddItem( wzLocalized, pKeyValues );
}
// Unowned item filter
nCount = m_pPrimaryFilter->GetCountForFilterItem( FILTER_UNOWNED_ITEMS );
if ( nCount )
{
pKeyValues->SetInt( "filter", FILTER_UNOWNED_ITEMS );
_snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", nCount );
g_pVGuiLocalize->ConstructString_safe( wzLocalized, g_pVGuiLocalize->Find( "#Store_Items_Unowned" ), 1, wszCount );
m_pFilterComboBox->AddItem( wzLocalized, pKeyValues );
}
#else
// All classes
if ( m_vecFilterCounts[FILTER_ALLCLASS_ITEMS] )
{
pKeyValues->SetInt( "filter", FILTER_ALLCLASS_ITEMS );
_snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", m_vecFilterCounts[FILTER_ALLCLASS_ITEMS] );
g_pVGuiLocalize->ConstructString_safe( wzLocalized, g_pVGuiLocalize->Find( "#Store_ClassFilter_AllClasses" ), 1, wszCount );
m_pFilterComboBox->AddItem( wzLocalized, pKeyValues );
}
// Individual classes
for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass < TF_LAST_NORMAL_CLASS; iClass++ )
{
if ( m_vecFilterCounts[iClass] == 0 )
continue;
pKeyValues->SetInt( "filter", iClass );
_snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", m_vecFilterCounts[iClass] );
g_pVGuiLocalize->ConstructString_safe( wzLocalized, g_pVGuiLocalize->Find( g_szClassFilterStrings[iClass] ), 1, wszCount );
m_pFilterComboBox->AddItem( wzLocalized, pKeyValues );
}
// Unowned item filter
if ( m_vecFilterCounts[FILTER_UNOWNED_ITEMS] )
{
pKeyValues->SetInt( "filter", FILTER_UNOWNED_ITEMS );
_snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", m_vecFilterCounts[FILTER_UNOWNED_ITEMS] );
g_pVGuiLocalize->ConstructString_safe( wzLocalized, g_pVGuiLocalize->Find( "#Store_Items_Unowned" ), 1, wszCount );
m_pFilterComboBox->AddItem( wzLocalized, pKeyValues );
}
#endif
pKeyValues->deleteThis();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePageBase::OnTick( void )
{
BaseClass::OnTick();
if ( m_flStartExplanationsAt && m_flStartExplanationsAt < engine->Time() )
{
m_flStartExplanationsAt = 0;
tf_explanations_store.SetValue( 1 );
CExplanationPopup *pPopup = dynamic_cast<CExplanationPopup*>( FindChildByName("StartExplanation") );
if ( pPopup )
{
pPopup->Popup();
}
}
if ( !m_flStartExplanationsAt )
{
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
}
}
@@ -0,0 +1,121 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_STORE_PAGE_H
#define TF_STORE_PAGE_H
#ifdef _WIN32
#pragma once
#endif
#include <game/client/iviewport.h>
#include "vgui_controls/PropertyPage.h"
#include <vgui_controls/Button.h>
#include <vgui_controls/ComboBox.h>
#include <vgui_controls/ImagePanel.h>
#include "econ_controls.h"
#include "econ_ui.h"
#include "econ_store.h"
#include "item_model_panel.h"
#include "store/store_page.h"
#include "tf_shareddefs.h"
class CItemModelPanel;
class CItemModelPanelToolTip;
class CTFPlayerModelPanel;
class CStorePreviewItemPanel;
class CStoreItemControlsPanel;
extern const char *g_pszTipsClassImages[];
#define FILTER_ALLCLASS_ITEMS TF_LAST_NORMAL_CLASS
#define FILTER_UNOWNED_ITEMS (TF_LAST_NORMAL_CLASS + 1)
//-----------------------------------------------------------------------------
// Purpose: A player class preview icon in the store's item preview panel
//-----------------------------------------------------------------------------
class CStorePreviewClassIcon : public CBaseStorePreviewIcon
{
DECLARE_CLASS_SIMPLE( CStorePreviewClassIcon, CBaseStorePreviewIcon );
public:
CStorePreviewClassIcon( vgui::Panel *parent, const char *name ) : CBaseStorePreviewIcon(parent,name)
{
m_pImagePanel = new vgui::ImagePanel( this, "classimage" );
m_pImagePanel->SetShouldScaleImage( true );
m_pImagePanel->SetMouseInputEnabled( false );
m_pImagePanel->SetKeyBoardInputEnabled( false );
m_iClass = 0;
}
virtual void OnCursorEntered()
{
BaseClass::OnCursorEntered();
PostActionSignal(new KeyValues("ShowClassIconMouseover", "class", m_iClass));
}
virtual void OnCursorExited()
{
BaseClass::OnCursorExited();
PostActionSignal(new KeyValues("HideClassIconMouseover"));
}
virtual void OnMouseReleased(vgui::MouseCode code)
{
BaseClass::OnMouseReleased(code);
PostActionSignal(new KeyValues("ClassIconSelected", "class", m_iClass));
}
virtual void SetInternalImageBounds( int iX, int iY, int iWide, int iTall )
{
m_pImagePanel->SetBounds( iX, iY, iWide, iTall );
}
void SetClass( int iClass )
{
if ( iClass >= TF_FIRST_NORMAL_CLASS && iClass < TF_LAST_NORMAL_CLASS )
{
m_pImagePanel->SetImage( g_pszTipsClassImages[iClass] );
}
else
{
m_pImagePanel->SetImage( "class_portraits/all_class" );
}
m_iClass = iClass;
}
int GetClass( void ) { return m_iClass; }
private:
vgui::ImagePanel *m_pImagePanel;
int m_iClass;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePageBase : public CStorePage
{
DECLARE_CLASS_SIMPLE( CTFStorePageBase, CStorePage );
protected:
// CTFStorePageBase should not be instantiated directly
CTFStorePageBase( Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData, const char *pPreviewItemResFile = NULL );
public:
virtual void OnCommand( const char *command );
virtual void ShowPreview( int iClass, const econ_store_entry_t* pEntry );
MESSAGE_FUNC( OnPageShow, "PageShow" );
MESSAGE_FUNC_PTR( OnItemDetails, "ItemDetails", panel );
virtual void UpdateFilterComboBox( void );
virtual void GetFiltersForDef( GameItemDefinition_t *pDef, CUtlVector<int> *pVecFilters );
virtual void OnTick( void );
virtual int GetNumPrimaryFilters( void ) { return FILTER_UNOWNED_ITEMS+1; }
protected:
float m_flStartExplanationsAt;
};
#endif // TF_STORE_PAGE_H
@@ -0,0 +1,133 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/tf_store_panel_base.h"
#include "vgui/IInput.h"
#include "iclientmode.h"
#include "econ_item_system.h"
#include "econ_notifications.h"
#include "c_tf_freeaccount.h"
#include <vgui_controls/AnimationController.h>
#include "charinfo_armory_subpanel.h"
#include "backpack_panel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
class CServerNotConnectedToSteamDialog;
CServerNotConnectedToSteamDialog *OpenServerNotConnectedToSteamDialog( vgui::Panel *pParent );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFBaseStorePanel::CTFBaseStorePanel( Panel *parent ) : CStorePanel(parent)
{
m_pArmoryPanel = new CArmoryPanel( this, "armory_panel" );
m_pNotificationsPresentPanel = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFBaseStorePanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_pNotificationsPresentPanel = FindChildByName( "NotificationsPresentPanel" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFBaseStorePanel::OnArmoryOpened( KeyValues *data )
{
int iItemDef = data->GetInt( "itemdef", 0 );
// If it's a bundle, open the armory to a custom page showing all the items in the bundle
CEconItemDefinition *pDef = ItemSystem()->GetStaticDataForItemByDefIndex( iItemDef );
if ( pDef )
{
const bundleinfo_t *pBundleInfo = pDef->GetBundleInfo();
if ( pBundleInfo )
{
CUtlVector<item_definition_index_t> vecItems;
FOR_EACH_VEC( pBundleInfo->vecItemDefs, j )
{
if ( pBundleInfo->vecItemDefs[j] )
{
vecItems.AddToTail( pBundleInfo->vecItemDefs[j]->GetDefinitionIndex() );
}
}
m_pArmoryPanel->ShowPanel( pDef->GetItemBaseName(), &vecItems );
m_pArmoryPanel->MoveToFront();
return;
}
}
m_pArmoryPanel->ShowPanel( iItemDef );
m_pArmoryPanel->MoveToFront();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFBaseStorePanel::OnArmoryClosed( void )
{
PostMessage( m_pArmoryPanel, new KeyValues("Closing") );
m_pArmoryPanel->SetVisible( false );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFBaseStorePanel::OnThink()
{
bool bShouldBeVisible = NotificationQueue_GetNumNotifications() != 0;
if ( m_pNotificationsPresentPanel != NULL && m_pNotificationsPresentPanel->IsVisible() != bShouldBeVisible )
{
m_pNotificationsPresentPanel->SetVisible( bShouldBeVisible );
if ( bShouldBeVisible )
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "NotificationsPresentBlink" );
}
else
{
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "NotificationsPresentBlinkStop" );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFBaseStorePanel::PostTransactionCompleted( void )
{
// pop this dialog up
if ( NeedsToChooseMostHelpfulFriend() )
{
// update main menu
IGameEvent *event = gameeventmanager->CreateEvent( "store_pricesheet_updated" );
if ( event )
{
gameeventmanager->FireEventClientSide( event );
}
}
EconUI()->GetBackpackPanel()->CheckForQuickOpenKey();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFBaseStorePanel::SetTransactionID( uint64 inID )
{
BaseClass::SetTransactionID( inID );
EconUI()->GetBackpackPanel()->SetCurrentTransactionID( inID );
}
@@ -0,0 +1,54 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_STORE_PANEL_BASE_H
#define TF_STORE_PANEL_BASE_H
#ifdef _WIN32
#pragma once
#endif
#include "store/store_panel.h"
class CArmoryPanel;
class CStorePage;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFBaseStorePanel : public CStorePanel
{
DECLARE_CLASS_SIMPLE( CTFBaseStorePanel, CStorePanel );
protected:
// CTFBaseStorePanel should not be instantiated directly
CTFBaseStorePanel( Panel *parent );
public:
// UI Layout
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnThink();
// GC Management
virtual void PostTransactionCompleted( void );
// Cart Management
CStoreCart *GetCart( void ) { return &m_Cart; }
void ShowStorePanel( void );
void InitiateCheckout( void );
void CheckoutCancel( void );
virtual void SetTransactionID( uint64 inID ) OVERRIDE;
// Armory management
MESSAGE_FUNC_PARAMS( OnArmoryOpened, "ArmoryOpened", data );
MESSAGE_FUNC( OnArmoryClosed, "ArmoryClosed" );
private:
CArmoryPanel *m_pArmoryPanel;
vgui::Panel *m_pNotificationsPresentPanel;
};
#endif // TF_STORE_PANEL_BASE_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,102 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_STORE_PREVIEW_ITEM_BASE_H
#define TF_STORE_PREVIEW_ITEM_BASE_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Panel.h>
#include "store/store_preview_item.h"
#include "store/v1/tf_store_page.h"
#include "tf_shareddefs.h"
#include "tf_hud_mainmenuoverride.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePreviewItemPanelBase : public CStorePreviewItemPanel
{
DECLARE_CLASS_SIMPLE( CTFStorePreviewItemPanelBase, CStorePreviewItemPanel );
protected:
// CTFStorePreviewItemPanelBase should not be intantiated directly
CTFStorePreviewItemPanelBase( vgui::Panel *pParent, const char *pResFile, const char *pPanelName, CStorePage *pOwner );
public:
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnCommand( const char *command );
virtual void PerformLayout( void );
virtual void OnTick( void );
virtual void PreviewItem( int iClass, CEconItemView *pItem, const econ_store_entry_t* pEntry=NULL ) OVERRIDE;
virtual void SetState( preview_state_t iState );
virtual int GetPreviewTeam() const;
MESSAGE_FUNC_PARAMS( OnClassIconSelected, "ClassIconSelected", data );
MESSAGE_FUNC( OnHideClassIconMouseover, "HideClassIconMouseover" );
MESSAGE_FUNC_PARAMS( OnShowClassIconMouseover, "ShowClassIconMouseover", data );
protected:
void UpdateModelPanel();
virtual void SetPlayerModelVisible( bool bVisible );
virtual void UpdatePlayerModelButtons( void );
virtual void UpdateCustomizeMenu( void );
void UpdateOptionsButton( void );
void UpdateNextWeaponButton( void );
void UpdateZoomButton( void );
void UpdateTeamButton( void );
virtual void UpdateIcons( void );
void SetPaint( item_definition_index_t iItemDef );
void SetStyle( style_index_t unStyle );
void SetUnusual( uint32 iUnusualIndex );
const CUtlVector< int > *GetUnusualList() const;
virtual bool AllowUnusualPreview() const
{
#ifdef STAGING_ONLY
// we want to be able to use this everywhere in staging for testing purpose
return true;
#else
return false;
#endif
}
void CyclePaint( bool bActuallyCycle = true );
void CycleStyle( void );
void ResetHandles( void );
// This can be overridden to capture *any* "cycle text" that is being set, so one generic label can be used
// by a derived class if needed. Base version just sets the label's text.
virtual void SetCycleLabelText( vgui::Label *pTargetLabel, const char *pCycleText );
vgui::Label *m_pClassIconMouseoverLabel;
CTFPlayerModelPanel *m_pPlayerModelPanel;
CUtlVector<CStorePreviewClassIcon*> m_pClassIcons;
int m_iCurrentClass;
int m_iCurrentHeldItem;
item_definition_index_t m_unPaintDef;
uint32 m_unPaintRGB0;
uint32 m_unPaintRGB1;
CExButton *m_pRotRightButton;
CExButton *m_pRotLeftButton;
CExButton *m_pNextWeaponButton;
CExButton *m_pZoomButton;
CExButton *m_pOptionsButton;
CExButton *m_pTeamButton;
vgui::Label *m_pPaintNameLabel;
vgui::Label *m_pStyleNameLabel;
Menu *m_pCustomizeMenu;
CUtlVector< item_definition_index_t > m_vecPaintCans;
};
#endif // TF_STORE_PREVIEW_ITEM_H
@@ -0,0 +1,96 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/v1/tf_store_page.h"
#include "store/v1/tf_store_preview_item.h"
#include "c_tf_freeaccount.h"
#include "store/store_panel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFStorePage1::CTFStorePage1(Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData, const char *pPreviewItemResFile ) : BaseClass(parent, pPageData, pPreviewItemResFile)
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CTFStorePage1::GetPageResFile( void )
{
Assert( !"No code should currently reference the old store!" );
return m_pPageData->m_pchPageRes;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage1::OnPageShow( void )
{
BaseClass::OnPageShow();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage1::OnCommand( const char *command )
{
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage1::OnItemDetails( vgui::Panel *panel )
{
BaseClass::OnItemDetails( panel );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage1::ShowPreview( int iClass, const econ_store_entry_t* pEntry )
{
BaseClass::ShowPreview( iClass, pEntry );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage1::UpdateFilterComboBox( void )
{
BaseClass::UpdateFilterComboBox();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage1::GetFiltersForDef( GameItemDefinition_t *pDef, CUtlVector<int> *pVecFilters )
{
return BaseClass::GetFiltersForDef( pDef, pVecFilters );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage1::OnTick( void )
{
BaseClass::OnTick();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStorePreviewItemPanel *CTFStorePage1::CreatePreviewPanel( void )
{
return new CTFStorePreviewItemPanel1( this, m_pPreviewItemResFile, "storepreviewitem", this );
}
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_STORE_PAGE1_H
#define TF_STORE_PAGE1_H
#ifdef _WIN32
#pragma once
#endif
#include "store/tf_store_page_base.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePage1 : public CTFStorePageBase
{
DECLARE_CLASS_SIMPLE( CTFStorePage1, CTFStorePageBase );
public:
CTFStorePage1( Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData, const char *pPreviewItemResFile = NULL );
virtual const char *GetPageResFile( void );
virtual void OnCommand( const char *command );
virtual void ShowPreview( int iClass, const econ_store_entry_t* pEntry );
MESSAGE_FUNC( OnPageShow, "PageShow" );
MESSAGE_FUNC_PTR( OnItemDetails, "ItemDetails", panel );
virtual void UpdateFilterComboBox( void );
virtual void GetFiltersForDef( GameItemDefinition_t *pDef, CUtlVector<int> *pVecFilters );
virtual void OnTick( void );
virtual CStorePreviewItemPanel *CreatePreviewPanel( void );
};
#endif // TF_STORE_PAGE1_H
@@ -0,0 +1,30 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/v1/tf_store_page_maps.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFStorePage_Maps::CTFStorePage_Maps( Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData )
: BaseClass( parent, pPageData, "Resource/UI/econ/store/v1/StorePreviewItemPanel_Maps.res" )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage_Maps::OnPageShow()
{
BaseClass::OnPageShow();
SetDetailsVisible( false );
}
@@ -0,0 +1,33 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef STORE_PAGE_MAPS_H
#define STORE_PAGE_MAPS_H
#ifdef _WIN32
#pragma once
#endif
#include "store/v1/tf_store_page.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePage_Maps : public CTFStorePage1
{
DECLARE_CLASS_SIMPLE( CTFStorePage_Maps, CTFStorePage1 );
public:
CTFStorePage_Maps( Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData );
virtual ~CTFStorePage_Maps() {}
virtual const char* GetPageResFile() { return "Resource/UI/econ/store/v1/StorePage_Maps.res"; }
virtual void OnPageShow( void );
protected:
};
#endif // STORE_PAGE_MAPS_H
@@ -0,0 +1,69 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/v1/tf_store_page.h"
#include "store/v1/tf_store_panel.h"
#include "store/store_page_halloween.h"
#include "store/store_page_new.h"
#include "store/v1/tf_store_page_maps.h"
#include "store/store_viewcart.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFStorePanel1::CTFStorePanel1( vgui::Panel *parent ) : CTFBaseStorePanel(parent)
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePanel1::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePanel1::OnThink()
{
BaseClass::OnThink();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePanel1::PostTransactionCompleted( void )
{
BaseClass::PostTransactionCompleted();
}
//-----------------------------------------------------------------------------
// Purpose: Static store page factory.
//-----------------------------------------------------------------------------
CStorePage *CTFStorePanel1::CreateStorePage( const CEconStoreCategoryManager::StoreCategory_t *pPageData )
{
if ( pPageData )
{
if ( !Q_strcmp( pPageData->m_pchPageClass, "CStorePage_SpecialPromo" ) )
return new CTFStorePage_SpecialPromo( this, pPageData );
if ( !Q_strcmp( pPageData->m_pchPageClass, "CStorePage_Maps" ) )
return new CTFStorePage_Maps( this, pPageData );
if ( !Q_strcmp( pPageData->m_pchPageClass, "CStorePage_Popular" ) )
return new CTFStorePage_Popular( this, pPageData );
}
// Default, standard store page.
return new CTFStorePage1( this, pPageData );
}
@@ -0,0 +1,38 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_STORE_PANEL1_H
#define TF_STORE_PANEL1_H
#ifdef _WIN32
#pragma once
#endif
#include "store/tf_store_panel_base.h"
class CStorePage;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePanel1 : public CTFBaseStorePanel
{
DECLARE_CLASS_SIMPLE( CTFStorePanel1, CTFBaseStorePanel );
public:
CTFStorePanel1( vgui::Panel *parent );
// UI Layout
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnThink();
// GC Management
virtual void PostTransactionCompleted( void );
private:
virtual CStorePage *CreateStorePage( const CEconStoreCategoryManager::StoreCategory_t *pPageData );
};
#endif // TF_STORE_PANEL1_H
@@ -0,0 +1,100 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/v1/tf_store_preview_item.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFStorePreviewItemPanel1::CTFStorePreviewItemPanel1( vgui::Panel *pParent, const char *pResFile, const char *pPanelName, CStorePage *pOwner )
: BaseClass( pParent, pResFile, "storepreviewitem", pOwner )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::PerformLayout( void )
{
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::OnCommand( const char *command )
{
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::OnClassIconSelected( KeyValues *data )
{
BaseClass::OnClassIconSelected( data );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::OnHideClassIconMouseover( void )
{
BaseClass::OnHideClassIconMouseover();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::OnShowClassIconMouseover( KeyValues *data )
{
BaseClass::OnShowClassIconMouseover( data );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::PreviewItem( int iClass, CEconItemView *pItem, const econ_store_entry_t* pEntry )
{
BaseClass::PreviewItem( iClass, pItem, pEntry );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::SetState( preview_state_t iState )
{
BaseClass::SetState( iState );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::UpdateIcons( void )
{
BaseClass::UpdateIcons();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePreviewItemPanel1::OnTick( void )
{
BaseClass::OnTick();
}
@@ -0,0 +1,41 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_STORE_PREVIEW_ITEM1_H
#define TF_STORE_PREVIEW_ITEM1_H
#ifdef _WIN32
#pragma once
#endif
#include "store/tf_store_preview_item_base.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePreviewItemPanel1 : public CTFStorePreviewItemPanelBase
{
DECLARE_CLASS_SIMPLE( CTFStorePreviewItemPanel1, CTFStorePreviewItemPanelBase );
public:
CTFStorePreviewItemPanel1( vgui::Panel *pParent, const char *pResFile, const char *pPanelName, CStorePage *pOwner );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnCommand( const char *command );
virtual void PerformLayout( void );
virtual void OnTick( void );
virtual void PreviewItem( int iClass, CEconItemView *pItem, const econ_store_entry_t* pEntry=NULL ) OVERRIDE;
virtual void SetState( preview_state_t iState );
MESSAGE_FUNC_PARAMS( OnClassIconSelected, "ClassIconSelected", data );
MESSAGE_FUNC( OnHideClassIconMouseover, "HideClassIconMouseover" );
MESSAGE_FUNC_PARAMS( OnShowClassIconMouseover, "ShowClassIconMouseover", data );
private:
virtual void UpdateIcons( void );
};
#endif // TF_STORE_PREVIEW_ITEM1_H
@@ -0,0 +1,83 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/v2/tf_store_mapstamps_info_dialog.h"
#include "tf_mouseforwardingpanel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
DECLARE_BUILD_FACTORY( CTFMapStampsInfoDialog );
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFMapStampsInfoDialog::CTFMapStampsInfoDialog( vgui::Panel *pParent, const char *pName )
: BaseClass( pParent, "MapStampsInfoDialog" )
{
m_pBgPanel = new CMouseMessageForwardingPanel( this, "BgPanel" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFMapStampsInfoDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/econ/store/v2/StoreMapStampsInfoDialog.res" );
m_pDlgFrame = dynamic_cast<EditablePanel *>( FindChildByName( "DialogFrame" ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFMapStampsInfoDialog::PerformLayout( void )
{
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFMapStampsInfoDialog::OnCommand( const char *command )
{
if ( !V_strnicmp( command, "close", 5 ) )
{
DoClose();
}
else
{
BaseClass::OnCommand( command );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFMapStampsInfoDialog::OnMouseReleased(MouseCode code)
{
BaseClass::OnMouseReleased( code );
if ( m_pDlgFrame && !m_pDlgFrame->IsCursorOver() )
{
DoClose();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFMapStampsInfoDialog::DoClose()
{
SetVisible( false );
MarkForDeletion();
}
@@ -0,0 +1,36 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_MAPS_INFO_DIALOG_H
#define TF_MAPS_INFO_DIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFMapStampsInfoDialog : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CTFMapStampsInfoDialog, vgui::EditablePanel );
public:
CTFMapStampsInfoDialog( vgui::Panel *pParent, const char *pName = "" );
void DoClose();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnCommand( const char *command );
virtual void PerformLayout( void );
virtual void OnMouseReleased(vgui::MouseCode code);
Panel *m_pBgPanel;
EditablePanel *m_pDlgFrame;
};
#endif // TF_MAPS_INFO_DIALOG_H
@@ -0,0 +1,849 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/v2/tf_store_page2.h"
#include "store/v2/tf_store_preview_item2.h"
#include "c_tf_freeaccount.h"
#include "store/store_panel.h"
#include "store/tf_store.h"
#include "navigationpanel.h"
#include "econ/store/store_page_new.h"
#include "econ_item_system.h"
#include "c_tf_gamestats.h"
#include "vgui_controls/TextImage.h"
#include "econ_item_description.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
static const int kNumSortTypes = 5;
ItemSortTypeData_t g_StoreSortTypes[ kNumSortTypes ] =
{
{ "#Store_SortType_DateNewest", kEconStoreSortType_DateNewest },
{ "#Store_SortType_DateOldest", kEconStoreSortType_DateOldest },
{ "#Store_SortType_HighestPrice", kEconStoreSortType_Price_HighestToLowest },
{ "#Store_SortType_LowestPrice", kEconStoreSortType_Price_LowestToHighest },
{ "#Store_SortType_Alphabetical", kEconStoreSortType_Name_AToZ },
};
class CClassFilterTooltip : public vgui::BaseTooltip
{
public:
CClassFilterTooltip( CTFStorePage2 *pStorePage )
: BaseTooltip( pStorePage )
, m_pStorePage( pStorePage )
{
}
CTFStorePage2 *m_pStorePage;
virtual void SetText(const char *text)
{
m_pStorePage->m_pClassFilterTooltipLabel->SetText( text );
}
virtual void ShowTooltip(Panel *currentPanel)
{
int x = 0;
int y = currentPanel->GetTall();
currentPanel->LocalToScreen( x, y );
m_pStorePage->ScreenToLocal( x, y );
// The tooltip wants to be centered around the given panel, but it's constrained by the left and right boundaries
// of the navigation panel.
if ( m_pStorePage->m_pClassFilterButtons )
{
// Right side of tooltip should not pass right boundary of nav panel
int aClassFilterNavPos[2] = { 0, 0 };
m_pStorePage->m_pClassFilterButtons->GetPos( aClassFilterNavPos[0], aClassFilterNavPos[1] );
const int nTipWide = m_pStorePage->m_pClassFilterTooltipLabel->GetWide();
x = clamp(
x + ( currentPanel->GetWide() - nTipWide ) / 2,
aClassFilterNavPos[0],
aClassFilterNavPos[0] + m_pStorePage->m_pClassFilterButtons->GetWide() - nTipWide );
}
m_pStorePage->m_pClassFilterTooltipLabel->SetPos( x, y );
m_pStorePage->m_pClassFilterTooltipLabel->SetVisible( true );
}
virtual void HideTooltip()
{
m_pStorePage->m_pClassFilterTooltipLabel->SetVisible( false );
}
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFStorePage2::CTFStorePage2(Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData, const char *pPreviewItemResFile )
: BaseClass( parent, pPageData, pPreviewItemResFile ),
m_pSubcategoriesFilterCombo( NULL ),
m_pSortByCombo( NULL ),
m_pHomeCategoryTabs( NULL ),
m_pClassFilterButtons( NULL ),
m_pNameFilterTextEntry( NULL ),
m_pSubcategoriesFilterLabel( NULL ),
m_iCurrentSubcategory( 2 ), // Switch to Featured items tab on home page when store launches; BRETT SAID I COULD DO THIS
m_pClassFilterTooltipLabel( NULL ),
m_pClassFilterTooltip( NULL ),
m_flFilterItemTime( 0.0f )
{
const CEconStorePriceSheet *pPriceSheet = EconUI()->GetStorePanel()->GetPriceSheet();
if ( IsHomePage() )
{
bool bAtLeastOneItemIsOnSale = false;
if ( pPriceSheet )
{
const CEconStorePriceSheet::StoreEntryMap_t& mapStoreEntries = pPriceSheet->GetEntries();
FOR_EACH_MAP_FAST( mapStoreEntries, i )
{
if ( mapStoreEntries[i].IsOnSale( EconUI()->GetStorePanel()->GetCurrency() ) )
{
bAtLeastOneItemIsOnSale = true;
break;
}
}
}
m_pHomeCategoryTabs = new CNavigationPanel( this, "ItemCategoryTabs" );
FOR_EACH_VEC( m_pPageData->m_vecSubcategories, i )
{
// Skip over adding the "On Sale!" tab if no items are currently on sale.
const char *pchName = m_pPageData->m_vecSubcategories[i]->m_pchName;
bool bIsOnSaleCategory = m_pPageData->m_vecSubcategories[i]->m_unID == CEconStoreCategoryManager::k_CategoryID_OnSale;
// Skip over the "Top Sellers" tab as we're replacing it with the 'Starter Packs' tab for now
bool bIsPopularCategory = m_pPageData->m_vecSubcategories[i]->m_unID == CEconStoreCategoryManager::k_CategoryID_Popular;
// Skip over the "New" tab as we're replacing it with the 'Featured' tab for now
bool bIsNew = m_pPageData->m_vecSubcategories[i]->m_unID == CEconStoreCategoryManager::k_CategoryID_New;
// We include all of the sale items in the Featured tab currently, so we don't need to add these categories back in at the moment
bAtLeastOneItemIsOnSale = false;
if ( ( !bIsPopularCategory && !bIsOnSaleCategory && !bIsNew ) || ( bAtLeastOneItemIsOnSale && bIsOnSaleCategory ) )
{
m_pHomeCategoryTabs->AddButton( i, pchName );
}
}
}
}
//-----------------------------------------------------------------------------
CTFStorePage2::~CTFStorePage2()
{
delete m_pClassFilterTooltip;
m_pClassFilterTooltip = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::OnPostCreate()
{
BaseClass::OnPostCreate();
m_bShouldDeletePreviewPanel = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CTFStorePage2::HasSubcategories() const
{
return m_pPageData && m_pPageData->HasSubcategories();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::PerformLayout()
{
BaseClass::PerformLayout();
if ( m_pSubcategoriesFilterCombo )
{
m_pSubcategoriesFilterCombo->SetVisible( HasSubcategories() );
}
if ( m_pSubcategoriesFilterLabel )
{
m_pSubcategoriesFilterLabel->SetVisible( HasSubcategories() );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_pNameFilterTextEntry = FindControl<vgui::TextEntry>( "NameFilterTextEntry" );
if ( m_pNameFilterTextEntry )
{
m_pNameFilterTextEntry->AddActionSignalTarget( this );
}
m_pSortByCombo = dynamic_cast< ComboBox * >( FindChildByName( "SortFilterComboBox" ) );
if ( m_pSortByCombo )
{
m_pSortByCombo->RemoveAll();
vgui::HFont hFont = pScheme->GetFont( "HudFontSmallestBold", true );
m_pSortByCombo->SetFont( hFont );
KeyValues *pKeyValues = new KeyValues( "data" );
for ( int i = 0; i < ARRAYSIZE(g_StoreSortTypes); i++ )
{
pKeyValues->SetInt( "sortby", i );
m_pSortByCombo->AddItem( g_StoreSortTypes[i].szSortDesc, pKeyValues );
}
pKeyValues->deleteThis();
m_pSortByCombo->ActivateItemByRow( 0 );
}
m_pSubcategoriesFilterCombo = dynamic_cast< ComboBox * >( FindChildByName( "SubcategoryFilterComboBox" ) );
if ( m_pSubcategoriesFilterCombo )
{
vgui::HFont hFont = pScheme->GetFont( "HudFontSmallestBold", true );
m_pSubcategoriesFilterCombo->SetFont( hFont );
m_pSubcategoriesFilterCombo->RemoveAll();
if ( m_pPageData )
{
// Add "all items" explicitly
KeyValuesAD kvAllItems( "data" );
kvAllItems->SetInt( "index", GetNumSubcategories() );
m_pSubcategoriesFilterCombo->AddItem( "#Store_ClassFilter_None", kvAllItems );
FOR_EACH_VEC( m_pPageData->m_vecSubcategories, i )
{
KeyValues *pData = new KeyValues( "data" );
pData->SetInt( "index", i );
m_pSubcategoriesFilterCombo->AddItem( m_pPageData->m_vecSubcategories[i]->m_pchName, pData );
pData->deleteThis();
}
}
// Move to "All items" selected
m_pSubcategoriesFilterCombo->ActivateItemByRow( 0 );
m_pSubcategoriesFilterCombo->GetComboButton()->SetFgColor( Color( 117,107,94,255 ) );
m_pSubcategoriesFilterCombo->GetComboButton()->SetDefaultColor( Color( 117,107,94,255), Color( 0,0,0,0) );
m_pSubcategoriesFilterCombo->GetComboButton()->SetArmedColor( Color( 117,107,94,255), Color( 0,0,0,0) );
m_pSubcategoriesFilterCombo->GetComboButton()->SetDepressedColor( Color( 117,107,94,255), Color( 0,0,0,0) );
}
m_pClassFilterButtons = dynamic_cast< CNavigationPanel * >( FindChildByName( "ClassFilterNavPanel" ) );
m_pSubcategoriesFilterLabel = dynamic_cast< CExLabel * >( FindChildByName( "SubcategoryFiltersLabel" ) );
m_pClassFilterTooltipLabel = dynamic_cast< CExLabel * >( FindChildByName( "ClassFilterTooltipLabel" ) );
if ( m_pClassFilterTooltipLabel && m_pClassFilterButtons )
{
m_pClassFilterTooltip = new CClassFilterTooltip(this);
for ( int i = 0 ; i < m_pClassFilterButtons->NumButtons() ; ++i )
{
CExButton *pButton = m_pClassFilterButtons->GetButton( i );
CUtlString sSaveText = pButton->GetEffectiveTooltipText();
pButton->SetTooltip( m_pClassFilterTooltip, sSaveText );
}
}
// Setup title text in home page
if ( IsHomePage() && g_pVGuiLocalize )
{
CExLabel *pTitleLabel = dynamic_cast<CExLabel *>( FindChildByName( "TitleLabel" ) );
wchar_t *pHomePageTitle = g_pVGuiLocalize->Find( "#Store_HomePageTitle" );
wchar_t *pRedText = g_pVGuiLocalize->Find( "#Store_HomePageTitleRedText" );
if ( pTitleLabel && pHomePageTitle && pRedText )
{
const store_promotion_spend_for_free_item_t *pPromotion = EconUI()->GetStorePanel()->GetPriceSheet()->GetStorePromotion_SpendForFreeItem();
ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency();
AssertMsg( eCurrency >= k_ECurrencyUSD && eCurrency < k_ECurrencyMax, "Invalid currency!" );
int iPriceThreshold = pPromotion->m_rgusPriceThreshold[ eCurrency ];
wchar_t wszPriceThreshold[ kLocalizedPriceSizeInChararacters ];
MakeMoneyString( wszPriceThreshold, ARRAYSIZE( wszPriceThreshold ), iPriceThreshold, EconUI()->GetStorePanel()->GetCurrency() );
static wchar_t wszText[512];
g_pVGuiLocalize->ConstructString_safe( wszText, pHomePageTitle, 2, pRedText, wszPriceThreshold );
pTitleLabel->SetText( wszText );
TextImage *pTextImage = pTitleLabel->GetTextImage();
const wchar_t *pFound = wcsstr( wszText, pRedText );
if ( pTextImage && pFound )
{
const int iRedTextPos = pFound - wszText;
const int nRedTextLen = wcslen( pRedText );
pTextImage->ClearColorChangeStream();
pTextImage->AddColorChange( Color(200,80,60,255), iRedTextPos );
pTextImage->AddColorChange( pTitleLabel->GetFgColor(), iRedTextPos + nRedTextLen );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CTFStorePage2::GetPageResFile( void )
{
if ( IsHomePage() )
{
Assert( ShouldUseNewStore() );
return "Resource/UI/econ/store/v2/StoreHome_Premium.res";
}
return m_pPageData->m_pchPageRes;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::OnPageShow( void )
{
BaseClass::OnPageShow();
if ( m_pClassFilterButtons )
{
m_pClassFilterButtons->UpdateButtonSelectionStates( 0 );
}
ClearNameFilter( true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::OnCommand( const char *command )
{
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::OnItemDetails( vgui::Panel *panel )
{
CStoreItemControlsPanel *pControlsPanel = dynamic_cast< CStoreItemControlsPanel * >( panel );
if ( pControlsPanel )
{
const econ_store_entry_t *pEntry = pControlsPanel->GetItem();
if ( pEntry && m_pPreviewPanel )
{
ShowPreviewWindow( pEntry->GetItemDefinitionIndex() );
}
}
}
//-----------------------------------------------------------------------------
void CTFStorePage2::OnItemDefDetails( KeyValues *pData )
{
ShowPreviewWindow( pData->GetInt("ItemDefIndex", -1) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::ShowPreviewWindow( item_definition_index_t usDefIndex )
{
if ( m_pPreviewPanel )
{
CEconItemView itemData;
itemData.Init( usDefIndex, AE_UNIQUE, AE_USE_SCRIPT_VALUE, true );
itemData.SetClientItemFlags( kEconItemFlagClient_Preview );
m_pPreviewPanel->PreviewItem( 0, &itemData );
m_pPreviewPanel->SetState( PS_ITEM ); // Adding this, since without it, only the item icon shows up
m_pPreviewPanel->SetVisible( true );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::OnNavButtonSelected( KeyValues *pData )
{
Panel *pPanel = (Panel *)pData->GetPtr( "panel" );
if ( pPanel == m_pClassFilterButtons )
{
const int iFilter = pData->GetInt( "userdata", -1 ); AssertMsg( iFilter >= 0, "Bad filter" );
if ( iFilter < 0 )
return;
SetFilter( iFilter );
m_iCurrentPage = 0;
UpdateModelPanels();
if ( m_pCheckoutButton )
{
m_pCheckoutButton->RequestFocus();
}
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_page_2_nav(class)", CFmtStr( "%i", iFilter ).Access() );
}
else if ( pPanel == m_pHomeCategoryTabs )
{
int iSelectedTab = pData->GetInt( "userdata", -1 );
if ( iSelectedTab < 0 )
return;
if ( !m_pPageData || !m_pPageData->m_vecSubcategories.IsValidIndex( iSelectedTab ) )
return;
m_iCurrentSubcategory = iSelectedTab;
FOR_EACH_VEC( m_vecItemPanels, i )
{
// Delete the old one
m_vecItemPanels[i].m_pStorePricePanel->MarkForDeletion();
// Create a new one and cache it
CStorePricePanel *pPricePanel = CreatePricePanel( i );
pPricePanel->InvalidateLayout();
pPricePanel->SetMouseInputEnabled( false );
pPricePanel->SetKeyBoardInputEnabled( false );
m_vecItemPanels[i].m_pStorePricePanel = pPricePanel;
// Setup the mouse handler
m_vecItemPanels[i].m_pItemControlsPanel->SetMouseHoverHandler( pPricePanel );
}
m_iCurrentPage = 0;
UpdateFilteredItems();
UpdateModelPanels();
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_page_2_nav(category)", CFmtStr( "%i", iSelectedTab ).Access() );
}
}
//-----------------------------------------------------------------------------
// Purpose: Called when text changes in combo box
//-----------------------------------------------------------------------------
void CTFStorePage2::OnTextChanged( KeyValues *data )
{
Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
vgui::TextEntry *pTextEntry = dynamic_cast<vgui::TextEntry *>( pPanel );
if ( pTextEntry )
{
if ( pTextEntry == m_pNameFilterTextEntry )
{
m_wNameFilter.RemoveAll();
if ( m_pNameFilterTextEntry->GetTextLength() )
{
m_wNameFilter.EnsureCount( m_pNameFilterTextEntry->GetTextLength() + 1 );
m_pNameFilterTextEntry->GetText( m_wNameFilter.Base(), m_wNameFilter.Count() * sizeof(wchar_t) );
V_wcslower( m_wNameFilter.Base() );
}
m_flFilterItemTime = gpGlobals->curtime + 0.5f;
return;
}
}
vgui::ComboBox *pComboBox = dynamic_cast<vgui::ComboBox *>( pPanel );
if ( pComboBox )
{
if ( pComboBox == m_pSubcategoriesFilterCombo )
{
// the class selection combo box changed, update class details
KeyValues *pUserData = m_pSubcategoriesFilterCombo->GetActiveItemUserData();
if ( !pUserData )
return;
// Update current subcategory filter
m_iCurrentSubcategory = pUserData->GetInt( "index", 0 );
m_bFilterDirty = true;
m_iCurrentPage = 0;
UpdateModelPanels();
if ( m_pCheckoutButton )
{
m_pCheckoutButton->RequestFocus();
}
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_page_2_nav(subcategories)", CFmtStr( "%i", m_iCurrentSubcategory ).Access() );
}
else if ( pComboBox == m_pSortByCombo )
{
// the class selection combo box changed, update class details
KeyValues *pUserData = m_pSortByCombo->GetActiveItemUserData();
if ( !pUserData )
return;
int iSortTypeSelectionIndex = pUserData->GetInt( "sortby", -1 );
m_bFilterDirty = true;
if ( iSortTypeSelectionIndex >= 0 )
{
eEconStoreSortType iSortType = (eEconStoreSortType)g_StoreSortTypes[iSortTypeSelectionIndex].iSortType;
UpdateFilteredItems();
UpdateModelPanels();
C_CTFGameStats::ImmediateWriteInterfaceEvent( "store_page_2_nav(sort_by)", CFmtStr( "%i", iSortType ).Access() );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::GetFiltersForDef( GameItemDefinition_t *pDef, CUtlVector<int> *pVecFilters )
{
BaseClass::GetFiltersForDef( pDef, pVecFilters );
}
bool CTFStorePage2::FindAndSelectEntry( const econ_store_entry_t *pEntry )
{
m_iCurrentSubcategory = GetAllSubcategoriesIndex();
m_bFilterDirty = true;
if ( BaseClass::FindAndSelectEntry( pEntry ) )
{
ivgui()->PostMessage( GetVPanel(), new KeyValues( "ItemDefDetails", "ItemDefIndex", pEntry->GetItemDefinitionIndex() ), GetVPanel() );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::ClearNameFilter( bool bUpdateModelPanels )
{
// don't do anything if we don't have any filter
if ( m_wNameFilter.Count() == 0 )
return;
m_wNameFilter.RemoveAll();
if( m_pNameFilterTextEntry )
{
m_pNameFilterTextEntry->SetText( "" );
}
if ( bUpdateModelPanels )
{
m_flFilterItemTime = gpGlobals->curtime + 0.1f;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CTFStorePage2::GetAllSubcategoriesIndex() const
{
return m_pPageData ? m_pPageData->GetNumSubcategories() : 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::UpdateFilteredItems()
{
if ( m_bFilterDirty )
{
// Make sure list of unfiltered items is sorted
m_pSortByCombo = dynamic_cast< ComboBox * >( FindChildByName( "SortFilterComboBox" ) );
if ( m_pSortByCombo )
{
KeyValues *pUserData = m_pSortByCombo->GetActiveItemUserData();
if ( pUserData )
{
int iSortTypeSelectionIndex = pUserData->GetInt( "sortby", -1 );
if ( iSortTypeSelectionIndex >= 0 )
{
eEconStoreSortType iSortType = (eEconStoreSortType)g_StoreSortTypes[iSortTypeSelectionIndex].iSortType;
CEconStorePriceSheet *pPriceSheet = EconUI()->GetStorePanel()->GetPriceSheetForEdit();
pPriceSheet->SetEconStoreSortType( iSortType );
CEconStoreCategoryManager::StoreCategory_t *pPageData = const_cast< CEconStoreCategoryManager::StoreCategory_t * >( m_pPageData );
pPageData->m_vecEntries.SetLessContext( pPriceSheet );
pPageData->m_vecEntries.RedoSort( true );
}
}
}
}
if ( !IsHomePage() )
{
BaseClass::UpdateFilteredItems();
return;
}
m_FilteredEntries.Purge();
// Subcategories on the home page are special cases, as they aren't based on
// an item's tags.
const StoreCategoryID_t unSubcategoryID = m_pPageData->m_vecSubcategories[ m_iCurrentSubcategory ]->m_unID;
CStorePanel *pStorePanel = EconUI()->GetStorePanel();
if ( !pStorePanel )
return;
FOR_EACH_VEC( m_vecItemPanels, idx )
{
m_vecItemPanels[idx].m_pItemModelPanel->SetShowQuantity( unSubcategoryID != CEconStoreCategoryManager::k_CategoryID_Popular );
}
if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_Popular )
{
const CUtlVector<uint32>& popularItems = pStorePanel->GetPopularItems();
for ( int i = 0; i < MIN( m_vecItemPanels.Count(), popularItems.Count() ); ++i )
{
const econ_store_entry_t *pEntry = pStorePanel->GetPriceSheet()->GetEntry( popularItems[i] );
m_FilteredEntries.AddToTail( pEntry );
}
}
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_New )
{
// Add all new items
const CUtlMap< uint16, econ_store_entry_t > &mapEntries = pStorePanel->GetPriceSheet()->GetEntries();
FOR_EACH_MAP_FAST( mapEntries, i )
{
const econ_store_entry_t *pCurEntry = &mapEntries[i];
if ( pCurEntry->m_bNew )
{
m_FilteredEntries.AddToTail( pCurEntry );
}
}
}
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_OnSale )
{
ECurrency eCurrency = EconUI()->GetStorePanel()->GetCurrency();
// Add all entries that are on sale
const CEconStorePriceSheet::StoreEntryMap_t &mapEntries = pStorePanel->GetPriceSheet()->GetEntries();
FOR_EACH_MAP_FAST( mapEntries, i )
{
const econ_store_entry_t *pCurEntry = &mapEntries[i];
if ( pCurEntry->IsOnSale( eCurrency ) )
{
m_FilteredEntries.AddToTail( pCurEntry );
}
}
}
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_Featured )
{
const CEconStorePriceSheet::FeaturedItems_t& vecFeaturedItems = pStorePanel->GetPriceSheet()->GetFeaturedItems();
FOR_EACH_VEC( vecFeaturedItems, i )
{
const econ_store_entry_t *pEntry = pStorePanel->GetPriceSheet()->GetEntry( vecFeaturedItems[i] );
if ( pEntry )
{
m_FilteredEntries.AddToTail( pEntry );
}
else
{
AssertMsg( 0, "trying to add featured item that's not in the store price sheet.\n" );
}
}
}
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_ClassBundles )
{
// Let's find the class bundles
const CEconStorePriceSheet::StoreEntryMap_t &mapEntries = pStorePanel->GetPriceSheet()->GetEntries();
FOR_EACH_MAP_FAST( mapEntries, i )
{
const econ_store_entry_t *pCurEntry = &mapEntries[i];
if ( pCurEntry->IsListedInCategory( CEconStoreCategoryManager::k_CategoryID_ClassBundles ) )
{
m_FilteredEntries.AddToTail( pCurEntry );
}
}
// Sort by date to get the weapon bundles before the keyless crates
//extern int ItemNameSortComparator( const econ_store_entry_t *const *ppEntryA, const econ_store_entry_t *const *ppEntryB );
extern int FirstSaleDateSortComparator( const econ_store_entry_t *const *ppItemA, const econ_store_entry_t *const *ppItemB );
m_FilteredEntries.Sort( &FirstSaleDateSortComparator );
}
else if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_Taunts )
{
const CEconStorePriceSheet::StoreEntryMap_t &mapEntries = pStorePanel->GetPriceSheet()->GetEntries();
FOR_EACH_MAP_FAST( mapEntries, i )
{
const econ_store_entry_t *pCurEntry = &mapEntries[i];
if ( pCurEntry->IsListedInCategory( CEconStoreCategoryManager::k_CategoryID_Taunts ) )
{
m_FilteredEntries.AddToTail( pCurEntry );
}
}
}
else
{
AssertMsg( 0, "Subcategory has no defined behavior in code" );
}
// If we're either "New" category or the "On Sale" category or the "Taunts" category, sort our contents
// by sale date.
if ( unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_New || unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_OnSale || unSubcategoryID == CEconStoreCategoryManager::k_CategoryID_Taunts )
{
extern int FirstSaleDateSortComparator( const econ_store_entry_t *const *ppItemA, const econ_store_entry_t *const *ppItemB );
m_FilteredEntries.Sort( &FirstSaleDateSortComparator );
}
m_bFilterDirty = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CTFStorePage2::DoesEntryFilterPassSecondaryFilter( const econ_store_entry_t *pEntry )
{
if ( !DoesEntryFilterPassSubcategoryFilter( pEntry ) )
{
return false;
}
if ( m_wNameFilter.Count() > 0 )
{
CEconItemView itemData;
itemData.Init( pEntry->GetItemDefinitionIndex(), AE_UNIQUE, AE_USE_SCRIPT_VALUE, true );
itemData.SetClientItemFlags( kEconItemFlagClient_Preview | kEconItemFlagClient_StoreItem );
return DoesItemPassSearchFilter( itemData.GetDescription(), m_wNameFilter.Base() );
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CTFStorePage2::DoesEntryFilterPassSubcategoryFilter( const econ_store_entry_t *pEntry )
{
Assert( pEntry );
Assert( m_pPageData );
// Make sure pages without subcategories can still function
if ( !HasSubcategories() )
return true;
// "All subcategories" item selected?
if ( m_iCurrentSubcategory == GetAllSubcategoriesIndex() )
return true;
if ( !m_pPageData->m_vecSubcategories.IsValidIndex( m_iCurrentSubcategory ) )
return false;
// Get the subcategory ID
const StoreCategoryID_t unSubCategoryID = m_pPageData->m_vecSubcategories[ m_iCurrentSubcategory ]->m_unID;
// If the store entry is covered by the currently selected category, return true.
// return pEntry->m_vecTagIds.Find( unSubCategoryID ) != pEntry->m_vecTagIds.InvalidIndex();
return pEntry->IsListedInCategory( unSubCategoryID );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::UpdateFilterComboBox( void )
{
BaseClass::UpdateFilterComboBox();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::OnThink( void )
{
BaseClass::OnThink();
if ( m_flFilterItemTime && gpGlobals->curtime >= m_flFilterItemTime )
{
m_bFilterDirty = true;
UpdateFilteredItems();
UpdateModelPanels();
m_flFilterItemTime = 0.0f;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStorePreviewItemPanel *CTFStorePage2::CreatePreviewPanel( void )
{
return new CTFStorePreviewItemPanel2( EconUI()->GetStorePanel(), m_pPreviewItemResFile, "storepreviewitem", this );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStorePricePanel* CTFStorePage2::CreatePricePanel( int iIndex )
{
if ( m_pPageData &&
m_pPageData->m_bIsHome &&
HasSubcategories() &&
m_pPageData->m_vecSubcategories.IsValidIndex( m_iCurrentSubcategory ) &&
m_pPageData->m_vecSubcategories[ m_iCurrentSubcategory ]->m_unID == CEconStoreCategoryManager::k_CategoryID_Popular )
{
return vgui::SETUP_PANEL( new CStorePricePanel_Popular( this, "StorePrice", iIndex + 1 ) );
}
return BaseClass::CreatePricePanel( iIndex );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::OnAddItemToCart( KeyValues *pData )
{
item_definition_index_t iItemDef = (item_definition_index_t)pData->GetInt( "item_def", INVALID_ITEM_DEF_INDEX );
AddItemToCartHelper( GetPageName(), iItemDef, (ECartItemType)pData->GetInt( "cart_add_type", kCartItem_Purchase ) );
UpdateCart();
// Turn the free slots indicator red if we can't fit everything.
UpdateBackpackLabel();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::OnItemPanelMouseReleased( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( pItemPanel && IsVisible() && pItemPanel->HasItem() )
{
FOR_EACH_VEC( m_vecItemPanels, i )
{
if ( m_vecItemPanels[i].m_pItemModelPanel == pItemPanel )
{
ShowPreviewWindow( m_vecItemPanels[i].m_pItemModelPanel->GetItem()->GetItemDefIndex() );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage2::OnItemPanelMouseDoublePressed( vgui::Panel *panel )
{
// Do nothing
}
@@ -0,0 +1,82 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_STORE_PAGE2_H
#define TF_STORE_PAGE2_H
#ifdef _WIN32
#pragma once
#endif
#include "store/tf_store_page_base.h"
class CNavigationPanel;
class CClassFilterTooltip;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePage2 : public CTFStorePageBase
{
DECLARE_CLASS_SIMPLE( CTFStorePage2, CTFStorePageBase );
public:
CTFStorePage2( Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData, const char *pPreviewItemResFile = NULL );
~CTFStorePage2();
virtual void OnPostCreate();
bool HasSubcategories() const;
int GetNumSubcategories() const { return m_pPageData ? m_pPageData->m_vecSubcategories.Count() : 0; }
virtual void PerformLayout();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual const char *GetPageResFile( void );
virtual void OnCommand( const char *command );
MESSAGE_FUNC( OnPageShow, "PageShow" );
MESSAGE_FUNC_PTR( OnItemDetails, "ItemDetails", panel );
MESSAGE_FUNC_PARAMS( OnItemDefDetails, "ItemDefDetails", pData );
MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pData );
MESSAGE_FUNC_PARAMS( OnNavButtonSelected, "NavButtonSelected", pData );
MESSAGE_FUNC_PARAMS( OnAddItemToCart, "AddItemToCart", data ); // Comes from preview panel
MESSAGE_FUNC_PTR( OnItemPanelMouseDoublePressed, "ItemPanelMouseDoublePressed", panel );
MESSAGE_FUNC_PTR( OnItemPanelMouseReleased, "ItemPanelMouseReleased", panel ); // Comes from CStoreItemControlsPanel
virtual bool DoesEntryFilterPassSecondaryFilter( const econ_store_entry_t *pEntry );
bool DoesEntryFilterPassSubcategoryFilter( const econ_store_entry_t *pEntry );
virtual void UpdateFilteredItems( void );
virtual void UpdateFilterComboBox( void );
virtual void GetFiltersForDef( GameItemDefinition_t *pDef, CUtlVector<int> *pVecFilters );
virtual void OnThink( void );
virtual bool FindAndSelectEntry( const econ_store_entry_t *pEntry );
void ClearNameFilter( bool bUpdateModelPanels );
virtual CStorePreviewItemPanel *CreatePreviewPanel( void );
virtual CStorePricePanel* CreatePricePanel( int iIndex );
void ShowPreviewWindow( item_definition_index_t usDefIndex );
int GetAllSubcategoriesIndex() const;
vgui::TextEntry *m_pNameFilterTextEntry;
CExLabel *m_pSubcategoriesFilterLabel;
vgui::ComboBox *m_pSubcategoriesFilterCombo;
vgui::ComboBox *m_pSortByCombo;
CNavigationPanel *m_pHomeCategoryTabs;
CNavigationPanel *m_pClassFilterButtons;
CExLabel *m_pClassFilterTooltipLabel;
CClassFilterTooltip *m_pClassFilterTooltip;
int m_iCurrentSubcategory;
CUtlVector<wchar_t> m_wNameFilter;
float m_flFilterItemTime;
friend class CClassFilterTooltip;
};
#endif // TF_STORE_PAGE2_H
@@ -0,0 +1,59 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/v2/tf_store_page_maps2.h"
#include "store/v2/tf_store_mapstamps_info_dialog.h"
#include "store/store_panel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFStorePage_Maps2::CTFStorePage_Maps2( Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData )
: BaseClass( parent, pPageData, "Resource/UI/econ/store/v2/StorePreviewItemPanel_Maps.res" )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage_Maps2::OnPageShow()
{
BaseClass::OnPageShow();
SetDetailsVisible( false );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage_Maps2::OnCommand( const char *command )
{
if ( !V_strnicmp( command, "maps_learnmore", 14 ) )
{
DisplayMapStampsDialog();
}
else
{
BaseClass::OnCommand( command );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePage_Maps2::DisplayMapStampsDialog()
{
CTFMapStampsInfoDialog *pDlg = vgui::SETUP_PANEL( new CTFMapStampsInfoDialog( EconUI()->GetStorePanel() ) );
pDlg->SetVisible( true );
pDlg->InvalidateLayout( true, true );
pDlg->SetKeyBoardInputEnabled(true);
pDlg->SetMouseInputEnabled(true);
}
@@ -0,0 +1,35 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef STORE_PAGE_MAPS2_H
#define STORE_PAGE_MAPS2_H
#ifdef _WIN32
#pragma once
#endif
#include "store/v2/tf_store_page2.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePage_Maps2 : public CTFStorePage2
{
DECLARE_CLASS_SIMPLE( CTFStorePage_Maps2, CTFStorePage2 );
public:
CTFStorePage_Maps2( Panel *parent, const CEconStoreCategoryManager::StoreCategory_t *pPageData );
virtual ~CTFStorePage_Maps2() {}
virtual const char* GetPageResFile() { return "Resource/UI/econ/store/v2/StorePage_Maps.res"; }
protected:
virtual void OnCommand( const char *command );
virtual void OnPageShow( void );
void DisplayMapStampsDialog();
};
#endif // STORE_PAGE_MAPS2_H
@@ -0,0 +1,109 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "store/v2/tf_store_panel2.h"
#include "store/v2/tf_store_page2.h"
#include "store/v2/tf_store_page_maps2.h"
#include "store/store_page_halloween.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFStorePanel2::CTFStorePanel2( vgui::Panel *parent ) : CTFBaseStorePanel(parent)
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePanel2::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePanel2::ShowPanel( bool bShow )
{
BaseClass::ShowPanel( bShow );
// Base class should turn this on
if ( bShow && m_bOGSLogging )
{
EconUI()->Gamestats_Store( IE_STORE2_ENTERED );
}
Panel *pCheckOutButton = FindChildByName( "CheckOutButton" );
if ( pCheckOutButton )
{
pCheckOutButton->RequestFocus();
}
}
void CTFStorePanel2::OnAddToCart( void )
{
Panel *pCheckOutButton = FindChildByName( "CheckOutButton" );
if ( pCheckOutButton )
{
pCheckOutButton->RequestFocus();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePanel2::OnThink()
{
BaseClass::OnThink();
}
void CTFStorePanel2::OnKeyCodePressed( vgui::KeyCode code )
{
// ESC cancels
if ( code == KEY_XBUTTON_B )
{
OnCommand( "close" );
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFStorePanel2::PostTransactionCompleted( void )
{
BaseClass::PostTransactionCompleted();
}
//-----------------------------------------------------------------------------
// Purpose: Static store page factory.
//-----------------------------------------------------------------------------
CStorePage *CTFStorePanel2::CreateStorePage( const CEconStoreCategoryManager::StoreCategory_t *pPageData )
{
if ( pPageData )
{
if ( !Q_strcmp( pPageData->m_pchPageClass, "CStorePage_SpecialPromo" ) )
return new CTFStorePage_SpecialPromo( this, pPageData );
if ( !Q_strcmp( pPageData->m_pchPageClass, "CStorePage_Maps" ) )
return new CTFStorePage_Maps2( this, pPageData );
if ( !Q_strcmp( pPageData->m_pchPageClass, "CStorePage_Popular" ) )
return new CTFStorePage_Popular( this, pPageData );
}
// Default, standard store page.
return new CTFStorePage2( this, pPageData );
}
@@ -0,0 +1,41 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_STORE_PANEL2_H
#define TF_STORE_PANEL2_H
#ifdef _WIN32
#pragma once
#endif
#include "store/tf_store_panel_base.h"
class CStorePage;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePanel2 : public CTFBaseStorePanel
{
DECLARE_CLASS_SIMPLE( CTFStorePanel2, CTFBaseStorePanel );
public:
CTFStorePanel2( vgui::Panel *parent );
// UI Layout
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnThink();
virtual void OnKeyCodePressed( vgui::KeyCode code );
virtual void ShowPanel( bool bShow );
virtual void OnAddToCart( void );
// GC Management
virtual void PostTransactionCompleted( void );
private:
virtual CStorePage *CreateStorePage( const CEconStoreCategoryManager::StoreCategory_t *pPageData );
};
#endif // TF_STORE_PANEL2_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,177 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_STORE_PREVIEW_ITEM2_H
#define TF_STORE_PREVIEW_ITEM2_H
#ifdef _WIN32
#pragma once
#endif
#include "store/tf_store_preview_item_base.h"
namespace vgui
{
class ScrollBar;
};
class CNavigationPanel;
class CExLabel;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CFullscreenStorePreviewItem : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CFullscreenStorePreviewItem, EditablePanel );
public:
CFullscreenStorePreviewItem( vgui::Panel *pParent, EditablePanel *pOwner );
void SetItemDef( itemid_t iItemDef );
void GoFullscreen( CTFPlayerModelPanel *pPlayerModelPanel );
void ExitFullscreen();
bool IsFullscreenMode();
private:
MESSAGE_FUNC_PARAMS( OnNavButtonSelected, "NavButtonSelected", pData );
virtual void OnThink();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnCommand( const char *command );
itemid_t m_iItemDef;
CExLabel *m_pCycleTextLabel;
CNavigationPanel *m_pTeamNavPanel;
CExButton *m_pPreviewButton;
struct ModelState_t
{
int m_aPlayerModelPanelBounds[4];
Vector m_vecPlayerPos;
bool m_bZoomed;
}
m_OldModelState;
struct Stats_t
{
Stats_t() { Clear(); }
void Clear() { V_memset( this, 0, sizeof( Stats_t ) ); }
float m_flRotationTime;
}
m_Stats;
float m_flGoFullscreenStartTime;
bool m_bIsHalloweenOrFullmoonOnlyItem;
vgui::DHANDLE< CTFPlayerModelPanel > m_pPlayerModelPanel;
CExButton *m_pZoomButton;
CExButton *m_pRotLeftButton;
CExButton *m_pRotRightButton;
EditablePanel *m_pOverlayPanel;
PHandle m_hOwner;
int m_nLastMouseX;
int m_nLastMouseY;
float m_flLastMouseMoveTime;
CPanelAnimationVar( float, m_flFullscreenFadeToBlackDuration, "fullscreen_fade_to_black_duration", "1.0" );
CPanelAnimationVar( float, m_flModelPanelOriginX, "fullscreen_modelpanel_origin_x", "170" );
CPanelAnimationVar( float, m_flModelPanelOriginY, "fullscreen_modelpanel_origin_y", "0" );
CPanelAnimationVar( float, m_flModelPanelOriginZ, "fullscreen_modelpanel_origin_z", "-36" );
CPanelAnimationVar( float, m_flUiFadeoutTime, "ui_fadeout_time", "5.0" );
CPanelAnimationVar( float, m_flUiFadeoutDuration, "ui_fadeout_duration", "1.0" );
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFStorePreviewItemPanel2 : public CTFStorePreviewItemPanelBase
{
DECLARE_CLASS_SIMPLE( CTFStorePreviewItemPanel2, CTFStorePreviewItemPanelBase );
public:
CTFStorePreviewItemPanel2( vgui::Panel *pParent, const char *pResFile, const char *pPanelName, CStorePage *pOwner );
virtual void PreviewItem( int iClass, CEconItemView *pItem, const econ_store_entry_t* pEntry=NULL ) OVERRIDE;
void PreviewItemCopy( int iClass, CEconItemView *pItem, const econ_store_entry_t* pEntry=NULL );
virtual void SetState( preview_state_t iState );
MESSAGE_FUNC_PARAMS( OnClassIconSelected, "ClassIconSelected", data );
MESSAGE_FUNC( OnHideClassIconMouseover, "HideClassIconMouseover" );
MESSAGE_FUNC_PARAMS( OnShowClassIconMouseover, "ShowClassIconMouseover", data );
protected:
virtual void OnThink();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnCommand( const char *command );
virtual void PerformLayout( void );
virtual void OnTick( void );
virtual void OnMouseWheeled( int delta );
int PlaceControl( Panel *pParent, const char *pControlNameA, const char *pControlNameB, int nOffset, bool bVertical,
bool bSizeAToContents = true, bool bUseContentSize = true );
void DoClose();
void Clear();
void UpdateScrollableChild();
virtual void SetPlayerModelVisible( bool bVisible );
virtual void UpdateIcons( void );
virtual void UpdatePlayerModelButtons( void );
virtual void SetCycleLabelText( vgui::Label *pTargetLabel, const char *pCycleText );
MESSAGE_FUNC_PARAMS( OnNavButtonSelected, "NavButtonSelected", pData );
MESSAGE_FUNC_PARAMS( OnExitFullscreen, "ExitFullscreen", pData );
Label *m_pLastNewLineControl;
EditablePanel *m_pDialogFrame; /// The background border
EditablePanel *m_pPreviewViewportBg;
CExLabel *m_pItemNameLabel;
CExLabel *m_pAttributesLabel;
vgui::EditablePanel *m_pItemCollectionHighlight;
CExLabel *m_pCycleTextLabel;
int m_nNumAttribLinesAdded;
bool m_bArmoryTextAdded;
EditablePanel *m_pDetailsView;
EditablePanel *m_pDetailsViewChild;
CExButton *m_pAddRentalToCartButtons[3];
EditablePanel *m_pScrollableChild;
ScrollBar *m_pScrollBar;
int m_iSliderPos;
bool m_bCloseOnUp;
bool m_bMouseWasDown;
int m_aClickPos[2];
CExButton *m_pItemWikiPageButton;
CNavigationPanel *m_pTeamNavPanel;
CExButton *m_pPreviewButton;
CExImageButton *m_pGoFullscreenButton;
int m_nViewMaxHeight;
CFullscreenStorePreviewItem *m_pFullscreenPanel;
bool m_bIsHalloweenOrFullmoonOnlyItem;
CEconItemView *m_pItemViewData;
CEconItem *m_pSOEconItemData;
// mouse over reference item tooltip
CItemModelPanel *m_pMouseOverItemPanel;
CItemModelPanelToolTip *m_pMouseOverTooltip;
CUtlVector< CItemModelPanel* > m_vecReferenceItemPanels;
CPanelAnimationVarAliasType( int, m_iSmallVerticalBreakSize, "small_vertical_break_size", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_iMediumVerticalBreakSize, "medium_vertical_break_size", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_iBigVerticalBreakSize, "big_vertical_break_size", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_iHorizontalBreakSize, "horizontal_break_size", "0", "proportional_xpos" );
CPanelAnimationVarAliasType( int, m_iControlButtonWidth, "control_button_width", "0", "proportional_xpos" );
CPanelAnimationVarAliasType( int, m_iControlButtonHeight, "control_button_height", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_iControlButtonY, "control_button_y", "0", "proportional_ypos" );
MESSAGE_FUNC_INT( OnSliderMoved, "ScrollBarSliderMoved", position );
};
#endif // TF_STORE_PREVIEW_ITEM2_H
@@ -0,0 +1,269 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "strange_count_transfer_panel.h"
#include "cdll_client_int.h"
#include "ienginevgui.h"
#include "econ_item_tools.h"
#include "econ_ui.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CStatModuleItemSelectionPanel : public CItemCriteriaSelectionPanel
{
DECLARE_CLASS_SIMPLE( CStatModuleItemSelectionPanel, CItemCriteriaSelectionPanel );
public:
CStatModuleItemSelectionPanel( Panel *pParent, const CEconItemView* pCorrespondingItem )
: BaseClass( pParent, NULL )
, m_pCorrespondingItem( pCorrespondingItem )
, m_mapXifierClassCount( CaselessStringLessThan )
{
int nCount = InventoryManager()->GetLocalInventory()->GetItemCount();
for( int i=0; i<nCount; ++i )
{
if ( !BIsItemStrange( InventoryManager()->GetLocalInventory()->GetItem( i ) ) )
continue;
const char *pItemXifier = InventoryManager()->GetLocalInventory()->GetItem( i )->GetItemDefinition()->GetXifierRemapClass();
auto idx = m_mapXifierClassCount.Find( pItemXifier );
if ( idx == m_mapXifierClassCount.InvalidIndex() )
{
idx = m_mapXifierClassCount.Insert( pItemXifier, 0 );
}
m_mapXifierClassCount[ idx ] = m_mapXifierClassCount[ idx ] + 1;
}
}
void ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
vgui::Label* pWeaponLabel = dynamic_cast<vgui::Label*>( FindChildByName("ItemSlotLabel") );
if ( pWeaponLabel )
{
pWeaponLabel->SetVisible( false );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *GetItemNotSelectableReason( const CEconItemView *pItem ) const
{
if ( !pItem )
return NULL;
if ( !BIsItemStrange( pItem ) )
return "#TF_StrangeCount_Transfer_NotStrange";
if ( m_pCorrespondingItem )
{
if ( pItem->GetItemID() == m_pCorrespondingItem->GetItemID() )
return "#TF_StrangeCount_Transfer_Self";
if ( !CEconTool_StrangeCountTransfer::AreItemsEligibleForStrangeCountTransfer( m_pCorrespondingItem, pItem ) )
return "#TF_StrangeCount_Transfer_TypeMismatch";
}
const char *pItemXifier = pItem->GetItemDefinition()->GetXifierRemapClass();
auto idx = m_mapXifierClassCount.Find( pItemXifier );
int nCount = 0;
if ( !pItemXifier )
{
// if no xifier, find atleast 1 other matching item
CPlayerInventory *pInventory = InventoryManager()->GetLocalInventory();
if ( pInventory )
{
for ( int i = 0; i < pInventory->GetItemCount(); i++ )
{
CEconItemView *pIterItem = pInventory->GetItem( i );
if ( pIterItem->GetItemDefIndex() == pItem->GetItemDefIndex() && BIsItemStrange(pIterItem) )
{
// find 2 or more, yourself and another
if ( ++nCount >= 2 )
return NULL;
}
}
}
}
else if ( idx != m_mapXifierClassCount.InvalidIndex() )
{
nCount = m_mapXifierClassCount[ idx ];
}
if ( nCount < 2 )
{
return "#TF_StrangeCount_Transfer_NotEnoughMatches";
}
return NULL;
}
protected:
const char * m_pszTitleToken;
const CEconItemView* m_pCorrespondingItem;
CUtlMap< const char*, int > m_mapXifierClassCount;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStrangeCountTransferPanel::CStrangeCountTransferPanel( vgui::Panel *parent, CEconItemView* pToolItem )
: BaseClass( parent, "StrangeCountTrasnferDialog" )
, m_pToolItem( pToolItem )
{
Assert( pToolItem );
ListenForGameEvent( "gameui_hidden" );
m_hSelectionPanel = 0;
m_pSelectingItemModelPanel = NULL;
EditablePanel* pBG = new EditablePanel( this, "BG" );
m_pSourceStrangeModelPanel = new CItemModelPanel( pBG, "SourceItem" );
m_pSourceStrangeModelPanel->SetActAsButton( true, true );
m_pTargetStrangeModelPanel = new CItemModelPanel( pBG, "TargetItem" );
m_pTargetStrangeModelPanel->SetActAsButton( true, true );
m_pOKButton = new CExButton( pBG, "OkButton", "" );
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" );
SetScheme( scheme );
SetProportional( true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStrangeCountTransferPanel::~CStrangeCountTransferPanel( void )
{
if ( m_hSelectionPanel )
{
m_hSelectionPanel->MarkForDeletion();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CStrangeCountTransferPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( GetResFile() );
}
void CStrangeCountTransferPanel::PerformLayout()
{
BaseClass::PerformLayout();
UpdateOKButton();
m_pSourceStrangeModelPanel->SetTooltip( EconUI()->GetBackpackPanel()->GetMouseOverToolTipPanel(), "" );
m_pTargetStrangeModelPanel->SetTooltip( EconUI()->GetBackpackPanel()->GetMouseOverToolTipPanel(), "" );
}
void CStrangeCountTransferPanel::OnCommand( const char *command )
{
if( FStrEq( "apply", command ) )
{
GCSDK::CProtoBufMsg<CMsgApplyStrangeCountTransfer> msg( k_EMsgGCApplyStrangeCountTransfer );
if ( !m_pToolItem || !m_pSourceStrangeModelPanel->GetItem() || !m_pTargetStrangeModelPanel->GetItem() )
return;
msg.Body().set_tool_item_id( m_pToolItem->GetItemID() );
msg.Body().set_item_src_item_id( m_pSourceStrangeModelPanel->GetItem()->GetItemID() );
msg.Body().set_item_dest_item_id( m_pTargetStrangeModelPanel->GetItem()->GetItemID() );
GCClientSystem()->BSendMessage( msg );
EconUI()->Gamestats_ItemTransaction( IE_ITEM_USED_TOOL, m_pToolItem, "applied_strangecounttransfer", m_pToolItem->GetItemDefIndex() );
GCClientSystem()->BSendMessage( msg );
SetVisible( false );
MarkForDeletion();
return;
}
else if ( FStrEq( "cancel", command ) )
{
MarkForDeletion();
return;
}
BaseClass::OnCommand( command );
}
void CStrangeCountTransferPanel::FireGameEvent( IGameEvent *event )
{
if ( FStrEq( event->GetName(), "gameui_hidden" ) )
{
SetVisible( false );
MarkForDeletion();
return;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CStrangeCountTransferPanel::OnItemPanelMousePressed( vgui::Panel *panel )
{
CItemModelPanel *pItemPanel = dynamic_cast < CItemModelPanel * > ( panel );
if ( pItemPanel && IsVisible() && !pItemPanel->IsGreyedOut() )
{
m_pSelectingItemModelPanel = pItemPanel;
CEconItemView* pOtherItem = pItemPanel == m_pSourceStrangeModelPanel ? m_pTargetStrangeModelPanel->GetItem()
: m_pSourceStrangeModelPanel->GetItem();
m_hSelectionPanel = new CStatModuleItemSelectionPanel( GetParent(), pOtherItem );
// Clicked on an item in the crafting area. Open up the selection panel.
m_hSelectionPanel->ShowDuplicateCounts( false );
m_hSelectionPanel->ShowPanel( 0, true );
m_hSelectionPanel->SetCaller( this );
m_hSelectionPanel->SetZPos( GetZPos() + 1 );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CStrangeCountTransferPanel::OnSelectionReturned( KeyValues *data )
{
Assert( m_pSelectingItemModelPanel );
if ( data && m_pSelectingItemModelPanel )
{
uint64 ulIndex = data->GetUint64( "itemindex", INVALID_ITEM_ID );
CEconItemView* pSelectedItem = InventoryManager()->GetLocalInventory()->GetInventoryItemByItemID( ulIndex );
m_pSelectingItemModelPanel->SetItem( pSelectedItem );
}
UpdateOKButton();
m_pSelectingItemModelPanel = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CStrangeCountTransferPanel::UpdateOKButton()
{
bool bOKEnabled = m_pSourceStrangeModelPanel->GetItem() && m_pTargetStrangeModelPanel->GetItem();
m_pOKButton->SetEnabled( bOKEnabled );
}
@@ -0,0 +1,60 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef STRANGE_COUNT_TRANSFER_H
#define STRANGE_COUNT_TRANSFER_H
#ifdef _WIN32
#pragma once
#endif
#include "backpack_panel.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "tf_gcmessages.h"
#include "econ_gcmessages.h"
#include "tf_imagepanel.h"
#include "tf_controls.h"
#include "item_selection_panel.h"
#include "confirm_dialog.h"
//-----------------------------------------------------------------------------
// A panel to let users choose 2 weapons to tranfer strange counts with
//-----------------------------------------------------------------------------
class CStrangeCountTransferPanel : public vgui::EditablePanel, public CGameEventListener
{
public:
DECLARE_CLASS_SIMPLE( CStrangeCountTransferPanel, vgui::EditablePanel );
CStrangeCountTransferPanel( vgui::Panel *parent, CEconItemView* pToolItem );
~CStrangeCountTransferPanel( void );
virtual const char *GetResFile( void ) { return "Resource/UI/econ/StrangeCountTransferDialog.res"; }
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout() OVERRIDE;
virtual void FireGameEvent( IGameEvent *event ) OVERRIDE;
virtual void OnCommand( const char *command ) OVERRIDE;
MESSAGE_FUNC_PTR( OnItemPanelMousePressed, "ItemPanelMousePressed", panel );
MESSAGE_FUNC_PARAMS( OnSelectionReturned, "SelectionReturned", data );
private:
void UpdateOKButton();
CTFTextToolTip *m_pToolTip;
vgui::EditablePanel *m_pToolTipEmbeddedPanel;
DHANDLE<CItemCriteriaSelectionPanel> m_hSelectionPanel;
CExButton *m_pOKButton;
CEconItemView *m_pToolItem;
CItemModelPanel *m_pSelectingItemModelPanel;
CItemModelPanel *m_pSourceStrangeModelPanel;
CItemModelPanel *m_pTargetStrangeModelPanel;
CItemModelPanel *m_pMouseOverItemPanel;
CItemModelPanelToolTip *m_pMouseOverTooltip;
};
#endif // STRANGE_COUNT_TRANSFER
+754
View File
@@ -0,0 +1,754 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include <vgui/ILocalize.h>
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/ComboBox.h"
#include "vgui_controls/CheckButton.h"
#include "testitem_dialog.h"
#include "tf_controls.h"
#include "c_playerresource.h"
#include "gcsdk/gcmsg.h"
#include "tf_gcmessages.h"
#include "econ_item_inventory.h"
#include "econ_gcmessages.h"
#include "ienginevgui.h"
#include "filesystem.h"
#include "vgui_controls/FileOpenDialog.h"
#include "econ_item_system.h"
#include "testitem_root.h"
#include "econ_item_tools.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
extern const char *g_TeamVisualSections[TEAM_VISUAL_SECTIONS];
static const char *g_pszTestItemHideBodygroup[] =
{
"hat", // TI_HIDEBG_HAT,
"headphones", // TI_HIDEBG_HEADPHONES,
"medal", // TI_HIDEBG_MEDALS,
"grenades", // TI_HIDEBG_GRENADES,
"bullets", // TI_HIDEBG_BULLETS
"arrows", // TI_HIDEBG_ARROWS
"rightarm", // TI_HIDEBG_RIGHTARM
"shoes_socks", // TI_HIDEBG_SHOES_SOCKS
};
COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszTestItemHideBodygroup ) == TI_HIDEBG_COUNT );
static const char *g_pszClassSubdirectories[] =
{
"all_class", // TF_CLASS_UNDEFINED = 0,
"scout", // TF_CLASS_SCOUT, // TF_FIRST_NORMAL_CLASS
"sniper", // TF_CLASS_SNIPER,
"soldier", // TF_CLASS_SOLDIER,
"demo", // TF_CLASS_DEMOMAN,
"medic", // TF_CLASS_MEDIC,
"heavy", // TF_CLASS_HEAVYWEAPONS,
"pyro", // TF_CLASS_PYRO,
"spy", // TF_CLASS_SPY,
"engineer", // TF_CLASS_ENGINEER,
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTestItemDialog::CTestItemDialog( vgui::Panel *parent, testitem_itemtypes_t iItemType, int iClassUsage, KeyValues *pExistingKVs ) : vgui::EditablePanel( parent, "TestItemDialog" )
{
// Need to use the clientscheme (we're not parented to a clientscheme'd panel)
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
SetScheme(scheme);
SetProportional( true );
ListenForGameEvent( "gameui_hidden" );
m_hImportModelDialog = NULL;
m_pModelLabel = NULL;
m_pSelectModelLabel = NULL;
m_pNoItemsToReplaceLabel = NULL;
m_pSelectModelButton = NULL;
m_pOkButton = NULL;
m_pItemReplacedPanel = new vgui::EditablePanel( this, "ItemReplacedPanel" );
m_pItemReplacedComboBox = new vgui::ComboBox( m_pItemReplacedPanel, "ItemReplacedComboBox", 20, false );
m_pItemReplacedComboBox->AddActionSignalTarget( this );
m_pExistingItemToTestPanel = new vgui::EditablePanel( this, "ExistingItemToTestPanel" );
m_pExistingItemComboBox = new vgui::ComboBox( m_pExistingItemToTestPanel, "ExistingItemComboBox", 20, false );
m_pExistingItemComboBox->AddActionSignalTarget( this );
m_pBodygroupPanel = new vgui::EditablePanel( this, "BodygroupPanel" );
for ( int i = 0; i < TI_HIDEBG_COUNT; i++ )
{
m_pBodygroupCheckButtons[i] = new vgui::CheckButton( m_pBodygroupPanel, VarArgs("HideBodygroupCheckBox%d",i), "" );
m_pBodygroupCheckButtons[i]->AddActionSignalTarget( this );
}
m_pCustomizationsPanel = new vgui::EditablePanel( this, "CustomizationsPanel" );
m_pPaintColorComboBox = new vgui::ComboBox( m_pCustomizationsPanel, "PaintColorComboBox", 20, false );
m_pPaintColorComboBox->AddActionSignalTarget( this );
m_pUnusualEffectComboBox = new vgui::ComboBox( m_pCustomizationsPanel, "UnusualEffectComboBox", 20, false );
m_pUnusualEffectComboBox->AddActionSignalTarget( this );
m_iItemType = iItemType;
m_iClassUsage = iClassUsage;
m_szRelativePath[0] = '\0';
SetDialogVariable("testmodel", g_pVGuiLocalize->Find( "#IT_NoModel" ) );
SetEntryStep( TI_STEP_MODELNAME );
// Load our scheme right away so we have all our pieces ready
MakeReadyForUse();
SetupPaintColorComboBox();
SetupUnusualEffectComboBox();
// Pull the data out of the existing KVs
if ( pExistingKVs )
{
InitializeFromExistingKVs( pExistingKVs );
}
else
{
for ( int i = 0; i < TI_HIDEBG_COUNT; i++ )
{
// Start with the "hat" bodygroup checked (for non-weapons)
bool bIsHat = ( m_iItemType != TI_TYPE_WEAPON ) && ( i == 0 );
m_pBodygroupCheckButtons[i]->SetSelected( bIsHat );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::InitializeFromExistingKVs( KeyValues *pExistingKVs )
{
// If we're testing an existing item, it supercedes everything else
item_definition_index_t iExistingItemDef = pExistingKVs->GetInt( "existing_itemdef", INVALID_ITEM_DEF_INDEX );
if ( iExistingItemDef != INVALID_ITEM_DEF_INDEX )
{
SetupItemComboBox( m_pExistingItemComboBox );
// Loop through the entries until we find the specified item def
for ( int i = 0; i < m_pExistingItemComboBox->GetItemCount(); i++ )
{
int iItemID = m_pExistingItemComboBox->GetItemIDFromRow(i);
KeyValues *pRowKV = m_pExistingItemComboBox->GetItemUserData( iItemID );
if ( pRowKV && pRowKV->GetInt( "item", INVALID_ITEM_DEF_INDEX ) == iExistingItemDef )
{
m_pExistingItemComboBox->SilentActivateItemByRow(i);
SetEntryStep( TI_STEP_FINISHED );
}
}
}
else
{
const char *pszModel = pExistingKVs->GetString( "model_player", NULL );
if ( pszModel && pszModel[0] )
{
Q_strncpy( m_szRelativePath, pszModel, MAX_PATH );
SetDialogVariable("testmodel", m_szRelativePath );
SetEntryStep( TI_STEP_MODELNAME );
SetEntryStep( TI_STEP_WPN_ITEMREPLACED );
if ( m_iItemType == TI_TYPE_WEAPON )
{
item_definition_index_t iItemDefToReplace = pExistingKVs->GetInt( "item_replace", INVALID_ITEM_DEF_INDEX );
if ( iItemDefToReplace != INVALID_ITEM_DEF_INDEX )
{
SetupItemComboBox( m_pItemReplacedComboBox );
// Loop through the entries until we find the specified item def
for ( int i = 0; i < m_pItemReplacedComboBox->GetItemCount(); i++ )
{
int iItemID = m_pItemReplacedComboBox->GetItemIDFromRow(i);
KeyValues *pRowKV = m_pItemReplacedComboBox->GetItemUserData( iItemID );
if ( pRowKV && pRowKV->GetInt( "item", INVALID_ITEM_DEF_INDEX ) == iItemDefToReplace )
{
m_pItemReplacedComboBox->SilentActivateItemByRow(i);
SetEntryStep( TI_STEP_FINISHED );
}
}
}
}
else
{
KeyValues *pkvVisuals = pExistingKVs->FindKey( g_TeamVisualSections[0] );
if ( pkvVisuals )
{
KeyValues *pKVEntry = pkvVisuals->GetFirstSubKey();
while ( pKVEntry )
{
if ( !Q_stricmp( pKVEntry->GetName(), "player_bodygroups" ) )
{
FOR_EACH_SUBKEY( pKVEntry, pKVSubEntry )
{
int iBG = StringFieldToInt( pKVSubEntry->GetName(), g_pszTestItemHideBodygroup, ARRAYSIZE(g_pszTestItemHideBodygroup) );
if ( iBG >= 0 && iBG < TI_HIDEBG_COUNT )
{
m_pBodygroupCheckButtons[iBG]->SetSelected( pKVSubEntry->GetInt() == 0 );
}
}
}
pKVEntry = pKVEntry->GetNextKey();
}
}
// Start with the right paint can selected
int iPaintCanIndex = pExistingKVs->GetInt("paintcan_index", 0);
for ( int i = 0; i < m_pPaintColorComboBox->GetItemCount(); i++ )
{
int iItemID = m_pPaintColorComboBox->GetItemIDFromRow(i);
KeyValues *pRowKV = m_pPaintColorComboBox->GetItemUserData( iItemID );
if ( pRowKV && pRowKV->GetInt("paintcan_index",0) == iPaintCanIndex )
{
m_pPaintColorComboBox->SilentActivateItemByRow(i);
}
}
// Start with the right unusual effect selected
int iUnusualIndex = pExistingKVs->GetInt("unusual_index", 0);
for ( int i = 0; i < m_pUnusualEffectComboBox->GetItemCount(); i++ )
{
int iItemID = m_pUnusualEffectComboBox->GetItemIDFromRow(i);
KeyValues *pRowKV = m_pUnusualEffectComboBox->GetItemUserData( iItemID );
if ( pRowKV && pRowKV->GetInt("unusual_index",0) == iUnusualIndex )
{
m_pUnusualEffectComboBox->SilentActivateItemByRow(i);
}
}
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTestItemDialog::~CTestItemDialog( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/TestItemDialog.res" );
m_pModelLabel = dynamic_cast<CExLabel*>( FindChildByName( "ModelLabel" ) );
m_pSelectModelLabel = dynamic_cast<CExLabel*>( FindChildByName( "SelectModelLabel" ) );
m_pSelectModelButton = dynamic_cast<CExButton*>( FindChildByName( "SelectModelButton" ) );
m_pOkButton = dynamic_cast<CExButton*>( FindChildByName( "OkButton" ) );
m_pNoItemsToReplaceLabel = dynamic_cast<CExLabel*>( m_pItemReplacedPanel->FindChildByName( "NoItemsToReplaceLabel" ) );
SetEntryStep( m_iEntryStep );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::PerformLayout( void )
{
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::FireGameEvent( IGameEvent *event )
{
const char *type = event->GetName();
if ( Q_strcmp(type, "gameui_hidden") == 0 )
{
Close();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::Close( void )
{
TFModalStack()->PopModal( this );
SetVisible( false );
MarkForDeletion();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::CloseAndUpdateItem( void )
{
// We're going to assemble a KV block that describes this test item
KeyValues *kv = new KeyValues( "SetTestItemKVs" );
kv->SetInt( "item_type", m_iItemType );
kv->SetString( "model_player", m_szRelativePath );
kv->SetBool( "test_existing_item", false );
kv->SetInt( "attach_to_hands", (m_iItemType == TI_TYPE_WEAPON) );
KeyValues *pKVModels = new KeyValues( "model_player_per_class" );
kv->AddSubKey( pKVModels );
const char *pFilename = V_UnqualifiedFileName( m_szRelativePath );
if ( pFilename)
{
for ( int i = TF_FIRST_NORMAL_CLASS; i < ARRAYSIZE( g_pszClassSubdirectories ); i++ )
{
if ( m_iClassUsage == 1 || ( m_iClassUsage & (1 << i) ) )
{
CFmtStr1024 path( "models/player/items/%s/%s", g_pszClassSubdirectories[i], pFilename );
if ( g_pFullFileSystem->FileExists( path.Access() ) )
{
pKVModels->SetString( ItemSystem()->GetItemSchema()->GetClassUsabilityStrings()[i], path.Access() );
}
}
}
}
KeyValues *pkvVisuals = new KeyValues( g_TeamVisualSections[0] ),
*pkvPlayerBodyGroups = new KeyValues( "player_bodygroups" );
kv->AddSubKey( pkvVisuals );
pkvVisuals->AddSubKey( pkvPlayerBodyGroups );
for ( int i = 0; i < TI_HIDEBG_COUNT; i++ )
{
KeyValues *pKVBG = new KeyValues( g_pszTestItemHideBodygroup[i] );
pKVBG->SetInt( NULL, m_pBodygroupCheckButtons[i]->IsSelected() ? 0 : 1 );
pkvPlayerBodyGroups->AddSubKey( pKVBG );
}
// Extract the paint can index
KeyValues *pPaintComboKV = m_pPaintColorComboBox->GetActiveItemUserData();
int iPaintCanIndex = pPaintComboKV ? pPaintComboKV->GetInt( "paintcan_index", 0 ) : 0;
kv->SetInt( "paintcan_index", iPaintCanIndex );
// Extract the unusual effect index
KeyValues *pUnusualComboKV = m_pUnusualEffectComboBox->GetActiveItemUserData();
int iUnusualIndex = pUnusualComboKV ? pUnusualComboKV->GetInt( "unusual_index", 0 ) : 0;
kv->SetInt( "unusual_index", iUnusualIndex );
item_definition_index_t iItemDef = INVALID_ITEM_DEF_INDEX;
// See if we're copying an existing item
KeyValues *pExistingUserData = m_pExistingItemComboBox->GetActiveItemUserData();
item_definition_index_t iExistingItemDef = pExistingUserData ? pExistingUserData->GetInt( "item", INVALID_ITEM_DEF_INDEX ) : INVALID_ITEM_DEF_INDEX;
if ( iExistingItemDef != INVALID_ITEM_DEF_INDEX )
{
iItemDef = iExistingItemDef;
kv->SetInt( "existing_itemdef", iItemDef );
kv->SetBool( "test_existing_item", true );
// copy model path from existing items
GameItemDefinition_t *pItemDef = ItemSystem()->GetStaticDataForItemByDefIndex( iItemDef );
if ( pItemDef )
{
for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass < TF_LAST_NORMAL_CLASS; iClass++ )
{
if ( m_iClassUsage == 1 || ( m_iClassUsage & (1 << iClass) ) )
{
const char *pszClassString = ItemSystem()->GetItemSchema()->GetClassUsabilityStrings()[iClass];
const char *pszModel = pItemDef->GetPlayerDisplayModel( iClass );
pKVModels->SetString( pszClassString, pszModel );
}
}
}
}
else
{
KeyValues *pUserData = m_pItemReplacedComboBox->GetActiveItemUserData();
iItemDef = pUserData ? pUserData->GetInt( "item", INVALID_ITEM_DEF_INDEX ) : INVALID_ITEM_DEF_INDEX;
// Find the item def we're going to build off
switch ( m_iItemType )
{
case TI_TYPE_WEAPON:
// Need an item def to replace
if ( iItemDef == INVALID_ITEM_DEF_INDEX )
return;
break;
case TI_TYPE_HEADGEAR:
iItemDef = ItemSystem()->GetItemSchema()->GetItemDefinitionByName("Football Helmet")->GetDefinitionIndex();
break;
case TI_TYPE_MISC1:
iItemDef = ItemSystem()->GetItemSchema()->GetItemDefinitionByName("Employee Badge A")->GetDefinitionIndex();
break;
case TI_TYPE_MISC2:
iItemDef = ItemSystem()->GetItemSchema()->GetItemDefinitionByName("High Five Taunt")->GetDefinitionIndex();
break;
}
}
// Tell the server what item we're replacing, and what def index we used
kv->SetInt( "item_replace", iItemDef );
// Send it to the testing root panel
PostMessage( GetParent(), kv );
Close();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "cancel" ) )
{
Close();
return;
}
else if ( !Q_stricmp( command, "ok" ) )
{
CloseAndUpdateItem();
return;
}
else if ( !Q_stricmp( command, "reloadscheme" ) )
{
InvalidateLayout( false, true );
return;
}
else if ( !Q_stricmp( command, "select_model" ) )
{
OpenSelectModelDialog();
return;
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::OpenSelectModelDialog( void )
{
if (m_hImportModelDialog == NULL)
{
m_hImportModelDialog = new vgui::FileOpenDialog( NULL, "#ToolCustomizeTextureTitle", true );
m_hImportModelDialog->AddFilter( "*.mdl", "#IT_MDL_Files", true );
m_hImportModelDialog->AddActionSignalTarget( this );
}
char szModelsDir[MAX_PATH];
switch( m_iItemType )
{
default:
break;
case TI_TYPE_WEAPON:
m_hImportModelDialog->SetStartDirectory( g_pFullFileSystem->RelativePathToFullPath( "models/weapons/c_models", "MOD", szModelsDir, sizeof(szModelsDir) ) );
break;
case TI_TYPE_HEADGEAR:
case TI_TYPE_MISC1:
case TI_TYPE_MISC2:
{
const char *pszSubDir = NULL;
// All classes?
if ( m_iClassUsage == 1 )
{
pszSubDir = g_pszClassSubdirectories[0];
}
else
{
// If we only have one class, jump into that directory
for ( int i = TF_FIRST_NORMAL_CLASS; i < LOADOUT_COUNT; i++ )
{
if ( m_iClassUsage & (1 << i) )
{
if ( !pszSubDir )
{
pszSubDir = g_pszClassSubdirectories[i];
}
else
{
// Found multiple classes. Move back up to the base dir.
pszSubDir = NULL;
break;
}
}
}
}
if ( pszSubDir )
{
m_hImportModelDialog->SetStartDirectory( g_pFullFileSystem->RelativePathToFullPath( VarArgs("models/player/items/%s",pszSubDir), "MOD", szModelsDir, sizeof(szModelsDir) ) );
}
else
{
m_hImportModelDialog->SetStartDirectory( g_pFullFileSystem->RelativePathToFullPath( "models/player/items", "MOD", szModelsDir, sizeof(szModelsDir) ) );
}
}
break;
}
m_hImportModelDialog->DoModal( false );
m_hImportModelDialog->Activate();
// Base file dialog won't refresh if it's opening to the same directory it was in. Force it to.
PostMessage( m_hImportModelDialog->GetVPanel(), new KeyValues( "PopulateFileList" ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct ComboBoxTestItem_t
{
const wchar_t *pwszItemName;
item_definition_index_t itemDef;
};
static int SortComboBoxTestItem( const ComboBoxTestItem_t *a, const ComboBoxTestItem_t *b )
{
return V_wcscmp( a->pwszItemName, b->pwszItemName );
}
void CTestItemDialog::SetupItemComboBox( vgui::ComboBox *pComboBox )
{
pComboBox->RemoveAll();
CUtlVector<item_definition_index_t> vecDefs;
int iReplacements = ((CTestItemRoot*)GetParent())->FindReplaceableItemsForSelectedClass( &vecDefs, m_iItemType == TI_TYPE_WEAPON );
if ( iReplacements )
{
KeyValues *pKeyValues = new KeyValues( "data" );
pKeyValues->SetInt( "item", INVALID_ITEM_DEF_INDEX );
pComboBox->AddItem( "#IT_ItemReplaced_Select", pKeyValues );
CUtlVector< ComboBoxTestItem_t > testItems;
FOR_EACH_VEC( vecDefs, i )
{
CEconItemDefinition *pDef = ItemSystem()->GetStaticDataForItemByDefIndex( vecDefs[i] );
if ( pDef )
{
const wchar_t *pwszLocalizedItemName = g_pVGuiLocalize->Find( pDef->GetItemBaseName() );
if ( pwszLocalizedItemName )
{
int newIndex = testItems.AddToTail();
testItems[newIndex].itemDef = vecDefs[i];
testItems[newIndex].pwszItemName = pwszLocalizedItemName;
}
}
}
if ( testItems.Count() )
{
testItems.Sort( &SortComboBoxTestItem );
FOR_EACH_VEC( testItems, i )
{
pKeyValues = new KeyValues( "data" );
pKeyValues->SetInt( "item", testItems[i].itemDef );
pComboBox->AddItem( testItems[i].pwszItemName, pKeyValues );
}
}
}
// No valid entries?
if ( pComboBox == m_pItemReplacedComboBox )
{
if ( m_pNoItemsToReplaceLabel )
{
m_pNoItemsToReplaceLabel->SetVisible( !iReplacements );
}
m_pItemReplacedPanel->SetVisible( iReplacements );
}
pComboBox->SetItemEnabled( 0, false );
pComboBox->SilentActivateItemByRow( 0 );
pComboBox->GetMenu()->SetBgColor( Color(0,0,0,255) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::SetupPaintColorComboBox( void )
{
m_pPaintColorComboBox->RemoveAll();
KeyValues *pKeyValues = new KeyValues( "data" );
pKeyValues->SetInt( "paintcan_index", 0 );
m_pPaintColorComboBox->AddItem( "#IT_PaintNone", pKeyValues );
// Now loop through all our paints and add them to the list
const CEconItemSchema::SortedItemDefinitionMap_t& mapItemDefs = ItemSystem()->GetItemSchema()->GetSortedItemDefinitionMap();
FOR_EACH_MAP( mapItemDefs, i )
{
const CEconItemDefinition *pDef = mapItemDefs[i];
const CEconTool_PaintCan *pEconToolPaintCan = pDef->GetTypedEconTool<CEconTool_PaintCan>();
if ( !pEconToolPaintCan )
continue;
pKeyValues->SetInt( "paintcan_index", pDef->GetDefinitionIndex() );
m_pPaintColorComboBox->AddItem( g_pVGuiLocalize->Find( pDef->GetItemBaseName() ), pKeyValues );
// Make sure it has valid colors (to skip the store version of the paint can)
KeyValues *pAttribs = pDef->GetDefinitionKey( "attributes" );
if ( !pAttribs )
continue;
KeyValues *pRGBAttrib = pAttribs->FindKey( "set_item_tint_rgb" );
if ( !pRGBAttrib )
continue;
int iModifiedRGB = pRGBAttrib->GetInt( "value", -1 );
if ( iModifiedRGB != -1 )
{
m_pPaintColorComboBox->AddItem( g_pVGuiLocalize->Find( pDef->GetItemBaseName() ), pKeyValues );
}
}
m_pPaintColorComboBox->SilentActivateItemByRow( 0 );
m_pPaintColorComboBox->GetMenu()->SetBgColor( Color(0,0,0,255) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::SetupUnusualEffectComboBox( void )
{
m_pUnusualEffectComboBox->RemoveAll();
KeyValues *pKeyValues = new KeyValues( "data" );
pKeyValues->SetInt( "unusual_index", 0 );
m_pUnusualEffectComboBox->AddItem( "#IT_UnusualNone", pKeyValues );
// Now loop through all unusual effects and add them to the list.
const CEconItemSchema::ParticleDefinitionMap_t& mapParticleDefs = ItemSystem()->GetItemSchema()->GetAttributeControlledParticleSystems();
FOR_EACH_MAP( mapParticleDefs, i )
{
pKeyValues->SetInt( "unusual_index", mapParticleDefs[i].nSystemID );
char particleNameEntry[128];
Q_snprintf( particleNameEntry, ARRAYSIZE( particleNameEntry ), "#Attrib_Particle%i", mapParticleDefs[i].nSystemID );
m_pUnusualEffectComboBox->AddItem( g_pVGuiLocalize->Find( particleNameEntry ), pKeyValues );
}
m_pUnusualEffectComboBox->SilentActivateItemByRow( 0 );
m_pUnusualEffectComboBox->GetMenu()->SetBgColor( Color(0,0,0,255) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::SetEntryStep( testitem_entrysteps_t iStep )
{
// Skip over the item replacement if we're not a weapon
if ( iStep == TI_STEP_WPN_ITEMREPLACED && m_iItemType != TI_TYPE_WEAPON )
{
iStep = (testitem_entrysteps_t)(iStep+1);
}
if ( iStep == TI_STEP_NONWPN_BODYGROUPS || iStep == TI_STEP_OTHER_OPTIONS )
{
// Move to "finished" straight away
iStep = TI_STEP_FINISHED;
}
m_iEntryStep = iStep;
if ( m_pSelectModelButton )
{
m_pSelectModelButton->SetVisible( iStep >= TI_STEP_MODELNAME );
m_pSelectModelLabel->SetVisible( iStep >= TI_STEP_MODELNAME );
m_pModelLabel->SetVisible( iStep >= TI_STEP_MODELNAME );
}
bool bTestingExistingItem = (iStep > TI_STEP_MODELNAME && m_szRelativePath[0] == '\0');
m_pBodygroupPanel->SetVisible( iStep >= TI_STEP_NONWPN_BODYGROUPS && m_iItemType != TI_TYPE_WEAPON && !bTestingExistingItem );
m_pExistingItemToTestPanel->SetVisible( iStep == TI_STEP_MODELNAME || bTestingExistingItem );
m_pItemReplacedPanel->SetVisible( iStep >= TI_STEP_WPN_ITEMREPLACED && m_iItemType == TI_TYPE_WEAPON && !bTestingExistingItem );
if ( m_pNoItemsToReplaceLabel )
{
m_pNoItemsToReplaceLabel->SetVisible( false );
}
m_pCustomizationsPanel->SetVisible( (iStep >= TI_STEP_CUSTOMIZATION && m_iItemType != TI_TYPE_WEAPON) );
if ( m_pOkButton )
{
m_pOkButton->SetEnabled( m_iEntryStep >= TI_STEP_FINISHED );
}
switch ( m_iEntryStep )
{
case TI_STEP_MODELNAME:
if ( !m_szRelativePath[0] )
{
SetDialogVariable("testmodel", g_pVGuiLocalize->Find( "#IT_NoModel" ) );
}
SetupItemComboBox( m_pExistingItemComboBox );
break;
case TI_STEP_WPN_ITEMREPLACED:
SetupItemComboBox( m_pItemReplacedComboBox );
break;
case TI_STEP_NONWPN_BODYGROUPS:
break;
default:
case TI_STEP_FINISHED:
break;
}
SetDialogVariable( "testtitle", g_pVGuiLocalize->Find( VarArgs("#IT_Title_%d",m_iItemType) ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::OnTextChanged( KeyValues *data )
{
Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
if ( pPanel == m_pExistingItemComboBox )
{
if ( m_iItemType != TI_TYPE_WEAPON )
{
SetEntryStep( TI_STEP_OTHER_OPTIONS );
}
else
{
SetEntryStep( TI_STEP_FINISHED );
}
}
else if ( pPanel == m_pItemReplacedComboBox )
{
SetEntryStep( TI_STEP_FINISHED );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemDialog::OnFileSelected(const char *fullpath)
{
m_szRelativePath[0] = '\0';
if ( g_pFullFileSystem->FullPathToRelativePathEx( fullpath, "GAME", m_szRelativePath, sizeof(m_szRelativePath) ) )
{
Q_FixSlashes( m_szRelativePath, '/' );
SetDialogVariable("testmodel", m_szRelativePath );
SetEntryStep( TI_STEP_WPN_ITEMREPLACED );
}
else
{
SetDialogVariable("testmodel", g_pVGuiLocalize->Find( "#IT_NoModel" ) );
}
// Nuke the file open dialog
m_hImportModelDialog->MarkForDeletion();
m_hImportModelDialog = NULL;
}
+99
View File
@@ -0,0 +1,99 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TESTITEM_DIALOG_H
#define TESTITEM_DIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "tf_controls.h"
enum testitem_entrysteps_t
{
TI_STEP_MODELNAME,
TI_STEP_WPN_ITEMREPLACED,
TI_STEP_NONWPN_BODYGROUPS,
TI_STEP_OTHER_OPTIONS,
TI_STEP_CUSTOMIZATION,
TI_STEP_FINISHED,
};
enum testitem_bodygroups_to_hide_t
{
TI_HIDEBG_HAT,
TI_HIDEBG_HEADPHONES,
TI_HIDEBG_MEDALS,
TI_HIDEBG_GRENADES,
TI_HIDEBG_BULLETS,
TI_HIDEBG_ARROWS,
TI_HIDEBG_RIGHTARM,
TI_HIDEBG_SHOES_SOCKS,
TI_HIDEBG_COUNT,
};
//-----------------------------------------------------------------------------
// A dialog that handles adding or modifying an item we're testing
//-----------------------------------------------------------------------------
class CTestItemDialog : public vgui::EditablePanel, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CTestItemDialog, vgui::EditablePanel );
public:
CTestItemDialog( vgui::Panel *parent, testitem_itemtypes_t iItemType, int iClassUsage, KeyValues *pExistingKVs );
~CTestItemDialog( void );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout( void );
virtual void OnCommand( const char *command );
virtual void FireGameEvent( IGameEvent *event );
void Close( void );
void CloseAndUpdateItem( void );
MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
MESSAGE_FUNC_CHARPTR( OnFileSelected, "FileSelected", fullpath );
private:
void InitializeFromExistingKVs( KeyValues *pExistingKVs );
void SetEntryStep( testitem_entrysteps_t iStep );
void OpenSelectModelDialog( void );
void SetupItemComboBox( vgui::ComboBox *pComboBox );
void SetupPaintColorComboBox( void );
void SetupUnusualEffectComboBox( void );
void HandleClassCheckbuttonChecked( vgui::Panel *pPanel );
private:
testitem_entrysteps_t m_iEntryStep;
testitem_itemtypes_t m_iItemType;
int m_iClassUsage;
vgui::FileOpenDialog *m_hImportModelDialog;
char m_szRelativePath[MAX_PATH];
CExLabel *m_pModelLabel;
CExLabel *m_pSelectModelLabel;
CExLabel *m_pNoItemsToReplaceLabel;
CExButton *m_pSelectModelButton;
CExButton *m_pOkButton;
vgui::ComboBox *m_pItemReplacedComboBox;
vgui::EditablePanel *m_pBodygroupPanel;
vgui::EditablePanel *m_pItemReplacedPanel;
vgui::CheckButton *m_pBodygroupCheckButtons[TI_HIDEBG_COUNT];
vgui::EditablePanel *m_pCustomizationsPanel;
vgui::ComboBox *m_pPaintColorComboBox;
vgui::ComboBox *m_pUnusualEffectComboBox;
vgui::EditablePanel *m_pExistingItemToTestPanel;
vgui::ComboBox *m_pExistingItemComboBox;
};
#endif // TESTITEM_DIALOG_H
+931
View File
@@ -0,0 +1,931 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include <vgui/ILocalize.h>
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/ComboBox.h"
#include "vgui_controls/CheckButton.h"
#include "testitem_root.h"
#include "tf_controls.h"
#include "c_playerresource.h"
#include "gcsdk/gcmsg.h"
#include "tf_gcmessages.h"
#include "econ_item_inventory.h"
#include "econ_gcmessages.h"
#include "ienginevgui.h"
#include "econ_item_system.h"
#include "vgui_controls/FileOpenDialog.h"
#include <filesystem.h>
#include "ai_activity.h"
#include "tf_gamerules.h"
#include "vgui_controls/Slider.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
ConVar tf_testitem_recent( "tf_testitem_recent", "", FCVAR_ARCHIVE );
KeyValues *g_pRootItemTestingKV = NULL;
// Bot animations
const char *g_pszBotAnimStrings[TI_BOTANIM_COUNT] =
{
"#IT_BotAnim_Idle", // TI_BOTANIM_IDLE,
"#IT_BotAnim_Crouch_Idle", // TI_BOTANIM_CROUCH,
"#IT_BotAnim_Run", // TI_BOTANIM_RUN,
"#IT_BotAnim_Crouch_Walk", // TI_BOTANIM_CROUCH_WALK
"#IT_BotAnim_Jump", // TI_BOTANIM_JUMP
};
void UpdateItemTestKVs( void )
{
KeyValues *pTmpCopy = g_pRootItemTestingKV->MakeCopy();
engine->ServerCmdKeyValues( pTmpCopy );
// Setup any clientside variables to match what we're sending to the server
TFGameRules()->ItemTesting_SetupFromKV( g_pRootItemTestingKV );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTestItemRoot::CTestItemRoot( vgui::Panel *parent ) : vgui::EditablePanel( parent, "TestItemRoot" )
{
// Need to use the clientscheme (we're not parented to a clientscheme'd panel)
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
SetScheme(scheme);
SetProportional( true );
ListenForGameEvent( "gameui_hidden" );
m_hEditItemDialog = NULL;
m_iClassUsage = 0;
m_pClassUsagePanel = NULL;
m_pTestingPanel = NULL;
m_hImportExportDialog = NULL;
m_bExporting = false;
memset( m_pItemTestButtons, 0, sizeof(m_pItemTestButtons) );
memset( m_pItemRemoveButtons, 0, sizeof(m_pItemRemoveButtons) );
memset( m_pClassCheckButtons, NULL, sizeof(m_pClassCheckButtons) );
memset( m_pItemTestKVs, 0, sizeof(m_pItemTestKVs) );
m_pBotAdditionPanel = new vgui::EditablePanel( this, "BotAdditionPanel" );
m_pBotSelectionComboBox = new vgui::ComboBox( m_pBotAdditionPanel, "BotSelectionComboBox", 9, false );
m_pBotSelectionComboBox->AddActionSignalTarget( this );
m_pAutoAddBotsCheckBox = new vgui::CheckButton( m_pBotAdditionPanel, "AutoAddBotsCheckBox", "" );
m_pAutoAddBotsCheckBox->AddActionSignalTarget( this );
m_pAutoAddBotsCheckBox->SetSelected( true );
m_pBotsOnBlueTeamCheckBox = new vgui::CheckButton( m_pBotAdditionPanel, "BotsOnBlueTeamCheckBox", "" );
m_pBotsOnBlueTeamCheckBox->AddActionSignalTarget( this );
m_pBotsOnBlueTeamCheckBox->SetSelected( true );
m_pAddBotButton = NULL;
m_pBotControlPanel = new CTestItemBotControls( this );
m_pBotControlPanel->SetEmbedded( true );
SetupComboBoxes();
if ( !g_pRootItemTestingKV )
{
g_pRootItemTestingKV = new KeyValues( "TestItems" );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTestItemRoot::~CTestItemRoot( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::SetupComboBoxes( void )
{
// Setup our Bot Selection combo box
KeyValues *pKeyValues;
for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass <= TF_LAST_NORMAL_CLASS; iClass++ )
{
if ( iClass == TF_CLASS_CIVILIAN )
continue;
pKeyValues = new KeyValues( "data" );
pKeyValues->SetInt( "class", iClass );
m_pBotSelectionComboBox->AddItem( g_aPlayerClassNames[iClass], pKeyValues );
}
m_pBotSelectionComboBox->SilentActivateItemByRow( 0 );
m_pBotControlPanel->SetupComboBoxes();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/TestItemRoot.res" );
m_pTestingPanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName( "TestingPanel" ) );
if ( m_pTestingPanel )
{
for ( int i = 0; i < TI_TYPE_COUNT; i++ )
{
m_pItemTestButtons[i] = dynamic_cast<CExButton*>( m_pTestingPanel->FindChildByName( VarArgs("TestItemButton%d",i) ) );
m_pItemTestButtons[i]->AddActionSignalTarget( this );
m_pItemRemoveButtons[i] = dynamic_cast<CExButton*>( m_pTestingPanel->FindChildByName( VarArgs("RemoveItemButton%d",i) ) );
m_pItemRemoveButtons[i]->AddActionSignalTarget( this );
m_pItemTestLabels[i] = dynamic_cast<CExLabel*>( m_pTestingPanel->FindChildByName( VarArgs("TestItemEntry%d",i) ) );
}
}
m_pClassUsagePanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName( "ClassUsagePanel" ) );
if ( m_pClassUsagePanel )
{
for ( int i = 0; i < TF_LAST_NORMAL_CLASS; i++ )
{
m_pClassCheckButtons[i] = dynamic_cast<vgui::CheckButton*>( m_pClassUsagePanel->FindChildByName( VarArgs("ClassCheckBox%d",i)) );
m_pClassCheckButtons[i]->AddActionSignalTarget( this );
}
}
m_pAddBotButton = dynamic_cast<CExButton*>( m_pBotAdditionPanel->FindChildByName( "AddBotButton" ) );
if ( m_pAddBotButton )
{
m_pAddBotButton->AddActionSignalTarget( this );
}
CExButton *pKickAllBotsButton = dynamic_cast<CExButton*>( m_pBotAdditionPanel->FindChildByName( "KickAllBotsButton" ) );
if ( pKickAllBotsButton )
{
pKickAllBotsButton->AddActionSignalTarget( this );
}
AddChildActionSignalTarget( this, "SteamWorkshopButtonSubButton", this, true );
UpdateTestItems();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::PerformLayout( void )
{
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::FireGameEvent( IGameEvent *event )
{
const char *type = event->GetName();
if ( Q_strcmp(type, "gameui_hidden") == 0 )
{
Close();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::Close( void )
{
TFModalStack()->PopModal( this );
SetVisible( false );
MarkForDeletion();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::OnSetTestItemKVs( KeyValues *pKV )
{
if ( !pKV )
return;
testitem_itemtypes_t iItemType = (testitem_itemtypes_t)pKV->GetInt("item_type");
if ( iItemType <= TI_TYPE_UNKNOWN || iItemType > TI_TYPE_COUNT )
return;
// If we already have KVs for that slot, nuke them
if ( m_pItemTestKVs[iItemType] )
{
g_pRootItemTestingKV->RemoveSubKey( m_pItemTestKVs[iItemType] );
m_pItemTestKVs[iItemType]->deleteThis();
}
// Make our copy, and store it in the root KVs
m_pItemTestKVs[iItemType] = pKV->MakeCopy();
m_pItemTestKVs[iItemType]->SetName( VarArgs("Item%d",iItemType) );
g_pRootItemTestingKV->AddSubKey( m_pItemTestKVs[iItemType] );
UpdateTestItems();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::OnButtonChecked( KeyValues *pData )
{
Panel *pPanel = reinterpret_cast<vgui::Panel *>( pData->GetPtr("panel") );
if ( pPanel == m_pAutoAddBotsCheckBox )
{
if ( m_pAutoAddBotsCheckBox->IsSelected() )
{
m_pAddBotButton->SetEnabled( false );
m_pBotSelectionComboBox->SetEnabled( false );
}
else
{
m_pAddBotButton->SetEnabled( true );
m_pBotSelectionComboBox->SetEnabled( true );
}
return;
}
// If they hit all classes, disable everything else.
if ( pPanel == m_pClassCheckButtons[0] )
{
bool bAllClass = m_pClassCheckButtons[0]->IsSelected();
for ( int i = 1; i < TF_LAST_NORMAL_CLASS; i++ )
{
m_pClassCheckButtons[i]->SetEnabled( !bAllClass );
if ( bAllClass )
{
m_pClassCheckButtons[i]->SetSelected( false );
}
}
}
else
{
// If they've individually checked all boxes, switch to all-classes being checked
bool bAllChecked = true;
for ( int i = 1; i < TF_LAST_NORMAL_CLASS; i++ )
{
if ( !m_pClassCheckButtons[i]->IsSelected() )
{
bAllChecked = false;
break;
}
}
if ( bAllChecked )
{
m_pClassCheckButtons[0]->SetSelected( true );
}
}
m_iClassUsage = 0;
for ( int i = 0; i < TF_LAST_NORMAL_CLASS; i++ )
{
if ( m_pClassCheckButtons[i]->IsSelected() )
{
m_iClassUsage |= (1 << i);
}
}
UpdateTestItems();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::CommitSettingsToKV( void )
{
g_pRootItemTestingKV->SetInt( "class_usage", m_iClassUsage );
g_pRootItemTestingKV->SetInt( "auto_add_bots", m_pAutoAddBotsCheckBox->IsSelected() );
g_pRootItemTestingKV->SetInt( "bots_on_blue_team", m_pBotsOnBlueTeamCheckBox->IsSelected() );
m_pBotControlPanel->CommitSettingsToKV();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::OnFileSelected(const char *fullpath)
{
if ( m_bExporting )
{
ExportTestSetup( fullpath );
}
else
{
ImportTestSetup( fullpath );
}
// Nuke the file open dialog
m_hImportExportDialog->MarkForDeletion();
m_hImportExportDialog = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::ExportTestSetup( const char *pFilename )
{
if ( !pFilename || !pFilename[0] )
return;
CommitSettingsToKV();
g_pRootItemTestingKV->SaveToFile( g_pFullFileSystem, pFilename );
tf_testitem_recent.SetValue( pFilename );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::ImportTestSetup( KeyValues *pKV )
{
// Setup the class usage checkboxes
m_iClassUsage = pKV->GetInt( "class_usage", 0 );
for ( int i = 0; i < TF_LAST_NORMAL_CLASS; i++ )
{
m_pClassCheckButtons[i]->SetSelected( (m_iClassUsage & (1<<i)) );
}
// Pull out the item KV blocks
for ( int i = 0; i < TI_TYPE_COUNT; i++ )
{
m_pItemTestKVs[i] = pKV->FindKey( VarArgs("Item%d",i) );
}
bool bAutoAdd = pKV->GetInt( "auto_add_bots", 1 );
m_pAutoAddBotsCheckBox->SetSelected(bAutoAdd);
bool bBlueTeamBots = pKV->GetInt( "bots_on_blue_team", 0 );
m_pBotsOnBlueTeamCheckBox->SetSelected(bBlueTeamBots);
m_pBotControlPanel->ImportTestSetup( pKV );
UpdateTestItems();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::ImportTestSetup( const char *pFilename )
{
if ( !pFilename || !pFilename[0] )
return;
g_pRootItemTestingKV->deleteThis();
g_pRootItemTestingKV = new KeyValues( "TestItems" );
if ( g_pRootItemTestingKV->LoadFromFile( g_pFullFileSystem, pFilename ) )
{
ImportTestSetup( g_pRootItemTestingKV );
}
else
{
m_iClassUsage = 0;
memset( m_pItemTestKVs, 0, sizeof(m_pItemTestKVs) );
g_pRootItemTestingKV->deleteThis();
g_pRootItemTestingKV = new KeyValues( "TestItems" );
UpdateTestItems();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CTestItemRoot::FindReplaceableItemsForSelectedClass( CUtlVector<item_definition_index_t> *pItemDefs, bool bWeapons )
{
// Build our list of checked classes
bool bClasses[TF_LAST_NORMAL_CLASS];
for ( int i = 0; i < TF_LAST_NORMAL_CLASS; i++ )
{
bClasses[i] = m_iClassUsage & (1 << i);
}
int iReplaceableItems = 0;
// Find all the weapons that can be used by the combination of classes we've checked
const CEconItemSchema::SortedItemDefinitionMap_t& mapItemDefs = ItemSystem()->GetItemSchema()->GetSortedItemDefinitionMap();
FOR_EACH_MAP( mapItemDefs, i )
{
const CTFItemDefinition *pDef = dynamic_cast<const CTFItemDefinition *>( mapItemDefs[i] );
// Never show:
// - Hidden items
// - Items that don't have fixed qualities
if ( !pDef || pDef->IsHidden() || pDef->GetQuality() == k_unItemQuality_Any )
continue;
// Only show in staging (internal dev branch):
// - Normal quality items
// - Items that haven't asked to be shown in the armory
static const bool bIsStaging = ( engine->GetAppID() == 810 );
if ( !bIsStaging )
{
if ( pDef->GetQuality() == AE_NORMAL || !pDef->ShouldShowInArmory() )
continue;
}
// Make sure it's the right type of item
int iDefSlot = pDef->GetDefaultLoadoutSlot();
bool bValidSlot = false;
if ( bWeapons )
{
bValidSlot = (iDefSlot == LOADOUT_POSITION_PRIMARY || iDefSlot == LOADOUT_POSITION_SECONDARY || iDefSlot == LOADOUT_POSITION_MELEE );
if ( !bValidSlot )
{
bValidSlot = pDef->CanBePlacedInSlot(LOADOUT_POSITION_PRIMARY) || pDef->CanBePlacedInSlot(LOADOUT_POSITION_SECONDARY) || pDef->CanBePlacedInSlot(LOADOUT_POSITION_MELEE);
}
}
else
{
bValidSlot = (iDefSlot == LOADOUT_POSITION_HEAD || iDefSlot == LOADOUT_POSITION_MISC );
if ( !bValidSlot )
{
bValidSlot = pDef->CanBePlacedInSlot(LOADOUT_POSITION_HEAD) || pDef->CanBePlacedInSlot(LOADOUT_POSITION_MISC);
}
}
if ( !bValidSlot )
continue;
// Make sure it's used by all the checked classes
bool bUsable = false;
if ( bClasses[0] )
{
bUsable = pDef->CanBeUsedByAllClasses();
}
else
{
bUsable = true;
for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass < TF_LAST_NORMAL_CLASS; iClass++ )
{
if ( bClasses[iClass] && !pDef->CanBeUsedByClass(iClass) )
{
bUsable = false;
break;
}
}
}
if ( !bUsable )
continue;
if ( pItemDefs )
{
pItemDefs->AddToTail( pDef->GetDefinitionIndex() );
}
iReplaceableItems++;
}
return iReplaceableItems;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::UpdateTestItems( void )
{
for ( int i = 0; i < TI_TYPE_COUNT; i++ )
{
// Weapon is handled specially, because it's tied to the class usage
if ( i == TI_TYPE_WEAPON )
{
int iValidWeapons = FindReplaceableItemsForSelectedClass( NULL, true );
m_pItemTestButtons[0]->SetEnabled( iValidWeapons );
if ( !iValidWeapons )
{
m_pItemTestLabels[0]->SetText( g_pVGuiLocalize->Find("#IT_ItemReplaced_Invalid") );
continue;
}
}
if ( m_pItemTestKVs[i] )
{
m_pItemTestButtons[i]->SetText( "#IT_Item_Edit" );
item_definition_index_t iExistingDef = m_pItemTestKVs[i]->GetInt( "existing_itemdef", INVALID_ITEM_DEF_INDEX );
if ( iExistingDef != INVALID_ITEM_DEF_INDEX )
{
CEconItemDefinition *pDef = ItemSystem()->GetItemSchema()->GetItemDefinition(iExistingDef);
if ( pDef )
{
m_pItemTestLabels[i]->SetText( g_pVGuiLocalize->Find( pDef->GetItemBaseName() ) );
}
else
{
m_pItemTestLabels[i]->SetText( "#IT_TestingSlot_Empty" );
}
}
else
{
const char *pszModel = m_pItemTestKVs[i]->GetString("model_player", "#IT_TestingSlot_Empty");
char szModel[MAX_PATH+1]="";
Q_FileBase( pszModel, szModel, ARRAYSIZE( szModel ) );
m_pItemTestLabels[i]->SetText( szModel );
}
m_pItemRemoveButtons[i]->SetEnabled( true );
}
else
{
m_pItemTestButtons[i]->SetText( "#IT_Item_Add" );
m_pItemTestLabels[i]->SetText( "#IT_TestingSlot_Empty" );
m_pItemRemoveButtons[i]->SetEnabled( false );
}
}
// Hide the testing panel if we don't have any classes selected
if ( m_pTestingPanel )
{
m_pTestingPanel->SetVisible( m_iClassUsage != 0 );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::CloseAndTestItem( void )
{
// Go through and update the schema definitions before we send them off to the server
for ( int i = 0; i < TI_TYPE_COUNT; i++ )
{
if ( !m_pItemTestKVs[i] )
continue;
item_definition_index_t iNewDef = TESTITEM_DEFINITIONS_BEGIN_AT + i;
item_definition_index_t iItemDef = m_pItemTestKVs[i]->GetInt( "item_replace", INVALID_ITEM_DEF_INDEX );
ItemSystem()->GetItemSchema()->ItemTesting_CreateTestDefinition( iItemDef, iNewDef, m_pItemTestKVs[i] );
m_pItemTestKVs[i]->SetInt( "item_def", iNewDef );
}
// Not connected to a game?
if ( !TFGameRules() )
return;
CommitSettingsToKV();
g_pRootItemTestingKV->SetName("TestItems");
UpdateItemTestKVs();
Close();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemRoot::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "cancel" ) )
{
Close();
return;
}
else if ( !Q_stricmp( command, "ok" ) )
{
CloseAndTestItem();
return;
}
else if ( !Q_stricmp( command, "steamworkshop" ) )
{
Close();
engine->ClientCmd_Unrestricted( "OpenSteamWorkshopDialog;" );
}
else if ( !Q_stricmp( command, "reloadscheme" ) )
{
InvalidateLayout( false, true );
return;
}
else if ( !Q_strnicmp( command, "item_test", 9 ) )
{
int iItemType = atoi( command+9 );
if ( iItemType >= 0 && iItemType < TI_TYPE_COUNT )
{
if (!m_hEditItemDialog.Get())
{
m_hEditItemDialog = vgui::SETUP_PANEL( new CTestItemDialog( this, (testitem_itemtypes_t)iItemType, m_iClassUsage, m_pItemTestKVs[iItemType] ) );
}
m_hEditItemDialog->InvalidateLayout( false, true );
m_hEditItemDialog->SetVisible( true );
m_hEditItemDialog->MoveToFront();
m_hEditItemDialog->SetKeyBoardInputEnabled(true);
m_hEditItemDialog->SetMouseInputEnabled(true);
TFModalStack()->PushModal( m_hEditItemDialog );
}
return;
}
else if ( !Q_strnicmp( command, "item_remove", 11 ) )
{
int iItemType = atoi( command+11 );
if ( iItemType >= 0 && iItemType < TI_TYPE_COUNT )
{
if ( m_pItemTestKVs[iItemType] )
{
g_pRootItemTestingKV->RemoveSubKey( m_pItemTestKVs[iItemType] );
m_pItemTestKVs[iItemType]->deleteThis();
m_pItemTestKVs[iItemType] = NULL;
}
UpdateTestItems();
}
return;
}
else if ( !Q_stricmp( command, "export" ) || !Q_stricmp( command, "import" ) )
{
m_bExporting = ( command[0] == 'e' );
if (m_hImportExportDialog == NULL)
{
m_hImportExportDialog = new vgui::FileOpenDialog( NULL, "#ToolCustomizeTextureTitle", m_bExporting ? vgui::FOD_SAVE : vgui::FOD_OPEN, NULL );
m_hImportExportDialog->AddFilter( "*.itf", "#IT_TestingFiles", true );
m_hImportExportDialog->AddActionSignalTarget( this );
char szModelsDir[MAX_PATH];
m_hImportExportDialog->SetStartDirectory( g_pFullFileSystem->RelativePathToFullPath( "cfg", "MOD", szModelsDir, sizeof(szModelsDir) ) );
}
m_hImportExportDialog->DoModal( false );
m_hImportExportDialog->Activate();
return;
}
else if ( !Q_stricmp( command, "importrecent" ) )
{
ImportTestSetup( tf_testitem_recent.GetString() );
return;
}
else if ( !Q_stricmp( command, "bot_add" ) )
{
KeyValues *pKV = m_pBotSelectionComboBox->GetActiveItemUserData();
int iClass = pKV->GetInt( "class", TF_CLASS_UNDEFINED );
if ( iClass >= TF_FIRST_NORMAL_CLASS && iClass < TF_LAST_NORMAL_CLASS )
{
bool bBlueTeam = m_pBotsOnBlueTeamCheckBox->IsSelected();
engine->ClientCmd_Unrestricted( VarArgs( "bot -team %s -class %s\n", bBlueTeam ? "blue" : "red", g_aPlayerClassNames_NonLocalized[iClass] ) );
}
return;
}
else if ( !Q_stricmp( command, "bot_removeall" ) )
{
// Kick everyone above the first player
for ( int i = 2; i <= gpGlobals->maxClients; i++ )
{
C_BasePlayer *pPlayer = UTIL_PlayerByIndex( i );
if ( pPlayer )
{
engine->ClientCmd_Unrestricted( VarArgs( "kickid %d\n", pPlayer->GetUserID() ) );
}
}
return;
}
BaseClass::OnCommand( command );
}
static vgui::DHANDLE<CTestItemRoot> g_hTestItemRoot;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void OpenTestItemRoot( void )
{
if (!g_hTestItemRoot.Get())
{
g_hTestItemRoot = vgui::SETUP_PANEL( new CTestItemRoot( NULL ) );
}
g_hTestItemRoot->SetVisible( true );
g_hTestItemRoot->MakePopup();
g_hTestItemRoot->MoveToFront();
g_hTestItemRoot->SetKeyBoardInputEnabled(true);
g_hTestItemRoot->SetMouseInputEnabled(true);
TFModalStack()->PushModal( g_hTestItemRoot );
g_hTestItemRoot->MakeReadyForUse();
if ( g_pRootItemTestingKV )
{
g_hTestItemRoot->ImportTestSetup( g_pRootItemTestingKV );
}
}
ConCommand testitem( "itemtest", OpenTestItemRoot, "Open the item testing panel.", FCVAR_NONE );
//========================================================================================================================================
// BOT CONTROLS PANEL
//========================================================================================================================================
static vgui::DHANDLE<CTestItemBotControls> g_hTestItemBotControls;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTestItemBotControls::CTestItemBotControls( vgui::Panel *parent ) : vgui::EditablePanel( parent, "TestItemBotControls" )
{
// Need to use the clientscheme (we're not parented to a clientscheme'd panel)
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
SetScheme(scheme);
SetProportional( true );
ListenForGameEvent( "gameui_hidden" );
m_pBotAnimationComboBox = new vgui::ComboBox( this, "BotAnimationComboBox", 9, false );
m_pBotAnimationComboBox->AddActionSignalTarget( this );
m_pBotForceFireCheckBox = new vgui::CheckButton( this, "BotForceFireCheckBox", "" );
m_pBotForceFireCheckBox->AddActionSignalTarget( this );
m_pBotTurntableCheckBox = new vgui::CheckButton( this, "BotTurntableCheckBox", "" );
m_pBotTurntableCheckBox->AddActionSignalTarget( this );
m_pBotViewScanCheckBox = new vgui::CheckButton( this, "BotViewScanCheckBox", "" );
m_pBotViewScanCheckBox->AddActionSignalTarget( this );
m_pBotAnimationSpeedSlider = new vgui::Slider( this, "BotAnimationSpeedSlider" );
m_pBotAnimationSpeedSlider->SetRange( 0, 100 );
m_pBotAnimationSpeedSlider->SetNumTicks( 10 );
m_pBotAnimationSpeedSlider->AddActionSignalTarget( this );
m_bEmbedded = false;
SetupComboBoxes();
if ( !g_pRootItemTestingKV )
{
g_pRootItemTestingKV = new KeyValues( "TestItems" );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTestItemBotControls::~CTestItemBotControls( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemBotControls::SetupComboBoxes( void )
{
KeyValues *pKeyValues;
// Setup our bot animation combo box
for ( int i = 0; i < TI_BOTANIM_COUNT; i++ )
{
pKeyValues = new KeyValues( "data" );
pKeyValues->SetInt( "anim", i );
m_pBotAnimationComboBox->AddItem( g_pszBotAnimStrings[i], pKeyValues );
}
m_pBotAnimationComboBox->SilentActivateItemByRow( 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemBotControls::FireGameEvent( IGameEvent *event )
{
const char *type = event->GetName();
if ( Q_strcmp(type, "gameui_hidden") == 0 )
{
Close();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemBotControls::Close( void )
{
TFModalStack()->PopModal( this );
SetVisible( false );
MarkForDeletion();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemBotControls::ImportTestSetup( KeyValues *pKV )
{
bool bForceFire = pKV->GetInt( "bot_force_fire", 0 );
m_pBotForceFireCheckBox->SetSelected(bForceFire);
bool bViewScan = pKV->GetInt( "bot_view_scan", 0 );
m_pBotViewScanCheckBox->SetSelected(bViewScan);
bool bTurnTable = pKV->GetInt( "bot_turntable", 0 );
m_pBotTurntableCheckBox->SetSelected(bTurnTable);
int iAnim = g_pRootItemTestingKV->GetInt( "bot_anim", TI_BOTANIM_IDLE );
m_pBotAnimationComboBox->SilentActivateItemByRow( iAnim );
int iAnimSpeed = g_pRootItemTestingKV->GetInt( "bot_animspeed", 100 );
m_pBotAnimationSpeedSlider->SetValue( iAnimSpeed, false );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemBotControls::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/TestItemBotControls.res" );
// Dumb, but the slider needs to have its scheme forcibly loaded to make it create the left/right text
m_pBotAnimationSpeedSlider->InvalidateLayout( true, true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemBotControls::PerformLayout( void )
{
BaseClass::PerformLayout();
CExButton *pButton = dynamic_cast<CExButton*>( FindChildByName( "OkButton" ) );
if ( pButton )
{
pButton->SetVisible( !m_bEmbedded );
}
pButton = dynamic_cast<CExButton*>( FindChildByName( "CloseButton" ) );
if ( pButton )
{
pButton->SetVisible( !m_bEmbedded );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemBotControls::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "cancel" ) )
{
Close();
return;
}
else if ( !Q_stricmp( command, "ok" ) )
{
UpdateBots();
return;
}
else if ( !Q_stricmp( command, "reloadscheme" ) )
{
InvalidateLayout( false, true );
return;
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemBotControls::UpdateBots( void )
{
// Not connected to a game?
if ( !TFGameRules() )
return;
CommitSettingsToKV();
g_pRootItemTestingKV->SetName("TestItemsBotUpdate");
UpdateItemTestKVs();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTestItemBotControls::CommitSettingsToKV( void )
{
g_pRootItemTestingKV->SetInt( "bot_force_fire", m_pBotForceFireCheckBox->IsSelected() );
g_pRootItemTestingKV->SetInt( "bot_view_scan", m_pBotViewScanCheckBox->IsSelected() );
g_pRootItemTestingKV->SetInt( "bot_turntable", m_pBotTurntableCheckBox->IsSelected() );
KeyValues *pKV = m_pBotAnimationComboBox->GetActiveItemUserData();
int iAnim = pKV->GetInt( "anim", TI_BOTANIM_IDLE );
g_pRootItemTestingKV->SetInt( "bot_anim", iAnim );
int iAnimSpeed = clamp( m_pBotAnimationSpeedSlider->GetValue(), 0, 100 );
g_pRootItemTestingKV->SetInt( "bot_animspeed", iAnimSpeed );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void OpenTestItemBotControls( void )
{
if (!g_hTestItemBotControls.Get())
{
g_hTestItemBotControls = vgui::SETUP_PANEL( new CTestItemBotControls( NULL ) );
}
g_hTestItemBotControls->SetVisible( true );
g_hTestItemBotControls->MakePopup();
g_hTestItemBotControls->MoveToFront();
g_hTestItemBotControls->SetKeyBoardInputEnabled(true);
g_hTestItemBotControls->SetMouseInputEnabled(true);
TFModalStack()->PushModal( g_hTestItemBotControls );
g_hTestItemBotControls->MakeReadyForUse();
if ( g_pRootItemTestingKV )
{
g_hTestItemBotControls->ImportTestSetup( g_pRootItemTestingKV );
g_hTestItemBotControls->SetEmbedded( false );
}
}
ConCommand testitem_botcontrols( "itemtest_botcontrols", OpenTestItemBotControls, "Open the item testing bot control panel.", FCVAR_NONE );
+109
View File
@@ -0,0 +1,109 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TESTITEM_ROOT_H
#define TESTITEM_ROOT_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "tf_controls.h"
#include "testitem_dialog.h"
//-----------------------------------------------------------------------------
// A panel that handles the overall item testing process
//-----------------------------------------------------------------------------
class CTestItemBotControls : public vgui::EditablePanel, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CTestItemBotControls, vgui::EditablePanel );
public:
CTestItemBotControls( vgui::Panel *parent );
~CTestItemBotControls( void );
void SetupComboBoxes( void );
virtual void FireGameEvent( IGameEvent *event );
void ImportTestSetup( KeyValues *pKV );
void Close( void );
void SetEmbedded( bool bEmbedded ) { m_bEmbedded = bEmbedded; InvalidateLayout(); }
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout( void );
virtual void OnCommand( const char *command );
void UpdateBots( void );
void CommitSettingsToKV( void );
private:
vgui::ComboBox *m_pBotAnimationComboBox;
vgui::Slider *m_pBotAnimationSpeedSlider;
vgui::CheckButton *m_pBotForceFireCheckBox;
vgui::CheckButton *m_pBotTurntableCheckBox;
vgui::CheckButton *m_pBotViewScanCheckBox;
bool m_bEmbedded;
};
//-----------------------------------------------------------------------------
// A panel that handles the overall item testing process
//-----------------------------------------------------------------------------
class CTestItemRoot : public vgui::EditablePanel, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CTestItemRoot, vgui::EditablePanel );
public:
CTestItemRoot( vgui::Panel *parent );
~CTestItemRoot( void );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout( void );
virtual void OnCommand( const char *command );
virtual void FireGameEvent( IGameEvent *event );
void Close( void );
void CloseAndTestItem( void );
void UpdateTestItems( void );
int FindReplaceableItemsForSelectedClass( CUtlVector<item_definition_index_t> *pItemDefs = NULL, bool bWeapons = false );
void ExportTestSetup( const char *pFilename );
void ImportTestSetup( const char *pFilename );
void ImportTestSetup( KeyValues *pKV );
void CommitSettingsToKV( void );
MESSAGE_FUNC_PARAMS( OnSetTestItemKVs, "SetTestItemKVs", pKV );
MESSAGE_FUNC_PARAMS( OnButtonChecked, "CheckButtonChecked", pData );
MESSAGE_FUNC_CHARPTR( OnFileSelected, "FileSelected", fullpath );
private:
void SetupComboBoxes( void );
private:
int m_iClassUsage;
vgui::EditablePanel *m_pClassUsagePanel;
vgui::EditablePanel *m_pTestingPanel;
vgui::EditablePanel *m_pBotAdditionPanel;
CTestItemBotControls *m_pBotControlPanel;
// Testing panel
CExButton *m_pItemTestButtons[TI_TYPE_COUNT];
CExButton *m_pItemRemoveButtons[TI_TYPE_COUNT];
CExLabel *m_pItemTestLabels[TI_TYPE_COUNT];
vgui::CheckButton *m_pClassCheckButtons[TF_LAST_NORMAL_CLASS];
KeyValues *m_pItemTestKVs[TI_TYPE_COUNT];
// Bot addition panel
vgui::ComboBox *m_pBotSelectionComboBox;
vgui::CheckButton *m_pAutoAddBotsCheckBox;
vgui::CheckButton *m_pBotsOnBlueTeamCheckBox;
CExButton *m_pAddBotButton;
vgui::DHANDLE<CTestItemDialog> m_hEditItemDialog;
vgui::FileOpenDialog *m_hImportExportDialog;
bool m_bExporting;
};
#endif // TESTITEM_ROOT_H
+426
View File
@@ -0,0 +1,426 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/ImagePanel.h>
#include <vgui_controls/RichText.h>
#include <vgui_controls/Frame.h>
#include <vgui/IScheme.h>
#include <game/client/iviewport.h>
#include <vgui/IVGui.h>
#include <KeyValues.h>
#include <filesystem.h>
#include "vguicenterprint.h"
#include "tf_controls.h"
#include "basemodelpanel.h"
#include "tf_arenateammenu.h"
#include <convar.h>
#include "IGameUIFuncs.h" // for key bindings
#include "hud.h" // for gEngfuncs
#include "c_tf_player.h"
#include "tf_gamerules.h"
#include "c_team.h"
#include "tf_hud_notification_panel.h"
#include "inputsystem/iinputsystem.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CTFArenaTeamMenu::CTFArenaTeamMenu( IViewPort *pViewPort ) : CTeamMenu( pViewPort )
{
SetMinimizeButtonVisible( false );
SetMaximizeButtonVisible( false );
SetCloseButtonVisible( false );
SetVisible( false );
SetKeyBoardInputEnabled( true );
m_iTeamMenuKey = BUTTON_CODE_INVALID;
m_pAutoTeamButton = new CTFTeamButton( this, "teambutton2" );
m_pSpecTeamButton = new CTFTeamButton( this, "teambutton3" );
m_pSpecLabel = new CExLabel( this, "TeamMenuSpectate", "" );
#ifdef _X360
m_pFooter = new CTFFooter( this, "Footer" );
#else
m_pCancelButton = new CExButton( this, "CancelButton", "#TF_Cancel" );
m_pJoinAutoHintIcon = m_pJoinSpectatorsHintIcon = m_pCancelHintIcon = nullptr;
#endif
vgui::ivgui()->AddTickSignal( GetVPanel() );
m_bRedDisabled = false;
m_bBlueDisabled = false;
if ( ::input->IsSteamControllerActive() )
{
LoadControlSettings( "Resource/UI/HudArenaTeamMenu_SC.res" );
}
else
{
LoadControlSettings( "Resource/UI/HudArenaTeamMenu.res" );
}
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CTFArenaTeamMenu::~CTFArenaTeamMenu()
{
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
void CTFArenaTeamMenu::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
if ( ::input->IsSteamControllerActive() )
{
LoadControlSettings( "Resource/UI/HudArenaTeamMenu_SC.res" );
m_pCancelHintIcon = dynamic_cast< CSCHintIcon* >( FindChildByName( "CancelHintIcon" ) );
m_pJoinAutoHintIcon = dynamic_cast< CSCHintIcon* >( FindChildByName( "JoinAutoHintIcon" ) );
m_pJoinSpectatorsHintIcon = dynamic_cast< CSCHintIcon* >( FindChildByName( "JoinSpectatorsHintIcon" ) );
SetMouseInputEnabled( false );
}
else
{
LoadControlSettings( "Resource/UI/HudArenaTeamMenu.res" );
SetMouseInputEnabled( true );
m_pCancelHintIcon = m_pJoinAutoHintIcon = m_pJoinSpectatorsHintIcon = nullptr;
}
Update();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFArenaTeamMenu::ShowPanel( bool bShow )
{
if ( BaseClass::IsVisible() == bShow )
return;
if ( !gameuifuncs || !gViewPortInterface || !engine )
return;
if ( bShow )
{
if ( !C_TFPlayer::GetLocalTFPlayer() )
return;
if ( TFGameRules()->State_Get() == GR_STATE_TEAM_WIN &&
C_TFPlayer::GetLocalTFPlayer() &&
C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() != TFGameRules()->GetWinningTeam()
&& C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() != TEAM_SPECTATOR
&& C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() != TEAM_UNASSIGNED )
{
SetVisible( false );
CHudNotificationPanel *pNotifyPanel = GET_HUDELEMENT( CHudNotificationPanel );
if ( pNotifyPanel )
{
pNotifyPanel->SetupNotifyCustom( "#TF_CantChangeTeamNow", "ico_notify_flag_moving", C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() );
}
return;
}
gViewPortInterface->ShowPanel( PANEL_CLASS_RED, false );
gViewPortInterface->ShowPanel( PANEL_CLASS_BLUE, false );
engine->CheckPoint( "TeamMenu" );
InvalidateLayout( true, true );
Activate();
// get key bindings if shown
m_iTeamMenuKey = gameuifuncs->GetButtonCodeForBind( "changeteam" );
m_iScoreBoardKey = gameuifuncs->GetButtonCodeForBind( "showscores" );
GetFocusNavGroup().SetCurrentFocus( m_pAutoTeamButton->GetVPanel(), m_pAutoTeamButton->GetVPanel() );
ActivateSelectIconHint( GetFocusNavGroup().GetCurrentFocus() ? GetFocusNavGroup().GetCurrentFocus()->GetTabPosition() : -1 );
}
else
{
SetVisible( false );
if ( IsConsole() )
{
// Close the door behind us
CTFArenaTeamMenu *pButton = dynamic_cast< CTFArenaTeamMenu *> ( GetFocusNavGroup().GetCurrentFocus() );
if ( pButton )
{
pButton->OnCursorExited();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Activate the right selection hint icon, depending on the focus group number selected
//-----------------------------------------------------------------------------
void CTFArenaTeamMenu::ActivateSelectIconHint( int focus_group_number )
{
if ( m_pJoinAutoHintIcon ) m_pJoinAutoHintIcon->SetVisible( false );
if ( m_pJoinSpectatorsHintIcon ) m_pJoinSpectatorsHintIcon->SetVisible( false );
CSCHintIcon* icon = nullptr;
switch ( focus_group_number )
{
case 1: icon = m_pJoinAutoHintIcon; break;
case 2: icon = m_pJoinSpectatorsHintIcon; break;
}
if ( icon )
{
icon->SetVisible( true );
}
}
//-----------------------------------------------------------------------------
// Purpose: called to update the menu with new information
//-----------------------------------------------------------------------------
void CTFArenaTeamMenu::Update( void )
{
BaseClass::Update();
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( pLocalPlayer && ( pLocalPlayer->GetTeamNumber() != TEAM_UNASSIGNED ) )
{
#ifdef _X360
if ( m_pFooter )
{
m_pFooter->ShowButtonLabel( "cancel", true );
}
#else
if ( m_pCancelButton )
{
m_pCancelButton->SetVisible( true );
if ( m_pCancelHintIcon )
{
m_pCancelHintIcon->SetVisible( true );
}
}
#endif
}
else
{
#ifdef _X360
if ( m_pFooter )
{
m_pFooter->ShowButtonLabel( "cancel", false );
}
#else
if ( m_pCancelButton && m_pCancelButton->IsVisible() )
{
m_pCancelButton->SetVisible( false );
if ( m_pCancelHintIcon )
{
m_pCancelHintIcon->SetVisible( false );
}
}
#endif
}
}
#ifdef _X360
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFArenaTeamMenu::Join_Team( const CCommand &args )
{
if ( args.ArgC() > 1 )
{
char cmd[256];
Q_snprintf( cmd, sizeof( cmd ), "jointeam_nomenus %s", args.Arg( 1 ) );
OnCommand( cmd );
}
}
#endif
//-----------------------------------------------------------------------------
// Purpose: chooses and loads the text page to display that describes mapName map
//-----------------------------------------------------------------------------
void CTFArenaTeamMenu::LoadMapPage( const char *mapName )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFArenaTeamMenu::OnKeyCodePressed( KeyCode code )
{
if ( ( m_iTeamMenuKey != BUTTON_CODE_INVALID && m_iTeamMenuKey == code ) ||
code == KEY_XBUTTON_BACK ||
code == KEY_XBUTTON_B ||
code == STEAMCONTROLLER_B )
{
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( pLocalPlayer && ( pLocalPlayer->GetTeamNumber() != TEAM_UNASSIGNED ) )
{
ShowPanel( false );
}
}
else if( code == KEY_SPACE || code == STEAMCONTROLLER_Y )
{
engine->ClientCmd( "jointeam auto" );
ShowPanel( false );
OnClose();
}
else if( code == KEY_XBUTTON_A || code == KEY_XBUTTON_RTRIGGER || code == STEAMCONTROLLER_A )
{
// select the active focus
if ( GetFocusNavGroup().GetCurrentFocus() )
{
ipanel()->SendMessage( GetFocusNavGroup().GetCurrentFocus()->GetVPanel(), new KeyValues( "PressButton" ), GetVPanel() );
}
}
else if( code == KEY_XBUTTON_RIGHT || code == KEY_XSTICK1_RIGHT || code == STEAMCONTROLLER_DPAD_RIGHT )
{
CTFTeamButton *pButton;
pButton = dynamic_cast< CTFTeamButton *> ( GetFocusNavGroup().GetCurrentFocus() );
if ( pButton )
{
pButton->OnCursorExited();
GetFocusNavGroup().RequestFocusNext( pButton->GetVPanel() );
}
else
{
GetFocusNavGroup().RequestFocusNext( NULL );
}
pButton = dynamic_cast< CTFTeamButton * > ( GetFocusNavGroup().GetCurrentFocus() );
if ( pButton )
{
pButton->OnCursorEntered();
}
ActivateSelectIconHint( GetFocusNavGroup().GetCurrentFocus() ? GetFocusNavGroup().GetCurrentFocus()->GetTabPosition() : -1 );
}
else if( code == KEY_XBUTTON_LEFT || code == KEY_XSTICK1_LEFT || code == STEAMCONTROLLER_DPAD_LEFT )
{
CTFTeamButton *pButton;
pButton = dynamic_cast< CTFTeamButton *> ( GetFocusNavGroup().GetCurrentFocus() );
if ( pButton )
{
pButton->OnCursorExited();
GetFocusNavGroup().RequestFocusPrev( pButton->GetVPanel() );
}
else
{
GetFocusNavGroup().RequestFocusPrev( NULL );
}
pButton = dynamic_cast< CTFTeamButton * > ( GetFocusNavGroup().GetCurrentFocus() );
if ( pButton )
{
pButton->OnCursorEntered();
}
ActivateSelectIconHint( GetFocusNavGroup().GetCurrentFocus() ? GetFocusNavGroup().GetCurrentFocus()->GetTabPosition() : -1 );
}
else if ( m_iScoreBoardKey != BUTTON_CODE_INVALID && m_iScoreBoardKey == code )
{
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, true );
gViewPortInterface->PostMessageToPanel( PANEL_SCOREBOARD, new KeyValues( "PollHideCode", "code", code ) );
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}
//-----------------------------------------------------------------------------
// Purpose: Called when the user picks a team
//-----------------------------------------------------------------------------
void CTFArenaTeamMenu::OnCommand( const char *command )
{
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( Q_stricmp( command, "vguicancel" ) )
{
// we're selecting a team, so make sure it's not the team we're already on before sending to the server
if ( pLocalPlayer && ( Q_strstr( command, "jointeam " ) ) )
{
engine->ClientCmd( command );
}
else if ( pLocalPlayer && ( Q_strstr( command, "jointeam_nomenus " ) ) )
{
engine->ClientCmd( command );
}
}
BaseClass::OnCommand( command );
ShowPanel( false );
OnClose();
}
//-----------------------------------------------------------------------------
// Frame-based update
//-----------------------------------------------------------------------------
void CTFArenaTeamMenu::OnTick()
{
// update the number of players on each team
// enable or disable buttons based on team limit
C_Team *pRed = GetGlobalTeam( TF_TEAM_RED );
C_Team *pBlue = GetGlobalTeam( TF_TEAM_BLUE );
if ( !pRed || !pBlue )
return;
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pLocalPlayer )
return;
CTFGameRules *pRules = TFGameRules();
if ( !pRules )
return;
if ( m_pSpecTeamButton && m_pSpecLabel )
{
{
if ( mp_allowspectators.GetBool() )
{
if ( !m_pSpecTeamButton->IsVisible() )
{
m_pSpecTeamButton->SetVisible( true );
m_pSpecLabel->SetVisible( true );
}
}
else
{
if ( m_pSpecTeamButton->IsVisible() )
{
m_pSpecTeamButton->SetVisible( false );
m_pSpecLabel->SetVisible( false );
}
}
}
}
}
+79
View File
@@ -0,0 +1,79 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef TF_ARENATEAMMENU_H
#define TF_ARENATEAMMENU_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_controls.h"
#include <teammenu.h>
#include "tf_teammenu.h"
//-----------------------------------------------------------------------------
// Purpose: Displays the team menu
//-----------------------------------------------------------------------------
class CTFArenaTeamMenu : public CTeamMenu
{
private:
DECLARE_CLASS_SIMPLE( CTFArenaTeamMenu, CTeamMenu );
public:
CTFArenaTeamMenu( IViewPort *pViewPort );
~CTFArenaTeamMenu();
void Update();
void ShowPanel( bool bShow );
#ifdef _X360
CON_COMMAND_MEMBER_F( CTFTeamMenu, "join_team", Join_Team, "Send a jointeam command", 0 );
#endif
protected:
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void OnKeyCodePressed( vgui::KeyCode code );
// command callbacks
virtual void OnCommand( const char *command );
virtual void LoadMapPage( const char *mapName );
virtual void OnTick( void );
virtual const char *GetName( void ) { return PANEL_ARENA_TEAM; }
private:
CTFTeamButton *m_pAutoTeamButton;
CTFTeamButton *m_pSpecTeamButton;
CExLabel *m_pSpecLabel;
#ifdef _X360
CTFFooter *m_pFooter;
#else
CExButton *m_pCancelButton;
#endif
CSCHintIcon *m_pCancelHintIcon;
CSCHintIcon *m_pJoinAutoHintIcon;
CSCHintIcon *m_pJoinSpectatorsHintIcon;
bool m_bRedDisabled;
bool m_bBlueDisabled;
private:
enum { NUM_TEAMS = 3 };
ButtonCode_t m_iTeamMenuKey;
void ActivateSelectIconHint( int focus_group_number );
};
#endif // TF_ARENATEAMMENU_H
+121
View File
@@ -0,0 +1,121 @@
#include "cbase.h"
#include "tf_asyncpanel.h"
#include "econ_controls.h"
static const float k_flRequestInterval = 5.f;
static const float k_flNeverRequestUpdate = -1.f;
CBaseASyncPanel::CBaseASyncPanel( Panel *pParent, const char *pszPanelName )
: EditablePanel( pParent, pszPanelName )
, m_flLastRequestTime( 0.f )
, m_flLastUpdatedTime( 0.f )
, m_bDataInitialized( false )
, m_bSettingsApplied( false )
{
ivgui()->AddTickSignal( GetVPanel(), 1.f );
}
void CBaseASyncPanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_bSettingsApplied = true;
m_flLastUpdatedTime = 0.f; // Force a refresh
}
void CBaseASyncPanel::LoadControlSettings(const char *dialogResourceName, const char *pathID, KeyValues *pPreloadedKeyValues, KeyValues *pConditions )
{
m_vecLoadingPanels.Purge();
m_vecPanelsToShow.Purge();
BaseClass::LoadControlSettings( dialogResourceName, pathID, pPreloadedKeyValues, pConditions );
}
void CBaseASyncPanel::PerformLayout()
{
BaseClass::PerformLayout();
FOR_EACH_VEC( m_vecLoadingPanels, i )
{
m_vecLoadingPanels[ i ]->SetVisible( true );
}
FOR_EACH_VEC( m_vecPanelsToShow, i )
{
m_vecPanelsToShow[ i ]->SetVisible( false );
}
}
void CBaseASyncPanel::OnChildSettingsApplied( KeyValues *pInResourceData, Panel *pChild )
{
const char *pszAsync = pInResourceData->GetString( "asynchandling", NULL );
if ( pszAsync == NULL )
return;
if ( FStrEq( pszAsync, "content" ) )
{
m_vecPanelsToShow[ m_vecPanelsToShow.AddToTail() ].Set( pChild );
}
else if ( FStrEq( pszAsync, "loading" ) )
{
m_vecLoadingPanels[ m_vecLoadingPanels.AddToTail() ].Set( pChild );
}
}
bool CBaseASyncPanel::IsInitialized() const
{
return m_bDataInitialized;
}
void CBaseASyncPanel::PresentDataIfReady()
{
if ( m_bDataInitialized && m_bSettingsApplied )
{
FOR_EACH_VEC( m_vecLoadingPanels, i )
{
m_vecLoadingPanels[ i ]->SetVisible( false );
}
FOR_EACH_VEC( m_vecPanelsToShow, i )
{
m_vecPanelsToShow[ i ]->SetVisible( true );
}
// stop ticking. job is done.
ivgui()->RemoveTickSignal( GetVPanel() );
}
}
//-----------------------------------------------------------------------------
// Purpose: Checks if data is ready. If so, mark the time and hide the loading image
//-----------------------------------------------------------------------------
void CBaseASyncPanel::CheckForData()
{
m_flLastRequestTime = Plat_FloatTime();
if ( CheckForData_Internal() )
{
m_flLastUpdatedTime = Plat_FloatTime();
m_bDataInitialized = true;
PresentDataIfReady();
}
}
//-----------------------------------------------------------------------------
// Purpose: Check if we need to check for data
//-----------------------------------------------------------------------------
void CBaseASyncPanel::OnTick()
{
const float flTimeSinceUpdate = Plat_FloatTime() - m_flLastUpdatedTime;
const float flTimeSinceRequest = Plat_FloatTime() - m_flLastRequestTime;
// Need an update if we're beyodn the refresh delay, and our refresh delay isn't k_flNeverRequestUpdate, or if we're just not initialized
const bool bNeedsUpdate = ( ( flTimeSinceUpdate > m_flRefreshDelay ) && ( m_flRefreshDelay != k_flNeverRequestUpdate ) ) || m_flLastUpdatedTime == 0.f;
if ( m_bSettingsApplied && bNeedsUpdate && flTimeSinceRequest > k_flRequestInterval )
{
CheckForData();
}
}
+40
View File
@@ -0,0 +1,40 @@
#ifndef TF_ASYNCPANEL
#define TF_ASYNCPANEL
#include "vgui_controls/EditablePanel.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CBaseASyncPanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CBaseASyncPanel, EditablePanel );
public:
CBaseASyncPanel( Panel *pParent, const char *pszPanelName );
virtual ~CBaseASyncPanel() {}
bool IsInitialized() const;
void CheckForData();
virtual void OnTick() OVERRIDE;
virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE;
virtual void PerformLayout() OVERRIDE;
virtual void LoadControlSettings(const char *dialogResourceName, const char *pathID = NULL, KeyValues *pPreloadedKeyValues = NULL, KeyValues *pConditions = NULL) OVERRIDE;
protected:
virtual void OnChildSettingsApplied( KeyValues *pInResourceData, Panel *pChild ) OVERRIDE;
private:
void PresentDataIfReady();
virtual bool CheckForData_Internal() = 0;
bool m_bDataInitialized;
bool m_bSettingsApplied;
float m_flLastRequestTime;
float m_flLastUpdatedTime;
CUtlVector< PHandle > m_vecLoadingPanels;
CUtlVector< PHandle > m_vecPanelsToShow;
CPanelAnimationVar( float, m_flRefreshDelay, "refresh_delay", "-1.f" );
};
#endif //TF_ASYNCPANEL
+49
View File
@@ -0,0 +1,49 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "modelimagepanel.h"
#include "tf_badge_panel.h"
DECLARE_BUILD_FACTORY( CTFBadgePanel );
CTFBadgePanel::CTFBadgePanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
{
m_pBadgePanel = new CModelImagePanel( this, "BadgePanel" );
m_nPrevLevel = 0;
}
void CTFBadgePanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_pBadgePanel->LoadControlSettings( "resource/ui/BadgePanel.res" );
}
void CTFBadgePanel::SetupBadge( const IProgressionDesc* pProgress, const LevelInfo_t& levelInfo )
{
if ( !pProgress )
return;
pProgress->SetupBadgePanel( m_pBadgePanel, levelInfo );
if ( m_nPrevLevel != levelInfo.m_nLevelNum )
{
m_nPrevLevel = levelInfo.m_nLevelNum;
m_pBadgePanel->InvalidateImage();
}
}
void CTFBadgePanel::SetupBadge( const IProgressionDesc* pProgress, const CSteamID& steamID )
{
if ( pProgress && steamID.IsValid() )
{
SetupBadge( pProgress, pProgress->YieldingGetLevelForSteamID( steamID ) );
}
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef TF_BADGE_PANEL_H
#define TF_BADGE_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
#include "tf_match_description.h"
class CTFBadgePanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CTFBadgePanel, vgui::EditablePanel );
public:
CTFBadgePanel( vgui::Panel *pParent, const char *pName );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
void SetupBadge( const IProgressionDesc* pProgress, const LevelInfo_t& levelInfo );
void SetupBadge( const IProgressionDesc* pProgress, const CSteamID& steamID );
private:
class CModelImagePanel *m_pBadgePanel;
uint32 m_nPrevLevel;
};
#endif // TF_BADGE_PANEL_H
File diff suppressed because it is too large Load Diff
+177
View File
@@ -0,0 +1,177 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_CLASSMENU_H
#define TF_CLASSMENU_H
#ifdef _WIN32
#pragma once
#endif
#include <classmenu.h>
#include <vgui_controls/EditablePanel.h>
#include "vgui_controls/KeyRepeat.h"
#include <filesystem.h>
#include <tf_shareddefs.h>
#include "cbase.h"
#include "tf_controls.h"
#include "tf_gamerules.h"
#include "basemodelpanel.h"
#include "IconPanel.h"
#include <vgui_controls/CheckButton.h>
#include "GameEventListener.h"
#include "c_tf_playerresource.h"
#include "tf_playermodelpanel.h"
#include "tf_mann_vs_machine_stats.h"
using namespace vgui;
#define CLASS_COUNT_IMAGES 11
class CTFClassTipsPanel;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CTFClassTipsItemPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CTFClassTipsItemPanel, vgui::EditablePanel );
public:
CTFClassTipsItemPanel( Panel *parent, const char *pszName, int iListItemID );
~CTFClassTipsItemPanel();
void SetClassTip( const wchar_t *pwszText, const char *pszIcon );
virtual void ApplySchemeSettings( IScheme *pScheme );
private:
vgui::ImagePanel *m_pTipIcon;
CExLabel *m_pTipLabel;
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CTFClassMenu : public CClassMenu, public CGameEventListener
{
private:
DECLARE_CLASS_SIMPLE( CTFClassMenu, CClassMenu );
public:
CTFClassMenu( IViewPort *pViewPort );
virtual void Update( void );
virtual Panel *CreateControlByName( const char *controlName );
virtual void OnTick( void );
virtual void PaintBackground( void );
virtual void SetVisible( bool state );
virtual void PerformLayout();
MESSAGE_FUNC_PTR_CHARPTR( OnShowPage, "ShowPage", panel, page );
CON_COMMAND_MEMBER_F( CTFClassMenu, "join_class", Join_Class, "Send a joinclass command", 0 );
virtual void OnCommand( const char *command );
virtual void OnClose();
virtual void ShowPanel( bool bShow );
virtual void UpdateClassCounts( void ){}
void SelectClass( int iClass );
virtual int GetTeamNumber( void ) = 0;
// IGameEventListener interface:
virtual void FireGameEvent( IGameEvent *event );
MESSAGE_FUNC( OnEconUIClosed, "EconUIClosed" ); // If the econ UI was opened (for editing loadout), we'll get notified when the user's done.
virtual GameActionSet_t GetPreferredActionSet() { return GAME_ACTION_SET_IN_GAME_HUD; }
protected:
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void OnKeyCodePressed( KeyCode code );
CExImageButton *GetCurrentClassButton();
virtual void OnKeyCodeReleased( vgui::KeyCode code );
virtual void OnThink();
virtual void UpdateNumClassLabels( int iTeam );
void UpdateButtonSelectionStates( int iClass );
void SetCancelButtonVisible( bool bVisible );
int GetCurrentPlayerClass();
void LoadItems();
void Go();
protected:
CExImageButton *m_pClassButtons[TF_CLASS_MENU_BUTTONS];
vgui::ImagePanel *m_pMvmUpgradeImages[TF_CLASS_MENU_BUTTONS];
CSCHintIcon *m_pClassHintIcons[TF_CLASS_MENU_BUTTONS];
CTFClassTipsPanel *m_pClassTipsPanel;
CTFPlayerModelPanel *m_pTFPlayerModelPanel;
CExButton *m_pEditLoadoutButton;
CExLabel *m_pSelectAClassLabel;
CExplanationPopup *m_pClassHighlightPanel;
CSCHintIcon *m_pEditLoadoutHintIcon;
CSCHintIcon *m_pCancelHintIcon;
private:
void CheckMvMUpgrades();
#ifdef _X360
CTFFooter *m_pFooter;
#endif
ButtonCode_t m_iClassMenuKey;
int m_iCurrentClassIndex;
vgui::CKeyRepeatHandler m_KeyRepeat;
int m_nBaseMusicGuid;
#ifndef _X360
CTFImagePanel *m_ClassCountImages[CLASS_COUNT_IMAGES];
CExLabel *m_pCountLabel;
CTFImagePanel *m_pLocalPlayerImage;
CTFImagePanel *m_pLocalPlayerBG;
int m_iLocalPlayerClass;
#endif
};
//-----------------------------------------------------------------------------
// Purpose: Draws the blue class menu
//-----------------------------------------------------------------------------
class CTFClassMenu_Blue : public CTFClassMenu
{
private:
DECLARE_CLASS_SIMPLE( CTFClassMenu_Blue, CTFClassMenu );
public:
CTFClassMenu_Blue( IViewPort *pViewPort ) : BaseClass( pViewPort ) {}
virtual const char *GetName( void ) { return PANEL_CLASS_BLUE; }
virtual int GetTeamNumber( void ) { return TF_TEAM_BLUE; }
virtual void UpdateClassCounts( void ){ UpdateNumClassLabels( TF_TEAM_BLUE ); }
};
//-----------------------------------------------------------------------------
// Purpose: Draws the red class menu
//-----------------------------------------------------------------------------
class CTFClassMenu_Red : public CTFClassMenu
{
private:
DECLARE_CLASS_SIMPLE( CTFClassMenu_Red, CTFClassMenu );
public:
CTFClassMenu_Red( IViewPort *pViewPort ) : BaseClass( pViewPort ) {}
virtual const char *GetName( void ) { return PANEL_CLASS_RED; }
virtual int GetTeamNumber( void ) { return TF_TEAM_RED; }
virtual void UpdateClassCounts( void ){ UpdateNumClassLabels( TF_TEAM_RED ); }
};
#endif // TF_CLASSMENU_H
File diff suppressed because it is too large Load Diff
+183
View File
@@ -0,0 +1,183 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_SCOREBOARD_H
#define TF_SCOREBOARD_H
#ifdef _WIN32
#pragma once
#endif
#include "hud.h"
#include "hudelement.h"
#include "tf_hud_playerstatus.h"
#include "clientscoreboarddialog.h"
#include "tf_hud_mann_vs_machine_scoreboard.h"
class CAvatarImagePanel;
class CTFBadgePanel;
//class CTFStatsGraph;
//-----------------------------------------------------------------------------
// Purpose: displays the scoreboard
//-----------------------------------------------------------------------------
class CTFClientScoreBoardDialog : public CClientScoreBoardDialog
{
private:
DECLARE_CLASS_SIMPLE( CTFClientScoreBoardDialog, CClientScoreBoardDialog );
public:
CTFClientScoreBoardDialog( IViewPort *pViewPort );
virtual ~CTFClientScoreBoardDialog();
virtual void Reset() OVERRIDE;
virtual void Update() OVERRIDE;
virtual void ShowPanel( bool bShow ) OVERRIDE;
virtual void OnCommand( const char *command ) OVERRIDE;
int HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding );
struct duel_panel_t
{
vgui::EditablePanel *m_pPanel;
CAvatarImagePanel *m_pAvatar;
CExLabel *m_pPlayerNameLabel;
};
MESSAGE_FUNC_PTR( OnItemSelected, "ItemSelected", panel );
MESSAGE_FUNC_PTR( OnItemContextMenu, "ItemContextMenu", panel );
void OnScoreBoardMouseRightRelease( void );
MESSAGE_FUNC_PARAMS( OnReportPlayer, "ReportPlayer", pData );
protected:
virtual void PerformLayout();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PostApplySchemeSettings( vgui::IScheme *pScheme ) {};
vgui::SectionedListPanel *GetPlayerListRed( void ){ return m_pPlayerListRed; }
vgui::SectionedListPanel *GetPlayerListBlue( void ){ return m_pPlayerListBlue; }
private:
void InitPlayerList( vgui::SectionedListPanel *pPlayerList );
void SetPlayerListImages( vgui::SectionedListPanel *pPlayerList );
void UpdateTeamInfo();
void UpdatePlayerList();
void UpdateSpectatorList();
void UpdatePlayerDetails();
void UpdateServerTimeLeft();
void UpdateArenaWaitingToPlayList( void );
void ClearPlayerDetails();
bool ShouldShowAsSpectator( int iPlayerIndex );
bool ShouldShowAsArenaWaitingToPlay( int iPlayerIndex );
void GetCameraUnderlayBounds( int *pX, int *pY, int *pWide, int *pTall );
bool UseMouseMode( void );
void InitializeInputScheme( void );
void AdjustForVisibleScrollbar( void );
void UpdateBadgePanels( CUtlVector<CTFBadgePanel*> &pBadgePanels, vgui::SectionedListPanel *pPlayerList );
virtual void FireGameEvent( IGameEvent *event );
static bool TFPlayerSortFunc( vgui::SectionedListPanel *list, int itemID1, int itemID2 );
vgui::SectionedListPanel *GetSelectedPlayerList( void );
void UpdatePlayerModel();
vgui::SectionedListPanel *m_pPlayerListBlue;
vgui::SectionedListPanel *m_pPlayerListRed;
CExLabel *m_pLabelPlayerName;
CExLabel *m_pLabelDuelOpponentPlayerName;
vgui::ImagePanel *m_pImagePanelHorizLine;
CTFClassImage *m_pClassImage;
vgui::EditablePanel *m_pLocalPlayerStatsPanel;
vgui::EditablePanel *m_pLocalPlayerDuelStatsPanel;
duel_panel_t m_duelPanelLocalPlayer;
duel_panel_t m_duelPanelOpponent;
vgui::Menu *m_pRightClickMenu;
CExLabel *m_pKillsLabel;
CExLabel *m_pDeathsLabel;
CExLabel *m_pAssistLabel;
CExLabel *m_pDestructionLabel;
CExLabel *m_pCapturesLabel;
CExLabel *m_pDefensesLabel;
CExLabel *m_pDominationsLabel;
CExLabel *m_pRevengeLabel;
CExLabel *m_pHealingLabel;
CExLabel *m_pInvulnsLabel;
CExLabel *m_pTeleportsLabel;
CExLabel *m_pHeadshotsLabel;
CExLabel *m_pBackstabsLabel;
CExLabel *m_pBonusLabel;
CExLabel *m_pSupportLabel;
CExLabel *m_pDamageLabel;
CExLabel *m_pServerTimeLeftValue;
vgui::HFont m_pFontTimeLeftNumbers;
vgui::HFont m_pFontTimeLeftString;
CTFHudMannVsMachineScoreboard *m_pMvMScoreboard;
int m_iImageDominated;
int m_iImageDominatedDead;
int m_iImageNemesis;
int m_iImageNemesisDead;
int m_iImageStreak;
int m_iImageStreakDead;
int m_iImageDom[SCOREBOARD_DOMINATION_ICONS];
int m_iImageDomDead[SCOREBOARD_DOMINATION_ICONS];
int m_iImageClass[SCOREBOARD_CLASS_ICONS];
int m_iImageClassAlt[SCOREBOARD_CLASS_ICONS];
int m_iImagePing[SCOREBOARD_PING_ICONS];
int m_iImagePingDead[SCOREBOARD_PING_ICONS];
int m_iTextureCamera;
bool m_bIsPVEMode;
// bool m_bDisplayLevel;
bool m_bMouseActivated;
vgui::HFont m_hScoreFontDefault;
vgui::HFont m_hScoreFontSmallest;
CPanelAnimationVarAliasType( int, m_iSpacerWidth, "spacer", "5", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iNemesisWidth, "nemesis_width", "20", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iMedalWidth, "medal_width", "15", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iKillstreakWidth, "killstreak_width", "20", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iKillstreakImageWidth, "killstreak_image_width", "20", "proportional_int" );
CTFPlayerModelPanel *m_pPlayerModelPanel;
int m_nPlayerModelPanelIndex;
bool m_bRedScrollBarVisible;
bool m_bBlueScrollBarVisible;
int m_nExtraSpace;
CExLabel *m_pRedTeamName;
CExLabel *m_pBlueTeamName;
CAvatarImagePanel *m_pRedLeaderAvatarImage;
EditablePanel *m_pRedLeaderAvatarBG;
vgui::ImagePanel *m_pRedTeamImage;
CAvatarImagePanel *m_pBlueLeaderAvatarImage;
EditablePanel *m_pBlueLeaderAvatarBG;
vgui::ImagePanel *m_pBlueTeamImage;
CUtlVector< CTFBadgePanel* > m_pBlueBadgePanels;
CUtlVector< CTFBadgePanel* > m_pRedBadgePanels;
CHandle< C_TFPlayer > m_hSelectedPlayer;
bool m_bUsePlayerModel;
};
const wchar_t *GetPointsString( int iPoints );
#endif // TF_SCOREBOARD_H
File diff suppressed because it is too large Load Diff
+308
View File
@@ -0,0 +1,308 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_CONTROLS_H
#define TF_CONTROLS_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/IScheme.h>
#include <vgui/KeyCode.h>
#include <KeyValues.h>
#include <vgui/IVGui.h>
#include <vgui_controls/ScrollBar.h>
#include <vgui_controls/EditablePanel.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/RichText.h>
#include "utlvector.h"
#include "vgui_controls/PHandle.h"
#include <vgui_controls/Tooltip.h>
#include "econ_controls.h"
#include "sc_hinticon.h"
#if defined( TF_CLIENT_DLL )
#include "tf_shareddefs.h"
#include "tf_imagepanel.h"
#endif
#include <vgui_controls/Frame.h>
#include <../common/GameUI/scriptobject.h>
#include <vgui/KeyCode.h>
#include <vgui_controls/Tooltip.h>
#include <vgui_controls/CheckButton.h>
wchar_t* LocalizeNumberWithToken( const char* pszLocToken, int nValue );
//-----------------------------------------------------------------------------
// Purpose: Xbox-specific panel that displays button icons text labels
//-----------------------------------------------------------------------------
class CTFFooter : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CTFFooter, vgui::EditablePanel );
public:
CTFFooter( Panel *parent, const char *panelName );
virtual ~CTFFooter();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *pResourceData );
virtual void Paint( void );
virtual void PaintBackground( void );
void ShowButtonLabel( const char *name, bool show = true );
void AddNewButtonLabel( const char *name, const char *text, const char *icon );
void ClearButtons();
private:
struct FooterButton_t
{
bool bVisible;
char name[MAX_PATH];
wchar_t text[MAX_PATH];
wchar_t icon[3]; // icon can be one or two characters
};
CUtlVector< FooterButton_t* > m_Buttons;
bool m_bPaintBackground; // fill the background?
int m_nButtonGap; // space between buttons
int m_FooterTall; // height of the footer
int m_ButtonOffsetFromTop; // how far below the top the buttons should be drawn
int m_ButtonSeparator; // space between the button icon and text
int m_TextAdjust; // extra adjustment for the text (vertically)...text is centered on the button icon and then this value is applied
bool m_bCenterHorizontal; // center buttons horizontally?
int m_ButtonPinRight; // if not centered, this is the distance from the right margin that we use to start drawing buttons (right to left)
char m_szTextFont[64]; // font for the button text
char m_szButtonFont[64]; // font for the button icon
char m_szFGColor[64]; // foreground color (text)
char m_szBGColor[64]; // background color (fill color)
vgui::HFont m_hButtonFont;
vgui::HFont m_hTextFont;
};
//-----------------------------------------------------------------------------
// Purpose: Tooltip for the main menu. Isn't a panel, it just wraps the
// show/hide/position handling for the embedded panel.
//-----------------------------------------------------------------------------
class CMainMenuToolTip : public vgui::BaseTooltip
{
DECLARE_CLASS_SIMPLE( CMainMenuToolTip, vgui::BaseTooltip );
public:
CMainMenuToolTip(vgui::Panel *parent, const char *text = NULL) : vgui::BaseTooltip( parent, text )
{
m_pEmbeddedPanel = NULL;
}
virtual ~CMainMenuToolTip() {}
virtual void SetText(const char *text);
const char *GetText() { return NULL; }
virtual void HideTooltip();
virtual void PerformLayout();
void SetEmbeddedPanel( vgui::EditablePanel *pPanel )
{
m_pEmbeddedPanel = pPanel;
}
protected:
vgui::EditablePanel *m_pEmbeddedPanel;
};
//-----------------------------------------------------------------------------
// Purpose: Simple TF-styled text tooltip
//-----------------------------------------------------------------------------
class CTFTextToolTip : public CMainMenuToolTip
{
DECLARE_CLASS_SIMPLE( CTFTextToolTip, CMainMenuToolTip );
public:
CTFTextToolTip(vgui::Panel *parent, const char *text = NULL) : CMainMenuToolTip( parent, text )
{
}
virtual void PerformLayout();
virtual void PositionWindow( vgui::Panel *pTipPanel );
virtual void SetText(const char *text)
{
_isDirty = true;
BaseClass::SetText( text );
}
};
//-----------------------------------------------------------------------------
// Purpose: Displays a TF specific list of options
// This is essentially a TF-styled version of the GameUI Advanced Multiplayer Options Dialog
//-----------------------------------------------------------------------------
class CTFAdvancedOptionsDialog : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CTFAdvancedOptionsDialog, vgui::EditablePanel );
public:
CTFAdvancedOptionsDialog(vgui::Panel *parent);
~CTFAdvancedOptionsDialog();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *pResourceData );
void Deploy( void );
private:
void CreateControls();
void DestroyControls();
void GatherCurrentValues();
void SaveValues();
virtual void OnCommand( const char *command );
virtual void OnClose();
virtual void OnKeyCodeTyped(vgui::KeyCode code);
virtual void OnKeyCodePressed(vgui::KeyCode code);
private:
CInfoDescription *m_pDescription;
mpcontrol_t *m_pList;
vgui::PanelListPanel *m_pListPanel;
CTFTextToolTip *m_pToolTip;
vgui::EditablePanel *m_pToolTipEmbeddedPanel;
CPanelAnimationVarAliasType( int, m_iControlW, "control_w", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iControlH, "control_h", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iSliderW, "slider_w", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iSliderH, "slider_h", "0", "proportional_int" );
};
//-----------------------------------------------------------------------------
// Purpose: Scrollable panel where you can define children within the .res file
//-----------------------------------------------------------------------------
class CExScrollingEditablePanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CExScrollingEditablePanel, vgui::EditablePanel );
public:
CExScrollingEditablePanel( Panel *pParent, const char *pszName );
virtual ~CExScrollingEditablePanel();
virtual void ApplySettings( KeyValues *inResourceData ) OVERRIDE;
virtual void PerformLayout() OVERRIDE;
virtual void OnSizeChanged( int newWide, int newTall ) OVERRIDE;
MESSAGE_FUNC( OnScrollBarSliderMoved, "ScrollBarSliderMoved" );
virtual void OnMouseWheeled( int delta ) OVERRIDE; // respond to mouse wheel events
void ResetScrollAmount() { m_nLastScrollValue = 0; m_pScrollBar->SetValue(0); }
protected:
void ShiftChildren( int nDistance );
vgui::ScrollBar *m_pScrollBar;
int m_nLastScrollValue;
bool m_bUseMouseWheelToScroll;
CPanelAnimationVarAliasType( int, m_iScrollStep, "scroll_step", "10", "proportional_xpos" );
CPanelAnimationVarAliasType( int, m_iBottomBuffer, "bottom_buffer", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_bRestrictWidth, "restrict_width", "1", "proportional_int" );
};
//-----------------------------------------------------------------------------
// An extension of CExScrollingEditablePanel where panels can be added to form
// a list.
//-----------------------------------------------------------------------------
class CScrollableList : public CExScrollingEditablePanel
{
DECLARE_CLASS_SIMPLE( CScrollableList, CExScrollingEditablePanel );
public:
CScrollableList( Panel* pParent, const char* pszName )
: CExScrollingEditablePanel( pParent, pszName )
{}
virtual ~CScrollableList();
virtual void PerformLayout() OVERRIDE;
void AddPanel( Panel* pPanel, int nGap );
void ClearAutoLayoutPanels();
private:
struct LayoutInfo_t
{
Panel* m_pPanel;
int m_nGap;
};
CUtlVector< LayoutInfo_t > m_vecAutoLayoutPanels;
};
//-----------------------------------------------------------------------------
// A checkbox where keyvalue data can be stored and retrieved (typically in OnCheckButtonChecked)
// so that you don't need a pointer to the checkbox in order to determine WHICH
// checkbox got checked.
//-----------------------------------------------------------------------------
class CExCheckButton : public vgui::CheckButton
{
DECLARE_CLASS_SIMPLE( CExCheckButton, vgui::CheckButton );
public:
CExCheckButton( Panel* pParent, const char* pszName )
: BaseClass( pParent, pszName, NULL )
, m_pKVData( NULL )
{}
virtual ~CExCheckButton()
{
if ( m_pKVData )
m_pKVData->deleteThis();
}
void SetData( KeyValues* pKVData )
{
if ( m_pKVData )
{
m_pKVData->deleteThis();
m_pKVData = NULL;
}
m_pKVData = pKVData;
}
KeyValues* GetData() const
{
return m_pKVData;
}
private:
KeyValues *m_pKVData;
};
class CExpandablePanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CExpandablePanel, vgui::EditablePanel );
public:
CExpandablePanel( Panel* pParent, const char* pszName );
virtual void OnCommand( const char *command ) OVERRIDE;
virtual void OnThink() OVERRIDE;
virtual void OnToggleCollapse( bool bIsExpanded ) {}
void SetCollapsed( bool bCollapsed );
void ToggleCollapse();
bool BIsExpanded() const { return m_bExpanded; }
void SetExpandedHeight( int nNewHeight );
float GetPercentAnimated() const;
protected:
CPanelAnimationVarAliasType( float, m_flResizeTime, "resize_time", "0.4", "float" );
CPanelAnimationVarAliasType( int, m_nCollapsedHeight, "collapsed_height", "17", "proportional_int" );
CPanelAnimationVarAliasType( int, m_nExpandedHeight, "expanded_height", "50", "proportional_int" );
private:
bool m_bExpanded;
float m_flAnimEndTime;
};
#endif // TF_CONTROLS_H
@@ -0,0 +1,447 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "vgui/IInput.h"
#include <vgui/IVGui.h>
#include <vgui/IScheme.h>
#include "tf_giveawayitempanel.h"
#include "iclientmode.h"
#include "baseviewport.h"
#include "econ_entity.h"
#include "c_tf_player.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 "achievementmgr.h"
#include "fmtstr.h"
#include "c_tf_playerresource.h"
#include "tf_gamerules.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CGiveawayPlayerPanel::CGiveawayPlayerPanel( vgui::Panel *parent, const char *name ) : BaseClass(parent,name)
{
m_pNameLabel = new vgui::Label( this, "name_label", "" );
m_pScoreLabel = new vgui::Label( this, "score_label", "" );
REGISTER_COLOR_AS_OVERRIDABLE( m_PlayerColorLocal, "fgcolor_local" );
REGISTER_COLOR_AS_OVERRIDABLE( m_PlayerColorOther, "fgcolor_other" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGiveawayPlayerPanel::PerformLayout( void )
{
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGiveawayPlayerPanel::SetPlayer( CTFPlayer *pPlayer )
{
m_iBonus = 0;
if ( pPlayer )
{
SetVisible( true );
if ( g_TF_PR )
{
int playerIndex = pPlayer->entindex();
const char *pszName = g_TF_PR->GetPlayerName( playerIndex );
m_iBonus = pPlayer->m_Shared.GetItemFindBonus();
SetDialogVariable( "playername", pszName );
SetDialogVariable( "playerscore", m_iBonus );
}
m_iPlayerIndex = pPlayer->entindex();
if ( pPlayer->IsLocalPlayer() )
{
m_pNameLabel->SetFgColor( m_PlayerColorLocal );
m_pScoreLabel->SetFgColor( m_PlayerColorLocal );
}
else
{
m_pNameLabel->SetFgColor( m_PlayerColorOther );
m_pScoreLabel->SetFgColor( m_PlayerColorOther );
}
}
else
{
SetVisible( false );
m_iPlayerIndex = 0;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGiveawayPlayerPanel::SpinBonus( void )
{
SetDialogVariable( "playerscore", RandomInt( PLAYER_ROLL_MIN, PLAYER_ROLL_MAX ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGiveawayPlayerPanel::LockBonus( int iRoll )
{
m_iRoll = iRoll;
SetDialogVariable( "playerscore", m_iBonus + m_iRoll );
}
//===========================================================================================================================
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFGiveawayItemPanel::CTFGiveawayItemPanel( IViewPort *pViewPort ) : Frame( NULL, PANEL_GIVEAWAY_ITEM )
{
m_pViewPort = pViewPort;
// load the new scheme early!!
SetScheme( "ClientScheme" );
SetTitleBarVisible( false );
SetMinimizeButtonVisible( false );
SetMaximizeButtonVisible( false );
SetCloseButtonVisible( false );
SetSizeable( false );
SetMoveable( false );
SetProportional( true );
SetVisible( false );
SetKeyBoardInputEnabled( true );
SetMouseInputEnabled( true );
m_pModelPanel = new CItemModelPanel( this, "item_panel" );
m_pPlayerListPanelKVs = NULL;
m_iNumActivePlayers = 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFGiveawayItemPanel::~CTFGiveawayItemPanel( void )
{
if ( m_pPlayerListPanelKVs )
{
m_pPlayerListPanelKVs->deleteThis();
m_pPlayerListPanelKVs = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGiveawayItemPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "Resource/UI/GiveawayItemPanel.res" );
for ( int i = 0; i < m_aPlayerList.Count(); i++ )
{
m_aPlayerList[i]->ApplySettings( m_pPlayerListPanelKVs );
m_aPlayerList[i]->SetBorder( pScheme->GetBorder("EconItemBorder") );
m_aPlayerList[i]->InvalidateLayout();
}
m_pModelPanel->SetNoItemText( "#Item_Giveaway_NoItem" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGiveawayItemPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
KeyValues *pItemKV = inResourceData->FindKey( "playerlist_panel_kvs" );
if ( pItemKV )
{
if ( m_pPlayerListPanelKVs )
{
m_pPlayerListPanelKVs->deleteThis();
}
m_pPlayerListPanelKVs = new KeyValues("playerlist_panel_kvs");
pItemKV->CopySubkeys( m_pPlayerListPanelKVs );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGiveawayItemPanel::PerformLayout( void )
{
BaseClass::PerformLayout();
int iPosition = 0;
for ( int i = 0; i < m_aPlayerList.Count(); i++ )
{
if ( !m_aPlayerList[i]->IsVisible() )
continue;
int iCenter = GetWide() * 0.5;
int iXPos = iCenter;
int iYPos = 0;
if ( iPosition < (m_iNumActivePlayers * 0.5) )
{
iXPos -= m_aPlayerList[i]->GetWide() + m_iPlayerXOffset;
iYPos = m_iPlayerYPos + iPosition * m_aPlayerList[i]->GetTall();
}
else
{
iXPos += m_iPlayerXOffset;
iYPos = m_iPlayerYPos + (iPosition - ceil(m_iNumActivePlayers * 0.5)) * m_aPlayerList[i]->GetTall();
}
m_aPlayerList[i]->SetPos( iXPos, iYPos );
iPosition++;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGiveawayItemPanel::ShowPanel(bool bShow)
{
if ( bShow )
{
SetItem( NULL );
m_bBuiltPlayerList = false;
m_flNextRollStart = 0;
m_iRollingForPlayer = 0;
m_iNumActivePlayers = 0;
}
SetMouseInputEnabled( bShow );
SetVisible( bShow );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGiveawayItemPanel::FireGameEvent( IGameEvent *event )
{
const char * type = event->GetName();
if ( Q_strcmp(type, "gameui_hidden") == 0 )
{
ShowPanel( false );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGiveawayItemPanel::OnCommand( const char *command )
{
if ( !Q_stricmp( command, "vguicancel" ) )
{
ShowPanel( false );
// If we're connected to a game server, we also close the game UI.
if ( engine->IsInGame() )
{
engine->ClientCmd_Unrestricted( "gameui_hide" );
}
}
else
{
engine->ClientCmd( const_cast<char *>( command ) );
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGiveawayItemPanel::Update( void )
{
// First, wait for the player list to get built
if ( !m_bBuiltPlayerList )
{
BuildPlayerList();
if ( !m_bBuiltPlayerList )
return;
}
// Then wait for the server to send us the item details
if ( !m_pModelPanel->HasItem() )
{
if ( TFGameRules() )
{
CBonusRoundLogic *pLogic = TFGameRules()->GetBonusLogic();
if ( pLogic )
{
m_pModelPanel->SetItem( pLogic->GetBonusItem() );
}
}
if ( !m_pModelPanel->HasItem() )
return;
}
// Then start rolling through the players and locking in their bonuses
if ( m_iRollingForPlayer < m_iNumActivePlayers )
{
// Spin all the numbers & lock them in one by one
for ( int i = 0; i < m_aPlayerList.Count(); i++ )
{
if ( m_iRollingForPlayer < i )
{
// Haven't got to this player yet, so spin their bonus.
m_aPlayerList[i]->SpinBonus();
continue;
}
if ( i == m_iRollingForPlayer )
{
if ( gpGlobals->curtime > m_flNextRollStart )
{
// Lock in this player's bonus and move on to the next one
CBonusRoundLogic *pLogic = TFGameRules()->GetBonusLogic();
if ( pLogic )
{
m_aPlayerList[i]->LockBonus( pLogic->GetPlayerBonusRoll( m_aPlayerList[i]->GetPlayerIndex() ) );
}
m_iRollingForPlayer++;
m_flNextRollStart = gpGlobals->curtime + 0.4;
}
else
{
m_aPlayerList[i]->SpinBonus();
}
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGiveawayItemPanel::BuildPlayerList( void )
{
CBonusRoundLogic *pLogic = TFGameRules()->GetBonusLogic();
if ( !pLogic )
return;
m_bBuiltPlayerList = true;
pLogic->BuildBonusPlayerList();
for ( int i = 0; i < m_aPlayerList.Count(); i++ )
{
m_aPlayerList[i]->SetPlayer(NULL);
}
m_iNumActivePlayers = 0;
for( int playerIndex = 0; playerIndex < pLogic->GetNumBonusPlayers(); playerIndex++ )
{
C_TFPlayer *pPlayer = pLogic->GetBonusPlayer(playerIndex);
if ( !pPlayer )
continue;
CGiveawayPlayerPanel *pPlayerPanel;
if ( m_iNumActivePlayers < m_aPlayerList.Count() )
{
pPlayerPanel = m_aPlayerList[m_iNumActivePlayers];
}
else
{
const char *pszCommand = VarArgs("playerpanel%d",m_iNumActivePlayers);
pPlayerPanel = new CGiveawayPlayerPanel( this, pszCommand );
if ( m_pPlayerListPanelKVs )
{
pPlayerPanel->ApplySettings( m_pPlayerListPanelKVs );
}
pPlayerPanel->MakeReadyForUse();
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
pPlayerPanel->SetBorder( pScheme->GetBorder("EconItemBorder") );
m_aPlayerList.AddToTail( pPlayerPanel );
}
pPlayerPanel->SetPlayer( pPlayer );
m_iNumActivePlayers++;
}
// Start the animation
m_flNextRollStart = gpGlobals->curtime + 1.0;
m_iRollingForPlayer = 0;
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGiveawayItemPanel::SetItem( CEconItemView *pItem )
{
m_pModelPanel->SetItem( pItem );
}
static vgui::DHANDLE<CTFGiveawayItemPanel> g_GiveawayItemPanel;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFGiveawayItemPanel *OpenGiveawayItemPanel( CEconItemView *pItem )
{
CTFGiveawayItemPanel *pPanel = (CTFGiveawayItemPanel*)gViewPortInterface->FindPanelByName( PANEL_GIVEAWAY_ITEM );
if ( pPanel )
{
pPanel->InvalidateLayout( false, true );
pPanel->SetItem( pItem );
gViewPortInterface->ShowPanel( pPanel, true );
}
return pPanel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Test_GiveawayItemPanel( const CCommand &args )
{
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
if ( !pLocalPlayer )
return;
CEconItemView *pScriptCreatedItem = NULL;
bool bAllItems = (args.ArgC() <= 1);
for ( int i = bAllItems ? 0 : clamp( atoi(args[1]), 0, 2 ); i <= 2; i++ )
{
CEconEntity *pItem = dynamic_cast<CEconEntity *>( pLocalPlayer->Weapon_GetWeaponByType( i ) );
if ( !pItem )
continue;
pScriptCreatedItem = pItem->GetAttributeContainer()->GetItem();
break;
}
if ( pScriptCreatedItem )
{
OpenGiveawayItemPanel( pScriptCreatedItem );
}
}
ConCommand test_giveawayitem( "test_giveawayitem", Test_GiveawayItemPanel, "Debugging tool to test the item giveaway panel. Usage: test_giveawayitem <weapon name>\n <weapon id>: 0 = primary, 1 = secondary, 2 = melee.", FCVAR_CHEAT );
+108
View File
@@ -0,0 +1,108 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_GIVEAWAYITEMPANEL_H
#define TF_GIVEAWAYITEMPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Panel.h>
#include <vgui_controls/Frame.h>
#include <game/client/iviewport.h>
#include "GameEventListener.h"
#include "basemodel_panel.h"
#include "basemodelpanel.h"
#include "tf_shareddefs.h"
#include "econ_item_inventory.h"
#include "econ_item_view.h"
#include "item_model_panel.h"
#include "c_tf_player.h"
class CEconItemView;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CGiveawayPlayerPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CGiveawayPlayerPanel, vgui::EditablePanel );
public:
CGiveawayPlayerPanel( vgui::Panel *parent, const char *name );
virtual void PerformLayout( void );
void SetPlayer( CTFPlayer *pPlayer );
int GetPlayerIndex( void ) { return m_iPlayerIndex; }
int GetBonus( void ) { return m_iBonus; }
void SpinBonus( void );
void LockBonus( int iRoll );
private:
vgui::Label *m_pNameLabel;
vgui::Label *m_pScoreLabel;
Color m_PlayerColorLocal;
Color m_PlayerColorOther;
int m_iBonus;
int m_iRoll;
int m_iPlayerIndex;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTFGiveawayItemPanel : public vgui::Frame, public IViewPortPanel, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CTFGiveawayItemPanel, vgui::Frame );
public:
CTFGiveawayItemPanel( IViewPort *pViewPort );
~CTFGiveawayItemPanel( void );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void PerformLayout( void );
virtual void OnCommand( const char *command );
virtual void FireGameEvent( IGameEvent *event );
void SetItem( CEconItemView *pItem );
void BuildPlayerList( void );
// IViewPortPanel overrides
virtual const char *GetName( void ){ return PANEL_GIVEAWAY_ITEM; }
virtual void SetData( KeyValues *data ) { return; }
virtual void Reset(){ Update(); }
virtual void Update();
virtual void ShowPanel( bool bShow );
virtual bool NeedsUpdate( void ){ return true; }
virtual bool HasInputElements( void ){ return true; }
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
vgui::VPANEL GetVPanel( void ){ return BaseClass::GetVPanel(); }
virtual bool IsVisible(){ return BaseClass::IsVisible(); }
virtual void SetParent( vgui::VPANEL parent ){ BaseClass::SetParent( parent ); }
virtual GameActionSet_t GetPreferredActionSet() { return GAME_ACTION_SET_MENUCONTROLS; }
private:
IViewPort *m_pViewPort;
CItemModelPanel *m_pModelPanel;
CUtlVector< CGiveawayPlayerPanel * > m_aPlayerList;
KeyValues *m_pPlayerListPanelKVs;
int m_iNumActivePlayers;
// Animation
bool m_bBuiltPlayerList;
float m_flNextRollStart;
int m_iRollingForPlayer;
CPanelAnimationVarAliasType( int, m_iPlayerYPos, "player_ypos", "0", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iPlayerXOffset, "player_xoffset", "0", "proportional_int" );
};
CTFGiveawayItemPanel *OpenGiveawayItemPanel( CEconItemView *pItem );
#endif // TF_GIVEAWAYITEMPANEL_H
+87
View File
@@ -0,0 +1,87 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include <KeyValues.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <vgui/ISystem.h>
#include <vgui_controls/AnimationController.h>
#include <vgui_controls/EditablePanel.h>
#include <vgui/ISurface.h>
#include <vgui/IImage.h>
#include <vgui_controls/Label.h>
#include "tf_imagepanel.h"
#include "c_tf_player.h"
using namespace vgui;
DECLARE_BUILD_FACTORY( CTFImagePanel );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFImagePanel::CTFImagePanel( Panel *parent, const char *name ) : ScalableImagePanel( parent, name )
{
for ( int i = 0; i < TF_TEAM_COUNT; i++ )
{
m_szTeamBG[i][0] = '\0';
}
C_TFPlayer *pPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() );
m_iBGTeam = pPlayer ? pPlayer->GetTeamNumber() : TEAM_UNASSIGNED;
ListenForGameEvent( "localplayer_changeteam" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFImagePanel::ApplySettings( KeyValues *inResourceData )
{
for ( int i = 0; i < TF_TEAM_COUNT; i++ )
{
Q_strncpy( m_szTeamBG[i], inResourceData->GetString( VarArgs("teambg_%d", i), "" ), sizeof( m_szTeamBG[i] ) );
if ( m_szTeamBG[i] && m_szTeamBG[i][0] )
{
PrecacheMaterial( VarArgs( "vgui/%s", m_szTeamBG[i] ) );
}
}
BaseClass::ApplySettings( inResourceData );
UpdateBGImage();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFImagePanel::UpdateBGImage( void )
{
if ( m_iBGTeam >= 0 && m_iBGTeam < TF_TEAM_COUNT )
{
if ( m_szTeamBG[m_iBGTeam] && m_szTeamBG[m_iBGTeam][0] )
{
SetImage( m_szTeamBG[m_iBGTeam] );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFImagePanel::FireGameEvent( IGameEvent * event )
{
if ( FStrEq( "localplayer_changeteam", event->GetName() ) )
{
C_TFPlayer *pPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() );
m_iBGTeam = pPlayer ? pPlayer->GetTeamNumber() : TEAM_UNASSIGNED;
UpdateBGImage();
}
}
+41
View File
@@ -0,0 +1,41 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_IMAGEPANEL_H
#define TF_IMAGEPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_shareddefs.h"
#include <vgui/IScheme.h>
#include <vgui_controls/ScalableImagePanel.h>
#include "GameEventListener.h"
#define MAX_BG_LENGTH 128
class CTFImagePanel : public vgui::ScalableImagePanel, public CGameEventListener
{
public:
DECLARE_CLASS_SIMPLE( CTFImagePanel, vgui::ScalableImagePanel );
CTFImagePanel( vgui::Panel *parent, const char *name );
virtual void ApplySettings( KeyValues *inResourceData );
void UpdateBGImage( void );
void SetBGTeam( int iTeam ) { m_iBGTeam = iTeam; }
public: // IGameEventListener Interface
virtual void FireGameEvent( IGameEvent * event );
public:
char m_szTeamBG[TF_TEAM_COUNT][MAX_BG_LENGTH];
int m_iBGTeam;
};
#endif // TF_IMAGEPANEL_H
+703
View File
@@ -0,0 +1,703 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include <KeyValues.h>
#include <vgui/IVGui.h>
#include <vgui/ISurface.h>
#include <filesystem.h>
#include <vgui_controls/AnimationController.h>
#include "iclientmode.h"
#include "clientmode_shared.h"
#include "shareddefs.h"
#include "tf_shareddefs.h"
#include "tf_controls.h"
#include "tf_gamerules.h"
#ifdef WIN32
#include "winerror.h"
#endif
#include "ixboxsystem.h"
#include "intromenu.h"
#include "tf_intromenu.h"
#include "inputsystem/iinputsystem.h"
// used to determine the action the intro menu should take when OnTick handles a think for us
enum
{
INTRO_NONE,
INTRO_STARTVIDEO,
INTRO_BACK,
INTRO_CONTINUE,
};
using namespace vgui;
// sort function for the list of captions that we're going to show
int CaptionsSort( CVideoCaption* const *p1, CVideoCaption* const *p2 )
{
// check the start time
if ( (*p2)->m_flStartTime < (*p1)->m_flStartTime )
{
return 1;
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CTFIntroMenu::CTFIntroMenu( IViewPort *pViewPort ) : BaseClass( pViewPort )
{
m_pVideo = new CTFVideoPanel( this, "VideoPanel" );
m_pModel = new CModelPanel( this, "MenuBG" );
m_pCaptionLabel = new CExLabel( this, "VideoCaption", "" );
#ifdef _X360
m_pFooter = new CTFFooter( this, "Footer" );
#else
m_pBack = new CExButton( this, "Back", "" );
m_pOK = new CExButton( this, "Skip", "" );
m_pReplayVideo = new CExButton( this, "ReplayVideo", "" );
m_pContinue = new CExButton( this, "Continue", "" );
#endif
m_iCurrentCaption = 0;
m_flVideoStartTime = 0;
m_flActionThink = -1;
m_iAction = INTRO_NONE;
//=============================================================================
// HPE_BEGIN
// [msmith] Flag for weather or not we're playing an in game video.
//=============================================================================
m_bPlayingInGameVideo = false;
//=============================================================================
// HPE_END
//=============================================================================
vgui::ivgui()->AddTickSignal( GetVPanel() );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CTFIntroMenu::~CTFIntroMenu()
{
m_Captions.PurgeAndDeleteElements();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
if ( ::input->IsSteamControllerActive() )
{
LoadControlSettings( "Resource/UI/IntroMenu_SC.res" );
SetMouseInputEnabled( false );
}
else
{
LoadControlSettings( "Resource/UI/IntroMenu.res" );
SetMouseInputEnabled( true );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::SetNextThink( float flActionThink, int iAction )
{
m_flActionThink = flActionThink;
m_iAction = iAction;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::OnTick()
{
// @note Tom Bui: (yuck)
// in training, never show the back button
// we do this late, because there's a race condition for when IsInTraining() will return true
if ( m_pBack->IsVisible() && TFGameRules() && TFGameRules()->IsInTraining() )
{
m_pBack->SetVisible(false);
}
//=============================================================================
// HPE_BEGIN
// [msmith] Used to play a movie during a map. For training videos.
//=============================================================================
if ( PendingInGameVideo() && !BaseClass::IsVisible() )
{
m_pViewPort->ShowPanel( this, true );
}
//=============================================================================
// HPE_END
//=============================================================================
// do we have anything special to do?
else if ( m_flActionThink > 0 && m_flActionThink < gpGlobals->curtime )
{
if ( m_iAction == INTRO_STARTVIDEO )
{
//=============================================================================
// HPE_BEGIN
// [msmith] Pulled start video into a separate function.
//=============================================================================
StartVideo();
//=============================================================================
// HPE_END
//=============================================================================
}
else if ( m_iAction == INTRO_BACK )
{
m_pViewPort->ShowPanel( this, false );
m_pViewPort->ShowPanel( PANEL_MAPINFO, true );
}
else if ( m_iAction == INTRO_CONTINUE )
{
m_pViewPort->ShowPanel( this, false );
//=============================================================================
// HPE_BEGIN
// [msmith] Used for the client to tell the server that we're whatching a movie or not
//=============================================================================
tf_training_client_message.SetValue( "" );
tf_training_client_message.SetValue( TRAINING_CLIENT_MESSAGE_NONE );
//=============================================================================
// HPE_END
//=============================================================================
if ( GetLocalPlayerTeam() == TEAM_UNASSIGNED )
{
if ( TFGameRules()->IsInArenaMode() == true && tf_arena_use_queue.GetBool() == true )
{
m_pViewPort->ShowPanel( PANEL_ARENA_TEAM, true );
}
else if ( TFGameRules()->IsMannVsMachineMode() || TFGameRules()->IsCompetitiveMode() )
{
engine->ClientCmd( "autoteam" );
}
else
{
m_pViewPort->ShowPanel( PANEL_TEAM, true );
}
}
else
{
C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
// only open the class menu if they're not on team Spectator and they haven't already picked a class
if ( pPlayer &&
( GetLocalPlayerTeam() != TEAM_SPECTATOR ) &&
( pPlayer->GetPlayerClass()->GetClassIndex() == TF_CLASS_UNDEFINED ) )
{
if ( tf_arena_force_class.GetBool() == false )
{
switch( GetLocalPlayerTeam() )
{
case TF_TEAM_RED:
m_pViewPort->ShowPanel( PANEL_CLASS_RED, true );
break;
case TF_TEAM_BLUE:
m_pViewPort->ShowPanel( PANEL_CLASS_BLUE, true );
break;
}
}
}
}
}
// reset our think
SetNextThink( -1, INTRO_NONE );
}
// check if we need to update our captions
if ( m_pCaptionLabel && m_pCaptionLabel->IsVisible() )
{
UpdateCaptions();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::OnThink()
{
//Always hide the health... this needs to be done every frame because a message from the server keeps resetting this.
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( pLocalPlayer )
{
pLocalPlayer->m_Local.m_iHideHUD |= HIDEHUD_HEALTH;
}
BaseClass::OnThink();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CTFIntroMenu::LoadCaptions( void )
{
bool bSuccess = false;
// clear any current captions
m_Captions.PurgeAndDeleteElements();
m_iCurrentCaption = 0;
if ( m_pCaptionLabel )
{
const char *szVideoFileName = GetVideoFileName( false );
KeyValues *kvCaptions = NULL;
char strFullpath[MAX_PATH];
if ( szVideoFileName != NULL )
{
//=============================================================================
// HPE_BEGIN
// [msmith] The video may now be either a map video or an in game video.
// Made a function to decide which video name to give back.
//=============================================================================
Q_strncpy( strFullpath, szVideoFileName, MAX_PATH ); // Assume we must play out of the media directory
//=============================================================================
// HPE_END
//=============================================================================
Q_strncat( strFullpath, ".res", MAX_PATH ); // Assume we're a .res extension type
if ( g_pFullFileSystem->FileExists( strFullpath ) )
{
kvCaptions = new KeyValues( strFullpath );
if ( kvCaptions )
{
if ( kvCaptions->LoadFromFile( g_pFullFileSystem, strFullpath ) )
{
for ( KeyValues *pData = kvCaptions->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
{
CVideoCaption *pCaption = new CVideoCaption;
if ( pCaption )
{
pCaption->m_pszString = ReadAndAllocStringValue( pData, "string" );
pCaption->m_flStartTime = pData->GetFloat( "start", 0.0 );
pCaption->m_flDisplayTime = pData->GetFloat( "length", 3.0 );
m_Captions.AddToTail( pCaption );
// we have at least one caption to show
bSuccess = true;
}
}
}
kvCaptions->deleteThis();
}
}
}
}
if ( bSuccess )
{
// sort the captions so we show them in the correct order (they're not necessarily in order in the .res file)
m_Captions.Sort( CaptionsSort );
}
return bSuccess;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::UpdateCaptions( void )
{
//=============================================================================
// HPE_BEGIN
// [msmith] Timing should be realtime when playing in game becase the curtime is paused.
//=============================================================================
float testTime = m_bPlayingInGameVideo ? gpGlobals->realtime : gpGlobals->curtime;
//=============================================================================
// HPE_END
//=============================================================================
if ( m_pCaptionLabel && m_pCaptionLabel->IsVisible() && ( m_Captions.Count() > 0 ) )
{
CVideoCaption *pCaption = m_Captions[m_iCurrentCaption];
if ( pCaption )
{
if ( ( pCaption->m_flCaptionStart >= 0 ) && ( pCaption->m_flCaptionStart + pCaption->m_flDisplayTime < testTime ) )
{
// fade out the caption
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "VideoCaptionFadeOut" );
// move to the next caption
m_iCurrentCaption++;
if ( !m_Captions.IsValidIndex( m_iCurrentCaption ) )
{
// we're done showing captions
m_pCaptionLabel->SetVisible( false );
}
}
// is it time to show the caption?
else if ( m_flVideoStartTime + pCaption->m_flStartTime < testTime )
{
// have we already started this video?
if ( pCaption->m_flCaptionStart < 0 )
{
m_pCaptionLabel->SetText( pCaption->m_pszString );
pCaption->m_flCaptionStart = testTime;
// fade in the next caption
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "VideoCaptionFadeIn" );
}
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::ShowPanel( bool bShow )
{
//=============================================================================
// HPE_BEGIN:
// [msmith] Don't show the back button when in training. You can only skip intro
// movies.
//=============================================================================
m_pBack->SetVisible(true);
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
m_pBack->SetVisible( false );
if ( PendingInGameVideo() == false )
{
VideoSystem_t playbackSystem = VideoSystem::NONE;
char resolvedFile[MAX_PATH];
if ( g_pVideo != NULL && g_pVideo->LocatePlayableVideoFile( GetVideoFileName(), "GAME", &playbackSystem, resolvedFile, sizeof(resolvedFile) ) != VideoResult::SUCCESS )
{
//If we have no movie, no need to show the intro screen on a training mission.
bShow = false;
}
}
}
//=============================================================================
// HPE_END
//=============================================================================
if ( BaseClass::IsVisible() == bShow )
return;
// reset our think
SetNextThink( -1, INTRO_NONE );
if ( bShow )
{
InvalidateLayout( true, true );
Activate();
if ( m_pVideo )
{
//=============================================================================
// HPE_BEGIN
// [msmith] Pulled shutting down the video into a separate function.
// If we're showing an in game video, we need to enable pausing so that
// we can pause the game during the video.
// If we're showing an intro training movie, we also need to tell the server that
// we're whatching the intro movie so that the round does not start until it's over.
// If we are watching an in game video, we do NOT send a message for that because
// tf_training_client_message will contain the name of the video we're watching.
//=============================================================================
ShutdownVideo();
SetNextThink( gpGlobals->curtime + m_pVideo->GetStartDelay(), INTRO_STARTVIDEO );
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
if ( PendingInGameVideo() )
{
engine->ClientCmd( "sv_pausable 1" );
}
else
{
tf_training_client_message.SetValue( TRAINING_CLIENT_MESSAGE_WATCHING_INTRO_MOVIE );
}
}
//=============================================================================
// HPE_END
//=============================================================================
}
if ( m_pModel )
{
m_pModel->SetPanelDirty();
}
}
else
{
Shutdown();
SetVisible( false );
//=============================================================================
// HPE_BEGIN
// [msmith] We must disable the ability to pause. If we don't, it looks like
// some other function in TF2 causes the entire game to pause if sv_pausable is enabled.
//=============================================================================
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
engine->ClientCmd( "sv_pausable 0" );
}
//=============================================================================
// HPE_END
//=============================================================================
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::OnIntroFinished( void )
{
// in training we want to give the user the ability to replay the movie
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
m_pReplayVideo->SetVisible( true );
m_pContinue->SetVisible( true );
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "IntroMovieContinueBlink" );
m_pOK->SetVisible( false );
}
else
{
float flTime = gpGlobals->curtime;
if ( m_pModel && m_pModel->SetSequence( "UpSlow" ) )
{
// wait for the model sequence to finish before going to the next menu
flTime = gpGlobals->curtime + m_pVideo->GetEndDelay();
}
Shutdown();
SetNextThink( flTime, INTRO_CONTINUE );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::OnCommand( const char *command )
{
if ( !Q_strcmp( command, "back" ) )
{
float flTime = gpGlobals->curtime;
Shutdown();
// try to play the screenup sequence
if ( m_pModel && m_pModel->SetSequence( "Up" ) )
{
flTime = gpGlobals->curtime + 0.35f;
}
// wait for the model sequence to finish before going back to the mapinfo menu
SetNextThink( flTime, INTRO_BACK );
}
else if ( !Q_strcmp( command, "skip" ) )
{
Shutdown();
// continue right now
SetNextThink( gpGlobals->curtime, INTRO_CONTINUE );
}
else if ( !Q_strcmp( command, "replayVideo" ) )
{
ShutdownVideo();
SetNextThink( gpGlobals->curtime, INTRO_STARTVIDEO );
}
else
{
BaseClass::OnCommand( command );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::OnKeyCodePressed( KeyCode code )
{
if ( code == KEY_XBUTTON_A || code == STEAMCONTROLLER_A )
{
OnCommand( "skip" );
}
else if ( code == KEY_XBUTTON_B || code == STEAMCONTROLLER_B )
{
OnCommand( "back" );
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFIntroMenu::Shutdown( void )
{
//=============================================================================
// HPE_BEGIN
// [msmith] Refactored the shutdown video logic into a containing function.
//=============================================================================
ShutdownVideo();
//=============================================================================
// HPE_END
//=============================================================================
if ( m_pCaptionLabel && m_pCaptionLabel->IsVisible() )
{
m_pCaptionLabel->SetVisible( false );
}
m_iCurrentCaption = 0;
m_flVideoStartTime = 0;
}
//=============================================================================
// HPE_BEGIN
// [msmith] New helper functions
//=============================================================================
void CTFIntroMenu::ShutdownVideo()
{
if ( m_pVideo )
{
m_pVideo->Shutdown(); // make sure we're not currently running
}
//Make sure we unpause the game if it was paused from an in game play of a video.
if ( m_bPlayingInGameVideo )
{
UnpauseGame();
}
m_bPlayingInGameVideo = false;
}
bool CTFIntroMenu::PendingInGameVideo( void )
{
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
//If the message is a string, it's a video name.
return strlen( tf_training_client_message.GetString() ) > 3;
}
return false;
}
const char *CTFIntroMenu::GetVideoFileName( bool withExtension )
{
if ( PendingInGameVideo() )
{
return TFGameRules()->FormatVideoName( tf_training_client_message.GetString(), withExtension );
}
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
ConVarRef training_map_video("training_map_video");
if ( strlen( training_map_video.GetString() ) > 3 )
{
return TFGameRules()->FormatVideoName( training_map_video.GetString(), withExtension );
}
}
return TFGameRules()->GetVideoFileForMap( withExtension );
}
void CTFIntroMenu::StartVideo()
{
m_pOK->SetVisible( true );
m_pReplayVideo->SetVisible( false );
m_pContinue->SetVisible( false );
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "IntroMovieContinueBlinkStop" );
if ( m_pVideo )
{
// turn on the captions if we have them
if ( LoadCaptions() )
{
if ( m_pCaptionLabel && !m_pCaptionLabel->IsVisible() )
{
m_pCaptionLabel->SetText( " " );
m_pCaptionLabel->SetVisible( true );
//Make sure the label is fully faded in when starting to play.
//It could have been faded out from a prior animation event form an animation effect in a previous video instance.
m_pCaptionLabel->SetAlpha( 255 );
}
}
else
{
if ( m_pCaptionLabel && m_pCaptionLabel->IsVisible() )
{
m_pCaptionLabel->SetVisible( false );
}
}
m_pVideo->Activate();
if ( PendingInGameVideo() )
{
m_pVideo->BeginPlayback( GetVideoFileName() );
PauseGame();
m_bPlayingInGameVideo = true;
//Since we have started playing the video, we can reset the message string to empty.
tf_training_client_message.SetValue( "" );
}
else
{
m_pVideo->BeginPlayback( GetVideoFileName() );
}
m_pVideo->MoveToFront();
m_flVideoStartTime = m_bPlayingInGameVideo ? gpGlobals->realtime : gpGlobals->curtime;
}
}
void CTFIntroMenu::UnpauseGame( void )
{
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
engine->ClientCmd( "unpause" );
}
}
void CTFIntroMenu::PauseGame( void )
{
if ( TFGameRules() && TFGameRules()->IsInTraining() )
{
engine->ClientCmd( "pause" );
}
}
//=============================================================================
// HPE_END
//=============================================================================
+128
View File
@@ -0,0 +1,128 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TF_INTROMENU_H
#define TF_INTROMENU_H
#ifdef _WIN32
#pragma once
#endif
#include "tf_vgui_video.h"
#include "basemodelpanel.h"
#define MAX_CAPTION_LENGTH 256
class CVideoCaption
{
public:
CVideoCaption()
{
m_pszString = NULL;
m_flStartTime = 0;
m_flDisplayTime = 0;
m_flCaptionStart = -1;
}
~CVideoCaption()
{
if ( m_pszString && m_pszString[0] )
{
delete [] m_pszString;
m_pszString = NULL;
}
}
const char *m_pszString; // the string to display (can be a localized # string)
float m_flStartTime; // the offset from the beginning of the video when we should show this caption
float m_flDisplayTime; // the length of time the string should be displayed once it's shown
float m_flCaptionStart; // the time when the caption is shown (so we know when to turn it off
};
//-----------------------------------------------------------------------------
// Purpose: displays the Intro menu
//-----------------------------------------------------------------------------
class CTFIntroMenu : public CIntroMenu
{
private:
DECLARE_CLASS_SIMPLE( CTFIntroMenu, CIntroMenu );
public:
CTFIntroMenu( IViewPort *pViewPort );
~CTFIntroMenu();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ShowPanel( bool bShow );
virtual void OnCommand( const char *command );
virtual void OnKeyCodePressed( KeyCode code );
virtual void OnTick() OVERRIDE;
virtual void OnThink() OVERRIDE;
//=============================================================================
// HPE_BEGIN
// [msmith] Some refactoring.
//=============================================================================
void StartVideo();
void ShutdownVideo();
//=============================================================================
// HPE_END
//=============================================================================
MESSAGE_FUNC( OnIntroFinished, "IntroFinished" );
private:
void SetNextThink( float flActionThink, int iAction );
void Shutdown( void );
bool LoadCaptions( void );
void UpdateCaptions( void );
//=============================================================================
// HPE_BEGIN
// [msmith] Added support for in game videos.
//=============================================================================
bool PendingInGameVideo( void );
const char *GetVideoFileName( bool withExtension = true );
void UnpauseGame( void );
void PauseGame( void );
//=============================================================================
// HPE_END
//=============================================================================
CTFVideoPanel *m_pVideo;
CModelPanel *m_pModel;
CExLabel *m_pCaptionLabel;
#ifdef _X360
CTFFooter *m_pFooter;
#else
CExButton *m_pBack;
CExButton *m_pOK;
CExButton *m_pReplayVideo;
CExButton *m_pContinue;
#endif
float m_flActionThink;
int m_iAction;
CUtlVector< CVideoCaption* > m_Captions;
int m_iCurrentCaption;
float m_flVideoStartTime;
//=============================================================================
// HPE_BEGIN
// [msmith] Added support for in game videos.
//=============================================================================
bool m_bPlayingInGameVideo;
//=============================================================================
// HPE_END
//=============================================================================
};
#endif // TF_INTROMENU_H

Some files were not shown because too many files have changed in this diff Show More