1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-19 20:16:10 +08:00

First version of the SOurce SDK 2013

This commit is contained in:
Joe Ludwig
2013-06-26 15:22:04 -07:00
commit e7d6f4c174
3682 changed files with 1624327 additions and 0 deletions

View File

@ -0,0 +1,580 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include <stdio.h>
#include <cdll_client_int.h>
#include <cdll_util.h>
#include <globalvars_base.h>
#include <igameresources.h>
#include "IGameUIFuncs.h" // for key bindings
#include "inputsystem/iinputsystem.h"
#include "clientscoreboarddialog.h"
#include <voice_status.h>
#include <vgui/IScheme.h>
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui/IVGui.h>
#include <vstdlib/IKeyValuesSystem.h>
#include <KeyValues.h>
#include <vgui_controls/ImageList.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/SectionedListPanel.h>
#include <game/client/iviewport.h>
#include <igameresources.h>
#include "vgui_avatarimage.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
bool AvatarIndexLessFunc( const int &lhs, const int &rhs )
{
return lhs < rhs;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CClientScoreBoardDialog::CClientScoreBoardDialog(IViewPort *pViewPort) : EditablePanel( NULL, PANEL_SCOREBOARD )
{
m_iPlayerIndexSymbol = KeyValuesSystem()->GetSymbolForString("playerIndex");
m_nCloseKey = BUTTON_CODE_INVALID;
//memset(s_VoiceImage, 0x0, sizeof( s_VoiceImage ));
TrackerImage = 0;
m_pViewPort = pViewPort;
// initialize dialog
SetProportional(true);
SetKeyBoardInputEnabled(false);
SetMouseInputEnabled(false);
// set the scheme before any child control is created
SetScheme("ClientScheme");
m_pPlayerList = new SectionedListPanel(this, "PlayerList");
m_pPlayerList->SetVerticalScrollbar(false);
LoadControlSettings("Resource/UI/ScoreBoard.res");
m_iDesiredHeight = GetTall();
m_pPlayerList->SetVisible( false ); // hide this until we load the images in applyschemesettings
m_HLTVSpectators = 0;
m_ReplaySpectators = 0;
// update scoreboard instantly if on of these events occure
ListenForGameEvent( "hltv_status" );
ListenForGameEvent( "server_spawn" );
m_pImageList = NULL;
m_mapAvatarsToImageList.SetLessFunc( DefLessFunc( CSteamID ) );
m_mapAvatarsToImageList.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CClientScoreBoardDialog::~CClientScoreBoardDialog()
{
if ( NULL != m_pImageList )
{
delete m_pImageList;
m_pImageList = NULL;
}
}
//-----------------------------------------------------------------------------
// Call every frame
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::OnThink()
{
BaseClass::OnThink();
// NOTE: this is necessary because of the way input works.
// If a key down message is sent to vgui, then it will get the key up message
// Sometimes the scoreboard is activated by other vgui menus,
// sometimes by console commands. In the case where it's activated by
// other vgui menus, we lose the key up message because this panel
// doesn't accept keyboard input. It *can't* accept keyboard input
// because another feature of the dialog is that if it's triggered
// from within the game, you should be able to still run around while
// the scoreboard is up. That feature is impossible if this panel accepts input.
// because if a vgui panel is up that accepts input, it prevents the engine from
// receiving that input. So, I'm stuck with a polling solution.
//
// Close key is set to non-invalid when something other than a keybind
// brings the scoreboard up, and it's set to invalid as soon as the
// dialog becomes hidden.
if ( m_nCloseKey != BUTTON_CODE_INVALID )
{
if ( !g_pInputSystem->IsButtonDown( m_nCloseKey ) )
{
m_nCloseKey = BUTTON_CODE_INVALID;
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, false );
GetClientVoiceMgr()->StopSquelchMode();
}
}
}
//-----------------------------------------------------------------------------
// Called by vgui panels that activate the client scoreboard
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::OnPollHideCode( int code )
{
m_nCloseKey = (ButtonCode_t)code;
}
//-----------------------------------------------------------------------------
// Purpose: clears everything in the scoreboard and all it's state
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::Reset()
{
// clear
m_pPlayerList->DeleteAllItems();
m_pPlayerList->RemoveAllSections();
m_iSectionId = 0;
m_fNextUpdateTime = 0;
// add all the sections
InitScoreboardSections();
}
//-----------------------------------------------------------------------------
// Purpose: adds all the team sections to the scoreboard
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::InitScoreboardSections()
{
}
//-----------------------------------------------------------------------------
// Purpose: sets up screen
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
if ( m_pImageList )
delete m_pImageList;
m_pImageList = new ImageList( false );
m_mapAvatarsToImageList.RemoveAll();
PostApplySchemeSettings( pScheme );
}
//-----------------------------------------------------------------------------
// Purpose: Does dialog-specific customization after applying scheme settings.
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::PostApplySchemeSettings( vgui::IScheme *pScheme )
{
// resize the images to our resolution
for (int i = 0; i < m_pImageList->GetImageCount(); i++ )
{
int wide, tall;
m_pImageList->GetImage(i)->GetSize(wide, tall);
m_pImageList->GetImage(i)->SetSize(scheme()->GetProportionalScaledValueEx( GetScheme(),wide), scheme()->GetProportionalScaledValueEx( GetScheme(),tall));
}
m_pPlayerList->SetImageList( m_pImageList, false );
m_pPlayerList->SetVisible( true );
// light up scoreboard a bit
SetBgColor( Color( 0,0,0,0) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::ShowPanel(bool bShow)
{
// Catch the case where we call ShowPanel before ApplySchemeSettings, eg when
// going from windowed <-> fullscreen
if ( m_pImageList == NULL )
{
InvalidateLayout( true, true );
}
if ( !bShow )
{
m_nCloseKey = BUTTON_CODE_INVALID;
}
if ( BaseClass::IsVisible() == bShow )
return;
if ( bShow )
{
Reset();
Update();
SetVisible( true );
MoveToFront();
}
else
{
BaseClass::SetVisible( false );
SetMouseInputEnabled( false );
SetKeyBoardInputEnabled( false );
}
}
void CClientScoreBoardDialog::FireGameEvent( IGameEvent *event )
{
const char * type = event->GetName();
if ( Q_strcmp(type, "hltv_status") == 0 )
{
// spectators = clients - proxies
m_HLTVSpectators = event->GetInt( "clients" );
m_HLTVSpectators -= event->GetInt( "proxies" );
}
else if ( Q_strcmp(type, "server_spawn") == 0 )
{
// We'll post the message ourselves instead of using SetControlString()
// so we don't try to translate the hostname.
const char *hostname = event->GetString( "hostname" );
Panel *control = FindChildByName( "ServerName" );
if ( control )
{
PostMessage( control, new KeyValues( "SetText", "text", hostname ) );
control->MoveToFront();
}
}
if( IsVisible() )
Update();
}
bool CClientScoreBoardDialog::NeedsUpdate( void )
{
return (m_fNextUpdateTime < gpGlobals->curtime);
}
//-----------------------------------------------------------------------------
// Purpose: Recalculate the internal scoreboard data
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::Update( void )
{
// Set the title
// Reset();
m_pPlayerList->DeleteAllItems();
FillScoreBoard();
// grow the scoreboard to fit all the players
int wide, tall;
m_pPlayerList->GetContentSize(wide, tall);
tall += GetAdditionalHeight();
wide = GetWide();
if (m_iDesiredHeight < tall)
{
SetSize(wide, tall);
m_pPlayerList->SetSize(wide, tall);
}
else
{
SetSize(wide, m_iDesiredHeight);
m_pPlayerList->SetSize(wide, m_iDesiredHeight);
}
MoveToCenterOfScreen();
// update every second
m_fNextUpdateTime = gpGlobals->curtime + 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose: Sort all the teams
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::UpdateTeamInfo()
{
// TODO: work out a sorting algorithm for team display for TF2
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::UpdatePlayerInfo()
{
m_iSectionId = 0; // 0'th row is a header
int selectedRow = -1;
// walk all the players and make sure they're in the scoreboard
for ( int i = 1; i <= gpGlobals->maxClients; ++i )
{
IGameResources *gr = GameResources();
if ( gr && gr->IsConnected( i ) )
{
// add the player to the list
KeyValues *playerData = new KeyValues("data");
GetPlayerScoreInfo( i, playerData );
UpdatePlayerAvatar( i, playerData );
const char *oldName = playerData->GetString("name","");
char newName[MAX_PLAYER_NAME_LENGTH];
UTIL_MakeSafeName( oldName, newName, MAX_PLAYER_NAME_LENGTH );
playerData->SetString("name", newName);
int itemID = FindItemIDForPlayerIndex( i );
int sectionID = gr->GetTeam( i );
if ( gr->IsLocalPlayer( i ) )
{
selectedRow = itemID;
}
if (itemID == -1)
{
// add a new row
itemID = m_pPlayerList->AddItem( sectionID, playerData );
}
else
{
// modify the current row
m_pPlayerList->ModifyItem( itemID, sectionID, playerData );
}
// set the row color based on the players team
m_pPlayerList->SetItemFgColor( itemID, gr->GetTeamColor( sectionID ) );
playerData->deleteThis();
}
else
{
// remove the player
int itemID = FindItemIDForPlayerIndex( i );
if (itemID != -1)
{
m_pPlayerList->RemoveItem(itemID);
}
}
}
if ( selectedRow != -1 )
{
m_pPlayerList->SetSelectedItem(selectedRow);
}
}
//-----------------------------------------------------------------------------
// Purpose: adds the top header of the scoreboars
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::AddHeader()
{
// add the top header
m_pPlayerList->AddSection(m_iSectionId, "");
m_pPlayerList->SetSectionAlwaysVisible(m_iSectionId);
m_pPlayerList->AddColumnToSection(m_iSectionId, "name", "#PlayerName", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),NAME_WIDTH) );
m_pPlayerList->AddColumnToSection(m_iSectionId, "frags", "#PlayerScore", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),SCORE_WIDTH) );
m_pPlayerList->AddColumnToSection(m_iSectionId, "deaths", "#PlayerDeath", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),DEATH_WIDTH) );
m_pPlayerList->AddColumnToSection(m_iSectionId, "ping", "#PlayerPing", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),PING_WIDTH) );
}
//-----------------------------------------------------------------------------
// Purpose: Adds a new section to the scoreboard (i.e the team header)
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::AddSection(int teamType, int teamNumber)
{
if ( teamType == TYPE_TEAM )
{
IGameResources *gr = GameResources();
if ( !gr )
return;
// setup the team name
wchar_t *teamName = g_pVGuiLocalize->Find( gr->GetTeamName(teamNumber) );
wchar_t name[64];
wchar_t string1[1024];
if (!teamName)
{
g_pVGuiLocalize->ConvertANSIToUnicode(gr->GetTeamName(teamNumber), name, sizeof(name));
teamName = name;
}
g_pVGuiLocalize->ConstructString( string1, sizeof( string1 ), g_pVGuiLocalize->Find("#Player"), 2, teamName );
m_pPlayerList->AddSection(m_iSectionId, "", StaticPlayerSortFunc);
// Avatars are always displayed at 32x32 regardless of resolution
if ( ShowAvatars() )
{
m_pPlayerList->AddColumnToSection( m_iSectionId, "avatar", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, m_iAvatarWidth );
}
m_pPlayerList->AddColumnToSection(m_iSectionId, "name", string1, 0, scheme()->GetProportionalScaledValueEx( GetScheme(),NAME_WIDTH) - m_iAvatarWidth );
m_pPlayerList->AddColumnToSection(m_iSectionId, "frags", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),SCORE_WIDTH) );
m_pPlayerList->AddColumnToSection(m_iSectionId, "deaths", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),DEATH_WIDTH) );
m_pPlayerList->AddColumnToSection(m_iSectionId, "ping", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),PING_WIDTH) );
}
else if ( teamType == TYPE_SPECTATORS )
{
m_pPlayerList->AddSection(m_iSectionId, "");
// Avatars are always displayed at 32x32 regardless of resolution
if ( ShowAvatars() )
{
m_pPlayerList->AddColumnToSection( m_iSectionId, "avatar", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, m_iAvatarWidth );
}
m_pPlayerList->AddColumnToSection(m_iSectionId, "name", "#Spectators", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),NAME_WIDTH) - m_iAvatarWidth );
m_pPlayerList->AddColumnToSection(m_iSectionId, "frags", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),SCORE_WIDTH) );
}
}
//-----------------------------------------------------------------------------
// Purpose: Used for sorting players
//-----------------------------------------------------------------------------
bool CClientScoreBoardDialog::StaticPlayerSortFunc(vgui::SectionedListPanel *list, int itemID1, int itemID2)
{
KeyValues *it1 = list->GetItemData(itemID1);
KeyValues *it2 = list->GetItemData(itemID2);
Assert(it1 && it2);
// first compare frags
int v1 = it1->GetInt("frags");
int v2 = it2->GetInt("frags");
if (v1 > v2)
return true;
else if (v1 < v2)
return false;
// next compare deaths
v1 = it1->GetInt("deaths");
v2 = it2->GetInt("deaths");
if (v1 > v2)
return false;
else if (v1 < v2)
return true;
// the same, so compare itemID's (as a sentinel value to get deterministic sorts)
return itemID1 < itemID2;
}
//-----------------------------------------------------------------------------
// Purpose: Adds a new row to the scoreboard, from the playerinfo structure
//-----------------------------------------------------------------------------
bool CClientScoreBoardDialog::GetPlayerScoreInfo(int playerIndex, KeyValues *kv)
{
IGameResources *gr = GameResources();
if (!gr )
return false;
kv->SetInt("deaths", gr->GetDeaths( playerIndex ) );
kv->SetInt("frags", gr->GetFrags( playerIndex ) );
kv->SetInt("ping", gr->GetPing( playerIndex ) ) ;
kv->SetString("name", gr->GetPlayerName( playerIndex ) );
kv->SetInt("playerIndex", playerIndex);
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::UpdatePlayerAvatar( int playerIndex, KeyValues *kv )
{
// Update their avatar
if ( kv && ShowAvatars() && steamapicontext->SteamFriends() && steamapicontext->SteamUtils() )
{
player_info_t pi;
if ( engine->GetPlayerInfo( playerIndex, &pi ) )
{
if ( pi.friendsID )
{
CSteamID steamIDForPlayer( pi.friendsID, 1, steamapicontext->SteamUtils()->GetConnectedUniverse(), k_EAccountTypeIndividual );
// See if we already have that avatar in our list
int iMapIndex = m_mapAvatarsToImageList.Find( steamIDForPlayer );
int iImageIndex;
if ( iMapIndex == m_mapAvatarsToImageList.InvalidIndex() )
{
CAvatarImage *pImage = new CAvatarImage();
pImage->SetAvatarSteamID( steamIDForPlayer );
pImage->SetAvatarSize( 32, 32 ); // Deliberately non scaling
iImageIndex = m_pImageList->AddImage( pImage );
m_mapAvatarsToImageList.Insert( steamIDForPlayer, iImageIndex );
}
else
{
iImageIndex = m_mapAvatarsToImageList[ iMapIndex ];
}
kv->SetInt( "avatar", iImageIndex );
CAvatarImage *pAvIm = (CAvatarImage *)m_pImageList->GetImage( iImageIndex );
pAvIm->UpdateFriendStatus();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: reload the player list on the scoreboard
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::FillScoreBoard()
{
// update totals information
UpdateTeamInfo();
// update player info
UpdatePlayerInfo();
}
//-----------------------------------------------------------------------------
// Purpose: searches for the player in the scoreboard
//-----------------------------------------------------------------------------
int CClientScoreBoardDialog::FindItemIDForPlayerIndex(int playerIndex)
{
for (int i = 0; i <= m_pPlayerList->GetHighestItemID(); i++)
{
if (m_pPlayerList->IsItemIDValid(i))
{
KeyValues *kv = m_pPlayerList->GetItemData(i);
kv = kv->FindKey(m_iPlayerIndexSymbol);
if (kv && kv->GetInt() == playerIndex)
return i;
}
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the text of a control by name
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::MoveLabelToFront(const char *textEntryName)
{
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
if (entry)
{
entry->MoveToFront();
}
}
//-----------------------------------------------------------------------------
// Purpose: Center the dialog on the screen. (vgui has this method on
// Frame, but we're an EditablePanel, need to roll our own.)
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::MoveToCenterOfScreen()
{
int wx, wy, ww, wt;
surface()->GetWorkspaceBounds(wx, wy, ww, wt);
SetPos((ww - GetWide()) / 2, (wt - GetTall()) / 2);
}

View File

@ -0,0 +1,68 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "IconPanel.h"
#include "KeyValues.h"
DECLARE_BUILD_FACTORY( CIconPanel );
CIconPanel::CIconPanel( vgui::Panel *parent, const char *name ) : vgui::Panel( parent, name )
{
m_szIcon[0] = '\0';
m_icon = NULL;
m_bScaleImage = false;
}
void CIconPanel::ApplySettings( KeyValues *inResourceData )
{
Q_strncpy( m_szIcon, inResourceData->GetString( "icon", "" ), sizeof( m_szIcon ) );
m_icon = gHUD.GetIcon( m_szIcon );
m_bScaleImage = inResourceData->GetInt("scaleImage", 0);
BaseClass::ApplySettings( inResourceData );
}
void CIconPanel::SetIcon( const char *szIcon )
{
Q_strncpy( m_szIcon, szIcon, sizeof(m_szIcon) );
m_icon = gHUD.GetIcon( m_szIcon );
}
void CIconPanel::Paint()
{
BaseClass::Paint();
if ( m_icon )
{
int x, y, w, h;
GetBounds( x, y, w, h );
if ( m_bScaleImage )
{
m_icon->DrawSelf( 0, 0, w, h, m_IconColor );
}
else
{
m_icon->DrawSelf( 0, 0, m_IconColor );
}
}
}
void CIconPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
if ( m_szIcon[0] != '\0' )
{
m_icon = gHUD.GetIcon( m_szIcon );
}
SetFgColor( pScheme->GetColor( "FgColor", Color( 255, 255, 255, 255 ) ) );
}

View File

@ -0,0 +1,42 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ICONPANEL_H
#define ICONPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Panel.h>
using namespace vgui;
class CIconPanel : public vgui::Panel
{
DECLARE_CLASS_SIMPLE( CIconPanel, vgui::Panel );
public:
CIconPanel( vgui::Panel *parent, const char *name );
void Init( void );
virtual void Paint();
virtual void ApplySettings( KeyValues *inResourceData );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
void SetIcon( const char *szIcon );
void SetIconColor( Color cColor ) { m_IconColor = cColor; }
private:
CHudTexture *m_icon;
char m_szIcon[128];
bool m_bScaleImage;
CPanelAnimationVar( Color, m_IconColor, "iconColor", "255 255 255 255" );
};
#endif //ICONPANEL_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "NavProgress.h"
#include <vgui/IScheme.h>
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <filesystem.h>
#include <KeyValues.h>
#include <convar.h>
#include <vgui_controls/Label.h>
#include <game/client/iviewport.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//--------------------------------------------------------------------------------------------------------------
CNavProgress::CNavProgress( IViewPort *pViewPort ) : Frame( NULL, PANEL_NAV_PROGRESS )
{
// initialize dialog
m_pViewPort = pViewPort;
// load the new scheme early!!
SetScheme("ClientScheme");
SetMoveable(false);
SetSizeable(false);
SetProportional(true);
// hide the system buttons
SetTitleBarVisible( false );
m_pTitle = new Label( this, "TitleLabel", "" );
m_pText = new Label( this, "TextLabel", "" );
m_pProgressBarBorder = new Panel( this, "ProgressBarBorder" );
m_pProgressBar = new Panel( this, "ProgressBar" );
m_pProgressBarSizer = new Panel( this, "ProgressBarSizer" );
LoadControlSettings("Resource/UI/NavProgress.res");
Reset();
}
//--------------------------------------------------------------------------------------------------------------
CNavProgress::~CNavProgress()
{
}
//--------------------------------------------------------------------------------------------------------------
void CNavProgress::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings( pScheme );
SetPaintBackgroundType( 2 );
m_pProgressBarSizer->SetVisible( false );
m_pProgressBarBorder->SetBorder( pScheme->GetBorder( "ButtonDepressedBorder" ) );
m_pProgressBarBorder->SetBgColor( Color( 0, 0, 0, 0 ) );
m_pProgressBar->SetBorder( pScheme->GetBorder( "ButtonBorder" ) );
m_pProgressBar->SetBgColor( pScheme->GetColor( "ProgressBar.FgColor", Color( 0, 0, 0, 0 ) ) );
}
//--------------------------------------------------------------------------------------------------------------
void CNavProgress::PerformLayout()
{
BaseClass::PerformLayout();
if ( m_numTicks )
{
int w = m_pProgressBarSizer->GetWide();
w = w * m_currentTick / m_numTicks;
m_pProgressBar->SetWide( w );
}
}
//--------------------------------------------------------------------------------------------------------------
void CNavProgress::Init( const char *title, int numTicks, int startTick )
{
m_pText->SetText( title );
m_numTicks = MAX( 1, numTicks ); // non-zero, since we'll divide by this
m_currentTick = MAX( 0, MIN( m_numTicks, startTick ) );
InvalidateLayout();
}
//--------------------------------------------------------------------------------------------------------------
void CNavProgress::SetData(KeyValues *data)
{
Init( data->GetString( "msg" ),
data->GetInt( "total" ),
data->GetInt( "current" ) );
}
//--------------------------------------------------------------------------------------------------------------
void CNavProgress::ShowPanel( bool bShow )
{
if ( BaseClass::IsVisible() == bShow )
return;
m_pViewPort->ShowBackGround( bShow );
if ( bShow )
{
Activate();
SetMouseInputEnabled( true );
}
else
{
SetVisible( false );
SetMouseInputEnabled( false );
}
}
//--------------------------------------------------------------------------------------------------------------
void CNavProgress::Reset( void )
{
}
//--------------------------------------------------------------------------------------------------------------
void CNavProgress::Update( void )
{
}
//--------------------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,59 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef NAVPROGRESS_H
#define NAVPROGRESS_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Frame.h>
#include <vgui_controls/ProgressBar.h>
#include <game/client/iviewport.h>
class CNavProgress : public vgui::Frame, public IViewPortPanel
{
private:
DECLARE_CLASS_SIMPLE( CNavProgress, vgui::Frame );
public:
CNavProgress(IViewPort *pViewPort);
virtual ~CNavProgress();
virtual const char *GetName( void ) { return PANEL_NAV_PROGRESS; }
virtual void SetData(KeyValues *data);
virtual void Reset();
virtual void Update();
virtual bool NeedsUpdate( void ) { return false; }
virtual bool HasInputElements( void ) { return true; }
virtual void ShowPanel( bool bShow );
// 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 ); }
public:
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout();
void Init( const char *title, int numTicks, int currentTick );
protected:
IViewPort *m_pViewPort;
int m_numTicks;
int m_currentTick;
vgui::Label * m_pTitle;
vgui::Label * m_pText;
vgui::Panel * m_pProgressBarBorder;
vgui::Panel * m_pProgressBar;
vgui::Panel * m_pProgressBarSizer;
};
#endif // NAVPROGRESS_H

View File

@ -0,0 +1,850 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include <cdll_client_int.h>
#include <globalvars_base.h>
#include <cdll_util.h>
#include <KeyValues.h>
#include "spectatorgui.h"
#include <vgui/IScheme.h>
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui/IPanel.h>
#include <vgui_controls/ImageList.h>
#include <vgui_controls/MenuItem.h>
#include <vgui_controls/TextImage.h>
#include <stdio.h> // _snprintf define
#include <game/client/iviewport.h>
#include "commandmenu.h"
#include "hltvcamera.h"
#if defined( REPLAY_ENABLED )
#include "replay/replaycamera.h"
#endif
#include <vgui_controls/TextEntry.h>
#include <vgui_controls/Panel.h>
#include <vgui_controls/ImagePanel.h>
#include <vgui_controls/Menu.h>
#include "IGameUIFuncs.h" // for key bindings
#include <imapoverview.h>
#include <shareddefs.h>
#include <igameresources.h>
#ifdef TF_CLIENT_DLL
#include "tf_gamerules.h"
void AddSubKeyNamed( KeyValues *pKeys, const char *pszName );
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifndef _XBOX
extern IGameUIFuncs *gameuifuncs; // for key binding details
#endif
// void DuckMessage(const char *str); // from vgui_teamfortressviewport.cpp
ConVar spec_scoreboard( "spec_scoreboard", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
CSpectatorGUI *g_pSpectatorGUI = NULL;
// NB disconnect between localization text and observer mode enums
static const char *s_SpectatorModes[] =
{
"#Spec_Mode0", // OBS_MODE_NONE = 0,
"#Spec_Mode1", // OBS_MODE_DEATHCAM,
"", // OBS_MODE_FREEZECAM,
"#Spec_Mode2", // OBS_MODE_FIXED,
"#Spec_Mode3", // OBS_MODE_IN_EYE,
"#Spec_Mode4", // OBS_MODE_CHASE,
"#Spec_Mode5", // OBS_MODE_ROAMING,
};
using namespace vgui;
ConVar cl_spec_mode(
"cl_spec_mode",
"1",
FCVAR_ARCHIVE | FCVAR_USERINFO | FCVAR_SERVER_CAN_EXECUTE,
"spectator mode" );
//-----------------------------------------------------------------------------
// Purpose: left and right buttons pointing buttons
//-----------------------------------------------------------------------------
class CSpecButton : public Button
{
public:
CSpecButton(Panel *parent, const char *panelName): Button(parent, panelName, "") {}
private:
void ApplySchemeSettings(vgui::IScheme *pScheme)
{
Button::ApplySchemeSettings(pScheme);
SetFont(pScheme->GetFont("Marlett", IsProportional()) );
}
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CSpectatorMenu::CSpectatorMenu( IViewPort *pViewPort ) : Frame( NULL, PANEL_SPECMENU )
{
m_iDuckKey = BUTTON_CODE_INVALID;
m_pViewPort = pViewPort;
SetMouseInputEnabled( true );
SetKeyBoardInputEnabled( true );
SetTitleBarVisible( false ); // don't draw a title bar
SetMoveable( false );
SetSizeable( false );
SetProportional(true);
SetScheme("ClientScheme");
m_pPlayerList = new ComboBox(this, "playercombo", 10 , false);
HFont hFallbackFont = scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmallFallBack", false );
if ( INVALID_FONT != hFallbackFont )
{
m_pPlayerList->SetUseFallbackFont( true, hFallbackFont );
}
m_pViewOptions = new ComboBox(this, "viewcombo", 10 , false );
m_pConfigSettings = new ComboBox(this, "settingscombo", 10 , false );
m_pLeftButton = new CSpecButton( this, "specprev");
m_pLeftButton->SetText("3");
m_pRightButton = new CSpecButton( this, "specnext");
m_pRightButton->SetText("4");
m_pPlayerList->SetText("");
m_pViewOptions->SetText("#Spec_Modes");
m_pConfigSettings->SetText("#Spec_Options");
m_pPlayerList->SetOpenDirection( Menu::UP );
m_pViewOptions->SetOpenDirection( Menu::UP );
m_pConfigSettings->SetOpenDirection( Menu::UP );
// create view config menu
CommandMenu * menu = new CommandMenu(m_pConfigSettings, "spectatormenu", gViewPortInterface);
menu->LoadFromFile( "Resource/spectatormenu.res" );
m_pConfigSettings->SetMenu( menu ); // attach menu to combo box
// create view mode menu
menu = new CommandMenu(m_pViewOptions, "spectatormodes", gViewPortInterface);
menu->LoadFromFile("Resource/spectatormodes.res");
m_pViewOptions->SetMenu( menu ); // attach menu to combo box
LoadControlSettings("Resource/UI/BottomSpectator.res");
ListenForGameEvent( "spec_target_updated" );
}
void CSpectatorMenu::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
// need to MakeReadyForUse() on the menus so we can set their bg color before they are displayed
m_pConfigSettings->GetMenu()->MakeReadyForUse();
m_pViewOptions->GetMenu()->MakeReadyForUse();
m_pPlayerList->GetMenu()->MakeReadyForUse();
if ( g_pSpectatorGUI )
{
m_pConfigSettings->GetMenu()->SetBgColor( g_pSpectatorGUI->GetBlackBarColor() );
m_pViewOptions->GetMenu()->SetBgColor( g_pSpectatorGUI->GetBlackBarColor() );
m_pPlayerList->GetMenu()->SetBgColor( g_pSpectatorGUI->GetBlackBarColor() );
}
}
//-----------------------------------------------------------------------------
// Purpose: makes the GUI fill the screen
//-----------------------------------------------------------------------------
void CSpectatorMenu::PerformLayout()
{
int w,h;
GetHudSize(w, h);
// fill the screen
SetSize(w,GetTall());
}
//-----------------------------------------------------------------------------
// Purpose: Handles changes to combo boxes
//-----------------------------------------------------------------------------
void CSpectatorMenu::OnTextChanged(KeyValues *data)
{
Panel *panel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
vgui::ComboBox *box = dynamic_cast<vgui::ComboBox *>( panel );
if( box == m_pConfigSettings) // don't change the text in the config setting combo
{
m_pConfigSettings->SetText("#Spec_Options");
}
else if ( box == m_pPlayerList )
{
KeyValues *kv = box->GetActiveItemUserData();
if ( kv && GameResources() )
{
const char *player = kv->GetString("player");
int currentPlayerNum = GetSpectatorTarget();
const char *currentPlayerName = GameResources()->GetPlayerName( currentPlayerNum );
if ( !FStrEq( currentPlayerName, player ) )
{
char command[128];
Q_snprintf( command, sizeof(command), "spec_player \"%s\"", player );
engine->ClientCmd( command );
}
}
}
}
void CSpectatorMenu::OnCommand( const char *command )
{
if (!stricmp(command, "specnext") )
{
engine->ClientCmd("spec_next");
}
else if (!stricmp(command, "specprev") )
{
engine->ClientCmd("spec_prev");
}
}
void CSpectatorMenu::FireGameEvent( IGameEvent * event )
{
const char *pEventName = event->GetName();
if ( Q_strcmp( "spec_target_updated", pEventName ) == 0 )
{
IGameResources *gr = GameResources();
if ( !gr )
return;
// make sure the player combo box is up to date
int playernum = GetSpectatorTarget();
if ( playernum < 1 || playernum > MAX_PLAYERS )
return;
const char *selectedPlayerName = gr->GetPlayerName( playernum );
const char *currentPlayerName = "";
KeyValues *kv = m_pPlayerList->GetActiveItemUserData();
if ( kv )
{
currentPlayerName = kv->GetString( "player" );
}
if ( !FStrEq( currentPlayerName, selectedPlayerName ) )
{
for ( int i=0; i<m_pPlayerList->GetItemCount(); ++i )
{
KeyValues *kv = m_pPlayerList->GetItemUserData( i );
if ( kv && FStrEq( kv->GetString( "player" ), selectedPlayerName ) )
{
m_pPlayerList->ActivateItemByRow( i );
break;
}
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: when duck is pressed it hides the active part of the GUI
//-----------------------------------------------------------------------------
void CSpectatorMenu::OnKeyCodePressed(KeyCode code)
{
if ( code == m_iDuckKey )
{
// hide if DUCK is pressed again
m_pViewPort->ShowPanel( this, false );
}
}
void CSpectatorMenu::ShowPanel(bool bShow)
{
if ( BaseClass::IsVisible() == bShow )
return;
if ( bShow )
{
Activate();
SetMouseInputEnabled( true );
SetKeyBoardInputEnabled( true );
}
else
{
SetVisible( false );
SetMouseInputEnabled( false );
SetKeyBoardInputEnabled( false );
}
bool bIsEnabled = true;
if ( engine->IsHLTV() && HLTVCamera()->IsPVSLocked() )
{
// when watching HLTV or Replay with a locked PVS, some elements are disabled
bIsEnabled = false;
}
m_pLeftButton->SetVisible( bIsEnabled );
m_pRightButton->SetVisible( bIsEnabled );
m_pPlayerList->SetVisible( bIsEnabled );
m_pViewOptions->SetVisible( bIsEnabled );
}
void CSpectatorMenu::Update( void )
{
IGameResources *gr = GameResources();
Reset();
if ( m_iDuckKey == BUTTON_CODE_INVALID )
{
m_iDuckKey = gameuifuncs->GetButtonCodeForBind( "duck" );
}
if ( !gr )
return;
int iPlayerIndex;
for ( iPlayerIndex = 1 ; iPlayerIndex <= gpGlobals->maxClients; iPlayerIndex++ )
{
// does this slot in the array have a name?
if ( !gr->IsConnected( iPlayerIndex ) )
continue;
if ( gr->IsLocalPlayer( iPlayerIndex ) )
continue;
if ( !gr->IsAlive( iPlayerIndex ) )
continue;
wchar_t playerText[ 80 ], playerName[ 64 ], *team, teamText[ 64 ];
char localizeTeamName[64];
char szPlayerIndex[16];
g_pVGuiLocalize->ConvertANSIToUnicode( UTIL_SafeName( gr->GetPlayerName(iPlayerIndex) ), playerName, sizeof( playerName ) );
const char * teamname = gr->GetTeamName( gr->GetTeam(iPlayerIndex) );
if ( teamname )
{
Q_snprintf( localizeTeamName, sizeof( localizeTeamName ), "#%s", teamname );
team=g_pVGuiLocalize->Find( localizeTeamName );
if ( !team )
{
g_pVGuiLocalize->ConvertANSIToUnicode( teamname , teamText, sizeof( teamText ) );
team = teamText;
}
g_pVGuiLocalize->ConstructString( playerText, sizeof( playerText ), g_pVGuiLocalize->Find( "#Spec_PlayerItem_Team" ), 2, playerName, team );
}
else
{
g_pVGuiLocalize->ConstructString( playerText, sizeof( playerText ), g_pVGuiLocalize->Find( "#Spec_PlayerItem" ), 1, playerName );
}
Q_snprintf( szPlayerIndex, sizeof( szPlayerIndex ), "%d", iPlayerIndex );
KeyValues *kv = new KeyValues( "UserData", "player", gr->GetPlayerName( iPlayerIndex ), "index", szPlayerIndex );
m_pPlayerList->AddItem( playerText, kv );
kv->deleteThis();
}
// make sure the player combo box is up to date
int playernum = GetSpectatorTarget();
const char *selectedPlayerName = gr->GetPlayerName( playernum );
for ( iPlayerIndex=0; iPlayerIndex<m_pPlayerList->GetItemCount(); ++iPlayerIndex )
{
KeyValues *kv = m_pPlayerList->GetItemUserData( iPlayerIndex );
if ( kv && FStrEq( kv->GetString( "player" ), selectedPlayerName ) )
{
m_pPlayerList->ActivateItemByRow( iPlayerIndex );
break;
}
}
//=============================================================================
// HPE_BEGIN:
// [pfreese] make sure the view mode combo box is up to date - the spectator
// mode can be changed multiple ways
//=============================================================================
int specmode = GetSpectatorMode();
m_pViewOptions->SetText(s_SpectatorModes[specmode]);
//=============================================================================
// HPE_END
//=============================================================================
}
//-----------------------------------------------------------------------------
// main spectator panel
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CSpectatorGUI::CSpectatorGUI(IViewPort *pViewPort) : EditablePanel( NULL, PANEL_SPECGUI )
{
// m_bHelpShown = false;
// m_bInsetVisible = false;
// m_iDuckKey = KEY_NONE;
SetSize( 10, 10 ); // Quiet "parent not sized yet" spew
m_bSpecScoreboard = false;
m_pViewPort = pViewPort;
g_pSpectatorGUI = this;
// initialize dialog
SetVisible(false);
SetProportional(true);
// load the new scheme early!!
SetScheme("ClientScheme");
SetMouseInputEnabled( false );
SetKeyBoardInputEnabled( false );
m_pTopBar = new Panel( this, "topbar" );
m_pBottomBarBlank = new Panel( this, "bottombarblank" );
// m_pBannerImage = new ImagePanel( m_pTopBar, NULL );
m_pPlayerLabel = new Label( this, "playerlabel", "" );
m_pPlayerLabel->SetVisible( false );
TextImage *image = m_pPlayerLabel->GetTextImage();
if ( image )
{
HFont hFallbackFont = scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmallFallBack", false );
if ( INVALID_FONT != hFallbackFont )
{
image->SetUseFallbackFont( true, hFallbackFont );
}
}
SetPaintBorderEnabled(false);
SetPaintBackgroundEnabled(false);
// m_pBannerImage->SetVisible(false);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CSpectatorGUI::~CSpectatorGUI()
{
g_pSpectatorGUI = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the colour of the top and bottom bars
//-----------------------------------------------------------------------------
void CSpectatorGUI::ApplySchemeSettings(IScheme *pScheme)
{
KeyValues *pConditions = NULL;
#ifdef TF_CLIENT_DLL
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
{
pConditions = new KeyValues( "conditions" );
AddSubKeyNamed( pConditions, "if_mvm" );
}
#endif
LoadControlSettings( GetResFile(), NULL, NULL, pConditions );
if ( pConditions )
{
pConditions->deleteThis();
}
m_pBottomBarBlank->SetVisible( true );
m_pTopBar->SetVisible( true );
BaseClass::ApplySchemeSettings( pScheme );
SetBgColor(Color( 0,0,0,0 ) ); // make the background transparent
m_pTopBar->SetBgColor(GetBlackBarColor());
m_pBottomBarBlank->SetBgColor(GetBlackBarColor());
// m_pBottomBar->SetBgColor(Color( 0,0,0,0 ));
SetPaintBorderEnabled(false);
SetBorder( NULL );
#ifdef CSTRIKE_DLL
SetZPos(80); // guarantee it shows above the scope
#endif
}
//-----------------------------------------------------------------------------
// Purpose: makes the GUI fill the screen
//-----------------------------------------------------------------------------
void CSpectatorGUI::PerformLayout()
{
int w,h,x,y;
GetHudSize(w, h);
// fill the screen
SetBounds(0,0,w,h);
// stretch the bottom bar across the screen
m_pBottomBarBlank->GetPos(x,y);
m_pBottomBarBlank->SetSize( w, h - y );
}
//-----------------------------------------------------------------------------
// Purpose: checks spec_scoreboard cvar to see if the scoreboard should be displayed
//-----------------------------------------------------------------------------
void CSpectatorGUI::OnThink()
{
BaseClass::OnThink();
if ( IsVisible() )
{
if ( m_bSpecScoreboard != spec_scoreboard.GetBool() )
{
if ( !spec_scoreboard.GetBool() || !gViewPortInterface->GetActivePanel() )
{
m_bSpecScoreboard = spec_scoreboard.GetBool();
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, m_bSpecScoreboard );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: sets the image to display for the banner in the top right corner
//-----------------------------------------------------------------------------
void CSpectatorGUI::SetLogoImage(const char *image)
{
if ( m_pBannerImage )
{
m_pBannerImage->SetImage( scheme()->GetImage(image, false) );
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets the text of a control by name
//-----------------------------------------------------------------------------
void CSpectatorGUI::SetLabelText(const char *textEntryName, const char *text)
{
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
if (entry)
{
entry->SetText(text);
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets the text of a control by name
//-----------------------------------------------------------------------------
void CSpectatorGUI::SetLabelText(const char *textEntryName, wchar_t *text)
{
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
if (entry)
{
entry->SetText(text);
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets the text of a control by name
//-----------------------------------------------------------------------------
void CSpectatorGUI::MoveLabelToFront(const char *textEntryName)
{
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
if (entry)
{
entry->MoveToFront();
}
}
//-----------------------------------------------------------------------------
// Purpose: shows/hides the buy menu
//-----------------------------------------------------------------------------
void CSpectatorGUI::ShowPanel(bool bShow)
{
if ( bShow && !IsVisible() )
{
m_bSpecScoreboard = false;
}
SetVisible( bShow );
if ( !bShow && m_bSpecScoreboard )
{
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, false );
}
}
bool CSpectatorGUI::ShouldShowPlayerLabel( int specmode )
{
return ( (specmode == OBS_MODE_IN_EYE) || (specmode == OBS_MODE_CHASE) );
}
//-----------------------------------------------------------------------------
// Purpose: Updates the gui, rearranges elements
//-----------------------------------------------------------------------------
void CSpectatorGUI::Update()
{
int wide, tall;
int bx, by, bwide, btall;
GetHudSize(wide, tall);
m_pTopBar->GetBounds( bx, by, bwide, btall );
IGameResources *gr = GameResources();
int specmode = GetSpectatorMode();
int playernum = GetSpectatorTarget();
IViewPortPanel *overview = gViewPortInterface->FindPanelByName( PANEL_OVERVIEW );
if ( overview && overview->IsVisible() )
{
int mx, my, mwide, mtall;
VPANEL p = overview->GetVPanel();
vgui::ipanel()->GetPos( p, mx, my );
vgui::ipanel()->GetSize( p, mwide, mtall );
if ( my < btall )
{
// reduce to bar
m_pTopBar->SetSize( wide - (mx + mwide), btall );
m_pTopBar->SetPos( (mx + mwide), 0 );
}
else
{
// full top bar
m_pTopBar->SetSize( wide , btall );
m_pTopBar->SetPos( 0, 0 );
}
}
else
{
// full top bar
m_pTopBar->SetSize( wide , btall ); // change width, keep height
m_pTopBar->SetPos( 0, 0 );
}
m_pPlayerLabel->SetVisible( ShouldShowPlayerLabel(specmode) );
// update player name filed, text & color
if ( playernum > 0 && playernum <= gpGlobals->maxClients && gr )
{
Color c = gr->GetTeamColor( gr->GetTeam(playernum) ); // Player's team color
m_pPlayerLabel->SetFgColor( c );
wchar_t playerText[ 80 ], playerName[ 64 ], health[ 10 ];
V_wcsncpy( playerText, L"Unable to find #Spec_PlayerItem*", sizeof( playerText ) );
memset( playerName, 0x0, sizeof( playerName ) );
g_pVGuiLocalize->ConvertANSIToUnicode( UTIL_SafeName(gr->GetPlayerName( playernum )), playerName, sizeof( playerName ) );
int iHealth = gr->GetHealth( playernum );
if ( iHealth > 0 && gr->IsAlive(playernum) )
{
_snwprintf( health, ARRAYSIZE( health ), L"%i", iHealth );
g_pVGuiLocalize->ConstructString( playerText, sizeof( playerText ), g_pVGuiLocalize->Find( "#Spec_PlayerItem_Team" ), 2, playerName, health );
}
else
{
g_pVGuiLocalize->ConstructString( playerText, sizeof( playerText ), g_pVGuiLocalize->Find( "#Spec_PlayerItem" ), 1, playerName );
}
m_pPlayerLabel->SetText( playerText );
}
else
{
m_pPlayerLabel->SetText( L"" );
}
// update extra info field
wchar_t szEtxraInfo[1024];
wchar_t szTitleLabel[1024];
char tempstr[128];
if ( engine->IsHLTV() )
{
// set spectator number and HLTV title
Q_snprintf(tempstr,sizeof(tempstr),"Spectators : %d", HLTVCamera()->GetNumSpectators() );
g_pVGuiLocalize->ConvertANSIToUnicode(tempstr,szEtxraInfo,sizeof(szEtxraInfo));
Q_strncpy( tempstr, HLTVCamera()->GetTitleText(), sizeof(tempstr) );
g_pVGuiLocalize->ConvertANSIToUnicode(tempstr,szTitleLabel,sizeof(szTitleLabel));
}
else
{
// otherwise show map name
Q_FileBase( engine->GetLevelName(), tempstr, sizeof(tempstr) );
wchar_t wMapName[64];
g_pVGuiLocalize->ConvertANSIToUnicode(tempstr,wMapName,sizeof(wMapName));
g_pVGuiLocalize->ConstructString( szEtxraInfo,sizeof( szEtxraInfo ), g_pVGuiLocalize->Find("#Spec_Map" ),1, wMapName );
g_pVGuiLocalize->ConvertANSIToUnicode( "" ,szTitleLabel,sizeof(szTitleLabel));
}
SetLabelText("extrainfo", szEtxraInfo );
SetLabelText("titlelabel", szTitleLabel );
}
//-----------------------------------------------------------------------------
// Purpose: Updates the timer label if one exists
//-----------------------------------------------------------------------------
void CSpectatorGUI::UpdateTimer()
{
wchar_t szText[ 63 ];
int timer = 0;
V_swprintf_safe ( szText, L"%d:%02d\n", (timer / 60), (timer % 60) );
SetLabelText("timerlabel", szText );
}
static void ForwardSpecCmdToServer( const CCommand &args )
{
if ( engine->IsPlayingDemo() )
return;
if ( args.ArgC() == 1 )
{
// just forward the command without parameters
engine->ServerCmd( args[ 0 ] );
}
else if ( args.ArgC() == 2 )
{
// forward the command with parameter
char command[128];
Q_snprintf( command, sizeof(command), "%s \"%s\"", args[ 0 ], args[ 1 ] );
engine->ServerCmd( command );
}
}
CON_COMMAND_F( spec_next, "Spectate next player", FCVAR_CLIENTCMD_CAN_EXECUTE )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer || !pPlayer->IsObserver() )
return;
if ( engine->IsHLTV() )
{
// handle the command clientside
if ( !HLTVCamera()->IsPVSLocked() )
{
HLTVCamera()->SpecNextPlayer( false );
}
}
else
{
ForwardSpecCmdToServer( args );
}
}
CON_COMMAND_F( spec_prev, "Spectate previous player", FCVAR_CLIENTCMD_CAN_EXECUTE )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer || !pPlayer->IsObserver() )
return;
if ( engine->IsHLTV() )
{
// handle the command clientside
if ( !HLTVCamera()->IsPVSLocked() )
{
HLTVCamera()->SpecNextPlayer( true );
}
}
else
{
ForwardSpecCmdToServer( args );
}
}
CON_COMMAND_F( spec_mode, "Set spectator mode", FCVAR_CLIENTCMD_CAN_EXECUTE )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer || !pPlayer->IsObserver() )
return;
if ( engine->IsHLTV() )
{
if ( HLTVCamera()->IsPVSLocked() )
{
// in locked mode we can only switch between first and 3rd person
HLTVCamera()->ToggleChaseAsFirstPerson();
}
else
{
// we can choose any mode, not loked to PVS
int mode;
if ( args.ArgC() == 2 )
{
// set specifc mode
mode = Q_atoi( args[1] );
}
else
{
// set next mode
mode = HLTVCamera()->GetMode()+1;
if ( mode > LAST_PLAYER_OBSERVERMODE )
mode = OBS_MODE_IN_EYE;
}
// handle the command clientside
HLTVCamera()->SetMode( mode );
}
// turn off auto director once user tried to change view settings
HLTVCamera()->SetAutoDirector( false );
}
else
{
// we spectate on a game server, forward command
ForwardSpecCmdToServer( args );
}
}
CON_COMMAND_F( spec_player, "Spectate player by name", FCVAR_CLIENTCMD_CAN_EXECUTE )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer || !pPlayer->IsObserver() )
return;
if ( args.ArgC() != 2 )
return;
if ( engine->IsHLTV() )
{
// we can only switch primary spectator targets is PVS isnt locked by auto-director
if ( !HLTVCamera()->IsPVSLocked() )
{
HLTVCamera()->SpecNamedPlayer( args[1] );
}
}
else
{
ForwardSpecCmdToServer( args );
}
}

View File

@ -0,0 +1,653 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "basemodel_panel.h"
#include "activitylist.h"
#include "animation.h"
#include "vgui/IInput.h"
#include "matsys_controls/manipulator.h"
using namespace vgui;
DECLARE_BUILD_FACTORY( CBaseModelPanel );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBaseModelPanel::CBaseModelPanel( vgui::Panel *pParent, const char *pName ): BaseClass( pParent, pName )
{
m_bForcePos = false;
m_bMousePressed = false;
m_bAllowRotation = false;
m_bAllowFullManipulation = false;
m_bApplyManipulators = false;
m_bForcedCameraPosition = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CBaseModelPanel::~CBaseModelPanel()
{
}
//-----------------------------------------------------------------------------
// Purpose: Load in the model portion of the panel's resource file.
//-----------------------------------------------------------------------------
void CBaseModelPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
// Set whether we render to texture
m_bRenderToTexture = inResourceData->GetBool( "render_texture", true );
// Grab and set the camera FOV.
float flFOV = GetCameraFOV();
m_BMPResData.m_flFOV = inResourceData->GetInt( "fov", flFOV );
SetCameraFOV( m_BMPResData.m_flFOV );
// Do we allow rotation on these panels.
m_bAllowRotation = inResourceData->GetBool( "allow_rot", false );
// Do we allow full manipulation on these panels.
m_bAllowFullManipulation = inResourceData->GetBool( "allow_manip", false );
// Parse our resource file and apply all necessary updates to the MDL.
for ( KeyValues *pData = inResourceData->GetFirstSubKey() ; pData != NULL ; pData = pData->GetNextKey() )
{
if ( !Q_stricmp( pData->GetName(), "model" ) )
{
ParseModelResInfo( pData );
}
}
SetMouseInputEnabled( m_bAllowFullManipulation || m_bAllowRotation );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::ParseModelResInfo( KeyValues *inResourceData )
{
m_bForcePos = ( inResourceData->GetInt( "force_pos", 0 ) == 1 );
m_BMPResData.m_pszModelName = ReadAndAllocStringValue( inResourceData, "modelname" );
m_BMPResData.m_pszModelName_HWM = ReadAndAllocStringValue( inResourceData, "modelname_hwm" );
m_BMPResData.m_pszVCD = ReadAndAllocStringValue( inResourceData, "vcd" );
m_BMPResData.m_angModelPoseRot.Init( inResourceData->GetFloat( "angles_x", 0.0f ), inResourceData->GetFloat( "angles_y", 0.0f ), inResourceData->GetFloat( "angles_z", 0.0f ) );
m_BMPResData.m_vecOriginOffset.Init( inResourceData->GetFloat( "origin_x", 110.0 ), inResourceData->GetFloat( "origin_y", 5.0 ), inResourceData->GetFloat( "origin_z", 5.0 ) );
m_BMPResData.m_vecFramedOriginOffset.Init( inResourceData->GetFloat( "frame_origin_x", 110.0 ), inResourceData->GetFloat( "frame_origin_y", 5.0 ), inResourceData->GetFloat( "frame_origin_z", 5.0 ) );
m_BMPResData.m_vecViewportOffset.Init();
m_BMPResData.m_nSkin = inResourceData->GetInt( "skin", -1 );
m_BMPResData.m_bUseSpotlight = ( inResourceData->GetInt( "spotlight", 0 ) == 1 );
m_angPlayer = m_BMPResData.m_angModelPoseRot;
m_vecPlayerPos = m_BMPResData.m_vecOriginOffset;
for ( KeyValues *pData = inResourceData->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
{
if ( !Q_stricmp( pData->GetName(), "animation" ) )
{
ParseModelAnimInfo( pData );
}
else if ( !Q_stricmp( pData->GetName(), "attached_model" ) )
{
ParseModelAttachInfo( pData );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::ParseModelAnimInfo( KeyValues *inResourceData )
{
if ( !inResourceData )
return;
int iAnim = m_BMPResData.m_aAnimations.AddToTail();
if ( iAnim == m_BMPResData.m_aAnimations.InvalidIndex() )
return;
m_BMPResData.m_aAnimations[iAnim].m_pszName = ReadAndAllocStringValue( inResourceData, "name" );
m_BMPResData.m_aAnimations[iAnim].m_pszSequence = ReadAndAllocStringValue( inResourceData, "sequence" );
m_BMPResData.m_aAnimations[iAnim].m_pszActivity = ReadAndAllocStringValue( inResourceData, "activity" );
m_BMPResData.m_aAnimations[iAnim].m_bDefault = ( inResourceData->GetInt( "default", 0 ) == 1 );
for ( KeyValues *pAnimData = inResourceData->GetFirstSubKey(); pAnimData != NULL; pAnimData = pAnimData->GetNextKey() )
{
if ( !Q_stricmp( pAnimData->GetName(), "pose_parameters" ) )
{
m_BMPResData.m_aAnimations[iAnim].m_pPoseParameters = pAnimData->MakeCopy();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::ParseModelAttachInfo( KeyValues *inResourceData )
{
if ( !inResourceData )
return;
int iAttach = m_BMPResData.m_aAttachModels.AddToTail();
if ( iAttach == m_BMPResData.m_aAttachModels.InvalidIndex() )
return;
m_BMPResData.m_aAttachModels[iAttach].m_pszModelName = ReadAndAllocStringValue( inResourceData, "modelname" );
m_BMPResData.m_aAttachModels[iAttach].m_nSkin = inResourceData->GetInt( "skin", -1 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::SetupModelDefaults( void )
{
SetupModelAnimDefaults();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::SetupModelAnimDefaults( void )
{
// Set the move_x parameter so the run activity works
SetPoseParameterByName( "move_x", 1.0f );
// Verify that we have animations for this model.
int nAnimCount = m_BMPResData.m_aAnimations.Count();
if ( nAnimCount == 0 )
return;
// Find the default animation if one exists.
int iIndex = FindDefaultAnim();
if ( iIndex == -1 )
return;
SetModelAnim( iIndex );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CBaseModelPanel::FindDefaultAnim( void )
{
int iIndex = -1;
int nAnimCount = m_BMPResData.m_aAnimations.Count();
for ( int iAnim = 0; iAnim < nAnimCount; ++iAnim )
{
if ( m_BMPResData.m_aAnimations[iAnim].m_bDefault )
return iAnim;
}
return iIndex;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CBaseModelPanel::FindAnimByName( const char *pszName )
{
int iIndex = -1;
if ( !pszName )
return iIndex;
int nAnimCount = m_BMPResData.m_aAnimations.Count();
for ( int iAnim = 0; iAnim < nAnimCount; ++iAnim )
{
if ( !Q_stricmp( m_BMPResData.m_aAnimations[iAnim].m_pszName, pszName ) )
return iAnim;
}
return iIndex;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CBaseModelPanel::FindSequenceFromActivity( CStudioHdr *pStudioHdr, const char *pszActivity )
{
if ( !pStudioHdr )
return -1;
for ( int iSeq = 0; iSeq < pStudioHdr->GetNumSeq(); ++iSeq )
{
mstudioseqdesc_t &seqDesc = pStudioHdr->pSeqdesc( iSeq );
if ( !V_stricmp( seqDesc.pszActivityName(), pszActivity ) )
{
return iSeq;
}
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::SetModelAnim( int iAnim )
{
int nAnimCount = m_BMPResData.m_aAnimations.Count();
if ( nAnimCount == 0 || !m_BMPResData.m_aAnimations.IsValidIndex( iAnim ) )
return;
MDLCACHE_CRITICAL_SECTION();
// Get the studio header of the root model.
studiohdr_t *pStudioHdr = m_RootMDL.m_MDL.GetStudioHdr();
if ( !pStudioHdr )
return;
CStudioHdr studioHdr( pStudioHdr, g_pMDLCache );
// Do we have an activity or a sequence?
int iSequence = ACT_INVALID;
if ( m_BMPResData.m_aAnimations[iAnim].m_pszActivity && m_BMPResData.m_aAnimations[iAnim].m_pszActivity[0] )
{
iSequence = FindSequenceFromActivity( &studioHdr, m_BMPResData.m_aAnimations[iAnim].m_pszActivity );
}
else if ( m_BMPResData.m_aAnimations[iAnim].m_pszSequence && m_BMPResData.m_aAnimations[iAnim].m_pszSequence[0] )
{
iSequence = LookupSequence( &studioHdr, m_BMPResData.m_aAnimations[iAnim].m_pszSequence );
}
if ( iSequence != ACT_INVALID )
{
SetSequence( iSequence );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::SetMDL( MDLHandle_t handle, void *pProxyData )
{
MDLCACHE_CRITICAL_SECTION();
studiohdr_t *pHdr = g_pMDLCache->GetStudioHdr( handle );
if ( pHdr )
{
// SetMDL will cause the base CMdl code to set our localtoglobal indices if they aren't set.
// We set them up here so that they're left alone by that code.
CStudioHdr studioHdr( pHdr, g_pMDLCache );
if (studioHdr.numflexcontrollers() > 0 && studioHdr.pFlexcontroller( LocalFlexController_t(0) )->localToGlobal == -1)
{
for (LocalFlexController_t i = LocalFlexController_t(0); i < studioHdr.numflexcontrollers(); i++)
{
int j = C_BaseFlex::AddGlobalFlexController( studioHdr.pFlexcontroller( i )->pszName() );
studioHdr.pFlexcontroller( i )->localToGlobal = j;
}
}
}
else
{
handle = MDLHANDLE_INVALID;
}
// Clear our current sequence
SetSequence( ACT_IDLE );
BaseClass::SetMDL( handle, pProxyData );
SetupModelDefaults();
// Need to invalidate the layout so the panel will adjust is LookAt for the new model.
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::SetModelAnglesAndPosition( const QAngle &angRot, const Vector &vecPos )
{
BaseClass::SetModelAnglesAndPosition( angRot, vecPos );
// Cache
m_vecPlayerPos = vecPos;
m_angPlayer = angRot;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::SetMDL( const char *pMDLName, void *pProxyData )
{
BaseClass::SetMDL( pMDLName, pProxyData );
// Need to invalidate the layout so the panel will adjust is LookAt for the new model.
// InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseModelPanel::PerformLayout()
{
BaseClass::PerformLayout();
if ( m_bForcedCameraPosition )
{
return;
}
if ( m_bAllowFullManipulation )
{
// Set this to true if you want to keep the current rotation when changing models or poses
const bool bPreserveManipulation = false;
// Need to look at the target so we can rotate around it
const Vector kVecFocalPoint( 0.0f, 0.0f, 60.0f );
ResetCameraPivot();
SetCameraOffset( -(m_vecPlayerPos + kVecFocalPoint) );
SetCameraPositionAndAngles( kVecFocalPoint, vec3_angle, !bPreserveManipulation );
// We want to move the player to the origin and facing the correct way,
// but don't clobber m_angPlayer and m_vecPlayerPos, so use BaseClass.
BaseClass::SetModelAnglesAndPosition( m_angPlayer, vec3_origin );
// Once a manual transform has been done we want to apply it
if ( m_bApplyManipulators )
{
ApplyManipulation();
}
else
{
SyncManipulation();
}
return;
}
if ( m_bForcePos )
{
ResetCameraPivot();
SetCameraOffset( Vector( 0.0f, 0.0f, 0.0f ) );
SetCameraPositionAndAngles( vec3_origin, vec3_angle );
SetModelAnglesAndPosition( m_angPlayer, m_vecPlayerPos );
}
// Center and fill the frame with the model?
if ( m_bStartFramed )
{
Vector vecBoundsMin, vecBoundsMax;
if ( GetBoundingBox( vecBoundsMin, vecBoundsMax ) )
{
LookAtBounds( vecBoundsMin, vecBoundsMax );
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CBaseModelPanel::OnKeyCodePressed ( vgui::KeyCode code )
{
if ( m_bAllowFullManipulation )
{
BaseClass::OnKeyCodePressed( code );
return;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CBaseModelPanel::OnKeyCodeReleased( vgui::KeyCode code )
{
if ( m_bAllowFullManipulation )
{
BaseClass::OnKeyCodeReleased( code );
return;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CBaseModelPanel::OnMousePressed ( vgui::MouseCode code )
{
if ( m_bAllowFullManipulation )
{
BaseClass::OnMousePressed( code );
return;
}
if ( !m_bAllowRotation )
return;
RequestFocus();
EnableMouseCapture( true, code );
// Warp the mouse to the center of the screen
int width, height;
GetSize( width, height );
int x = width / 2;
int y = height / 2;
int xpos = x;
int ypos = y;
LocalToScreen( xpos, ypos );
input()->SetCursorPos( xpos, ypos );
m_nManipStartX = xpos;
m_nManipStartY = ypos;
m_bMousePressed = true;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CBaseModelPanel::OnMouseReleased( vgui::MouseCode code )
{
if ( m_bAllowFullManipulation )
{
BaseClass::OnMouseReleased( code );
return;
}
if ( !m_bAllowRotation )
return;
EnableMouseCapture( false );
m_bMousePressed = false;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CBaseModelPanel::OnCursorMoved( int x, int y )
{
if ( m_bAllowFullManipulation )
{
if ( m_pCurrentManip )
{
m_bApplyManipulators = true;
}
BaseClass::OnCursorMoved( x, y );
return;
}
if ( !m_bAllowRotation )
return;
if ( m_bMousePressed )
{
WarpMouse( x, y );
int xpos, ypos;
input()->GetCursorPos( xpos, ypos );
// Only want the x delta.
float flDelta = xpos - m_nManipStartX;
// Apply the delta and rotate the player.
RotateYaw( flDelta );
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CBaseModelPanel::RotateYaw( float flDelta )
{
m_angPlayer.y += flDelta;
if ( m_angPlayer.y > 360.0f )
{
m_angPlayer.y = m_angPlayer.y - 360.0f;
}
else if ( m_angPlayer.y < -360.0f )
{
m_angPlayer.y = m_angPlayer.y + 360.0f;
}
SetModelAnglesAndPosition( m_angPlayer, m_vecPlayerPos );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
Vector CBaseModelPanel::GetPlayerPos() const
{
return m_vecPlayerPos;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
QAngle CBaseModelPanel::GetPlayerAngles() const
{
return m_angPlayer;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CBaseModelPanel::OnMouseWheeled( int delta )
{
if ( m_bAllowFullManipulation )
{
BaseClass::OnMouseWheeled( delta );
return;
}
}
//-----------------------------------------------------------------------------
// Purpose: Set the camera to a distance that allows the object to fill the model panel.
//-----------------------------------------------------------------------------
void CBaseModelPanel::LookAtBounds( const Vector &vecBoundsMin, const Vector &vecBoundsMax )
{
// Get the model space render bounds.
Vector vecMin = vecBoundsMin;
Vector vecMax = vecBoundsMax;
Vector vecCenter = ( vecMax + vecMin ) * 0.5f;
vecMin -= vecCenter;
vecMax -= vecCenter;
// Get the bounds points and transform them by the desired model panel rotation.
Vector aBoundsPoints[8];
aBoundsPoints[0].Init( vecMax.x, vecMax.y, vecMax.z );
aBoundsPoints[1].Init( vecMin.x, vecMax.y, vecMax.z );
aBoundsPoints[2].Init( vecMax.x, vecMin.y, vecMax.z );
aBoundsPoints[3].Init( vecMin.x, vecMin.y, vecMax.z );
aBoundsPoints[4].Init( vecMax.x, vecMax.y, vecMin.z );
aBoundsPoints[5].Init( vecMin.x, vecMax.y, vecMin.z );
aBoundsPoints[6].Init( vecMax.x, vecMin.y, vecMin.z );
aBoundsPoints[7].Init( vecMin.x, vecMin.y, vecMin.z );
// Translated center point (offset from camera center).
Vector vecTranslateCenter = -vecCenter;
// Build the rotation matrix.
matrix3x4_t matRotation;
AngleMatrix( m_BMPResData.m_angModelPoseRot, matRotation );
Vector aXFormPoints[8];
for ( int iPoint = 0; iPoint < 8; ++iPoint )
{
VectorTransform( aBoundsPoints[iPoint], matRotation, aXFormPoints[iPoint] );
}
Vector vecXFormCenter;
VectorTransform( -vecTranslateCenter, matRotation, vecXFormCenter );
int w, h;
GetSize( w, h );
float flW = (float)w;
float flH = (float)h;
float flFOVx = DEG2RAD( m_BMPResData.m_flFOV * 0.5f );
float flFOVy = CalcFovY( ( m_BMPResData.m_flFOV * 0.5f ), flW/flH );
flFOVy = DEG2RAD( flFOVy );
float flTanFOVx = tan( flFOVx );
float flTanFOVy = tan( flFOVy );
// Find the max value of x, y, or z
Vector2D dist[8];
float flDist = 0.0f;
for ( int iPoint = 0; iPoint < 8; ++iPoint )
{
float flDistY = fabs( aXFormPoints[iPoint].y / flTanFOVx ) - aXFormPoints[iPoint].x;
float flDistZ = fabs( aXFormPoints[iPoint].z / flTanFOVy ) - aXFormPoints[iPoint].x;
dist[iPoint].x = flDistY;
dist[iPoint].y = flDistZ;
float flTestDist = MAX( flDistZ, flDistY );
flDist = MAX( flDist, flTestDist );
}
// Screen space points.
Vector2D aScreenPoints[8];
Vector aCameraPoints[8];
for ( int iPoint = 0; iPoint < 8; ++iPoint )
{
aCameraPoints[iPoint] = aXFormPoints[iPoint];
aCameraPoints[iPoint].x += flDist;
aScreenPoints[iPoint].x = aCameraPoints[iPoint].y / ( flTanFOVx * aCameraPoints[iPoint].x );
aScreenPoints[iPoint].y = aCameraPoints[iPoint].z / ( flTanFOVy * aCameraPoints[iPoint].x );
aScreenPoints[iPoint].x = ( aScreenPoints[iPoint].x * 0.5f + 0.5f ) * flW;
aScreenPoints[iPoint].y = ( aScreenPoints[iPoint].y * 0.5f + 0.5f ) * flH;
}
// Find the min/max and center of the 2D bounding box of the object.
Vector2D vecScreenMin( 99999.0f, 99999.0f ), vecScreenMax( -99999.0f, -99999.0f );
for ( int iPoint = 0; iPoint < 8; ++iPoint )
{
vecScreenMin.x = MIN( vecScreenMin.x, aScreenPoints[iPoint].x );
vecScreenMin.y = MIN( vecScreenMin.y, aScreenPoints[iPoint].y );
vecScreenMax.x = MAX( vecScreenMax.x, aScreenPoints[iPoint].x );
vecScreenMax.y = MAX( vecScreenMax.y, aScreenPoints[iPoint].y );
}
// Offset the model to the be the correct distance away from the camera.
Vector vecModelPos;
vecModelPos.x = flDist - vecXFormCenter.x;
vecModelPos.y = -vecXFormCenter.y;
vecModelPos.z = -vecXFormCenter.z;
SetModelAnglesAndPosition( m_BMPResData.m_angModelPoseRot, vecModelPos );
m_vecPlayerPos = vecModelPos;
// Back project to figure out the camera offset to center the model.
Vector2D vecPanelCenter( ( flW * 0.5f ), ( flH * 0.5f ) );
Vector2D vecScreenCenter = ( vecScreenMax + vecScreenMin ) * 0.5f;
Vector2D vecPanelCenterCamera, vecScreenCenterCamera;
vecPanelCenterCamera.x = ( ( vecPanelCenter.x / flW ) * 2.0f ) - 0.5f;
vecPanelCenterCamera.y = ( ( vecPanelCenter.y / flH ) * 2.0f ) - 0.5f;
vecPanelCenterCamera.x *= ( flTanFOVx * flDist );
vecPanelCenterCamera.y *= ( flTanFOVy * flDist );
vecScreenCenterCamera.x = ( ( vecScreenCenter.x / flW ) * 2.0f ) - 0.5f;
vecScreenCenterCamera.y = ( ( vecScreenCenter.y / flH ) * 2.0f ) - 0.5f;
vecScreenCenterCamera.x *= ( flTanFOVx * flDist );
vecScreenCenterCamera.y *= ( flTanFOVy * flDist );
Vector2D vecCameraOffset( 0.0f, 0.0f );
vecCameraOffset.x = vecPanelCenterCamera.x - vecScreenCenterCamera.x;
vecCameraOffset.y = vecPanelCenterCamera.y - vecScreenCenterCamera.y;
// Clear the camera pivot and set position matrix.
ResetCameraPivot();
if (m_bAllowRotation )
{
vecCameraOffset.x = 0.0f;
}
SetCameraOffset( Vector( 0.0f, -vecCameraOffset.x, -vecCameraOffset.y ) );
UpdateCameraTransform();
}

View File

@ -0,0 +1,225 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef BASEMODEL_PANEL_H
#define BASEMODEL_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "matsys_controls/mdlpanel.h"
//-----------------------------------------------------------------------------
// Resource file data used in posing the model inside of the model panel.
//-----------------------------------------------------------------------------
struct BMPResAnimData_t
{
const char *m_pszName;
const char *m_pszSequence;
const char *m_pszActivity;
KeyValues *m_pPoseParameters;
bool m_bDefault;
BMPResAnimData_t()
{
m_pszName = NULL;
m_pszSequence = NULL;
m_pszActivity = NULL;
m_pPoseParameters = NULL;
m_bDefault = false;
}
~BMPResAnimData_t()
{
if ( m_pszName && m_pszName[0] )
{
delete [] m_pszName;
m_pszName = NULL;
}
if ( m_pszSequence && m_pszSequence[0] )
{
delete [] m_pszSequence;
m_pszSequence = NULL;
}
if ( m_pszActivity && m_pszActivity[0] )
{
delete [] m_pszActivity;
m_pszActivity = NULL;
}
if ( m_pPoseParameters )
{
m_pPoseParameters->deleteThis();
m_pPoseParameters = NULL;
}
}
};
struct BMPResAttachData_t
{
const char *m_pszModelName;
int m_nSkin;
BMPResAttachData_t()
{
m_pszModelName = NULL;
m_nSkin = 0;
}
~BMPResAttachData_t()
{
if ( m_pszModelName && m_pszModelName[0] )
{
delete [] m_pszModelName;
m_pszModelName = NULL;
}
}
};
struct BMPResData_t
{
float m_flFOV;
const char *m_pszModelName;
const char *m_pszModelName_HWM;
const char *m_pszVCD;
QAngle m_angModelPoseRot;
Vector m_vecOriginOffset;
Vector m_vecFramedOriginOffset;
Vector2D m_vecViewportOffset;
int m_nSkin;
bool m_bUseSpotlight;
CUtlVector<BMPResAnimData_t> m_aAnimations;
CUtlVector<BMPResAttachData_t> m_aAttachModels;
BMPResData_t()
{
m_flFOV = 0.0f;
m_pszModelName = NULL;
m_pszModelName_HWM = NULL;
m_pszVCD = NULL;
m_angModelPoseRot.Init();
m_vecOriginOffset.Init();
m_vecFramedOriginOffset.Init();
m_vecViewportOffset.Init();
m_nSkin = 0;
m_bUseSpotlight = false;
}
~BMPResData_t()
{
if ( m_pszModelName && m_pszModelName[0] )
{
delete [] m_pszModelName;
m_pszModelName = NULL;
}
if ( m_pszModelName_HWM && m_pszModelName_HWM[0] )
{
delete [] m_pszModelName_HWM;
m_pszModelName_HWM = NULL;
}
if ( m_pszVCD && m_pszVCD[0] )
{
delete [] m_pszVCD;
m_pszVCD = NULL;
}
m_aAnimations.Purge();
m_aAttachModels.Purge();
}
};
//-----------------------------------------------------------------------------
// Base Model Panel
//
// ...vgui::Panel |--> vgui
// +->vgui::EditablePanel |
// +->PotterWheelPanel |--> matsys_controls
// +->MDLPanel |
// +->BaseModelPanel |--> game_controls, client.dll
//
//-----------------------------------------------------------------------------
class CBaseModelPanel : public CMDLPanel
{
DECLARE_CLASS_SIMPLE( CBaseModelPanel, CMDLPanel );
public:
// Constructor, Destructor.
CBaseModelPanel( vgui::Panel *pParent, const char *pName );
virtual ~CBaseModelPanel();
// Overridden mdlpanel.h
virtual void SetMDL( MDLHandle_t handle, void *pProxyData = NULL );
virtual void SetMDL( const char *pMDLName, void *pProxyData = NULL );
virtual void SetModelAnglesAndPosition( const QAngle &angRot, const Vector &vecPos );
// Overridden methods of vgui::Panel
virtual void ApplySettings( KeyValues *inResourceData );
virtual void PerformLayout();
// Animation.
int FindDefaultAnim( void );
int FindAnimByName( const char *pszName );
void SetModelAnim( int iAnim );
// Manipulation.
virtual void OnKeyCodePressed ( vgui::KeyCode code );
virtual void OnKeyCodeReleased( vgui::KeyCode code );
virtual void OnMousePressed ( vgui::MouseCode code );
virtual void OnMouseReleased( vgui::MouseCode code );
virtual void OnCursorMoved( int x, int y );
virtual void OnMouseWheeled( int delta );
studiohdr_t* GetStudioHdr( void ) { return m_RootMDL.m_MDL.GetStudioHdr(); }
void SetBody( unsigned int nBody ) { m_RootMDL.m_MDL.m_nBody = nBody; }
void RotateYaw( float flDelta );
Vector GetPlayerPos() const;
QAngle GetPlayerAngles() const;
void LookAtBounds( const Vector &vecBoundsMin, const Vector &vecBoundsMax );
// Set to true if external code has set a specific camera position that shouldn't be clobbered by layout
void SetForcedCameraPosition( bool bForcedCameraPosition ) { m_bForcedCameraPosition = bForcedCameraPosition; }
int FindSequenceFromActivity( CStudioHdr *pStudioHdr, const char *pszActivity );
protected:
// Resource file data.
void ParseModelResInfo( KeyValues *inResourceData );
void ParseModelAnimInfo( KeyValues *inResourceData );
void ParseModelAttachInfo( KeyValues *inResourceData );
void SetupModelDefaults( void );
void SetupModelAnimDefaults( void );
public:
BMPResData_t m_BMPResData; // Base model panel data set in the .res file.
QAngle m_angPlayer;
Vector m_vecPlayerPos;
protected:
bool m_bForcePos;
bool m_bMousePressed;
bool m_bAllowRotation;
bool m_bAllowFullManipulation;
bool m_bApplyManipulators;
bool m_bForcedCameraPosition;
// VGUI script accessible variables.
CPanelAnimationVar( bool, m_bStartFramed, "start_framed", "0" );
CPanelAnimationVar( bool, m_bDisableManipulation, "disable_manipulation", "0" );
};
#endif // BASEMODEL_PANEL_H

View File

@ -0,0 +1,898 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include <KeyValues.h>
#include <vgui/ISurface.h>
#include <vgui/ISystem.h>
#include <vgui/IScheme.h>
#include <vgui_controls/AnimationController.h>
#include <vgui_controls/EditablePanel.h>
#include <vgui_controls/ImagePanel.h>
#include <vgui/ISurface.h>
#include <vgui/IImage.h>
#include <vgui_controls/Label.h>
#include "materialsystem/imaterialsystem.h"
#include "engine/ivmodelinfo.h"
#include "c_sceneentity.h"
#include "gamestringpool.h"
#include "model_types.h"
#include "view_shared.h"
#include "view.h"
#include "ivrenderview.h"
#include "iefx.h"
#include "dlight.h"
#include "activitylist.h"
#include "basemodelpanel.h"
bool UseHWMorphModels();
using namespace vgui;
DECLARE_BUILD_FACTORY( CModelPanel );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CModelPanel::CModelPanel( vgui::Panel *pParent, const char *pName ) : vgui::EditablePanel( pParent, pName )
{
m_nFOV = 54;
m_hModel = NULL;
m_pModelInfo = NULL;
m_hScene = NULL;
m_iDefaultAnimation = 0;
m_bPanelDirty = true;
m_bStartFramed = false;
m_bAllowOffscreen = false;
ListenForGameEvent( "game_newmap" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CModelPanel::~CModelPanel()
{
if ( m_pModelInfo )
{
delete m_pModelInfo;
m_pModelInfo = NULL;
}
DeleteVCDData();
DeleteModelData();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
m_nFOV = inResourceData->GetInt( "fov", 54 );
m_bStartFramed = inResourceData->GetInt( "start_framed", false );
m_bAllowOffscreen = inResourceData->GetInt( "allow_offscreen", false );
// do we have a valid "model" section in the .res file?
for ( KeyValues *pData = inResourceData->GetFirstSubKey() ; pData != NULL ; pData = pData->GetNextKey() )
{
if ( !Q_stricmp( pData->GetName(), "model" ) )
{
ParseModelInfo( pData );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::ParseModelInfo( KeyValues *inResourceData )
{
// delete any current info
if ( m_pModelInfo )
{
delete m_pModelInfo;
m_pModelInfo = NULL;
}
m_pModelInfo = new CModelPanelModelInfo;
if ( !m_pModelInfo )
return;
m_pModelInfo->m_pszModelName = ReadAndAllocStringValue( inResourceData, "modelname" );
m_pModelInfo->m_pszModelName_HWM = ReadAndAllocStringValue( inResourceData, "modelname_hwm" );
m_pModelInfo->m_nSkin = inResourceData->GetInt( "skin", -1 );
m_pModelInfo->m_vecAbsAngles.Init( inResourceData->GetFloat( "angles_x", 0.0 ), inResourceData->GetFloat( "angles_y", 0.0 ), inResourceData->GetFloat( "angles_z", 0.0 ) );
m_pModelInfo->m_vecOriginOffset.Init( inResourceData->GetFloat( "origin_x", 110.0 ), inResourceData->GetFloat( "origin_y", 5.0 ), inResourceData->GetFloat( "origin_z", 5.0 ) );
m_pModelInfo->m_vecFramedOriginOffset.Init( inResourceData->GetFloat( "frame_origin_x", 110.0 ), inResourceData->GetFloat( "frame_origin_y", 5.0 ), inResourceData->GetFloat( "frame_origin_z", 5.0 ) );
m_pModelInfo->m_pszVCD = ReadAndAllocStringValue( inResourceData, "vcd" );
m_pModelInfo->m_bUseSpotlight = ( inResourceData->GetInt( "spotlight", 0 ) == 1 );
m_pModelInfo->m_vecViewportOffset.Init();
for ( KeyValues *pData = inResourceData->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
{
if ( !Q_stricmp( pData->GetName(), "animation" ) )
{
OnAddAnimation( pData );
}
else if ( !Q_stricmp( pData->GetName(), "attached_model" ) )
{
CModelPanelAttachedModelInfo *pAttachedModelInfo = new CModelPanelAttachedModelInfo;
if ( pAttachedModelInfo )
{
pAttachedModelInfo->m_pszModelName = ReadAndAllocStringValue( pData, "modelname" );
pAttachedModelInfo->m_nSkin = pData->GetInt( "skin", -1 );
m_pModelInfo->m_AttachedModelsInfo.AddToTail( pAttachedModelInfo );
}
}
}
m_bPanelDirty = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::OnAddAnimation( KeyValues *pData )
{
if ( !pData )
return;
CModelPanelModelAnimation *pAnimation = new CModelPanelModelAnimation;
if ( pAnimation )
{
pAnimation->m_pszName = ReadAndAllocStringValue( pData, "name" );
pAnimation->m_pszSequence = ReadAndAllocStringValue( pData, "sequence" );
pAnimation->m_pszActivity = ReadAndAllocStringValue( pData, "activity" );
pAnimation->m_bDefault = ( pData->GetInt( "default", 0 ) == 1 );
for ( KeyValues *pAnimData = pData->GetFirstSubKey(); pAnimData != NULL; pAnimData = pAnimData->GetNextKey() )
{
if ( !Q_stricmp( pAnimData->GetName(), "pose_parameters" ) )
{
pAnimation->m_pPoseParameters = pAnimData->MakeCopy();
}
}
m_pModelInfo->m_Animations.AddToTail( pAnimation );
if ( pAnimation->m_bDefault )
{
m_iDefaultAnimation = m_pModelInfo->m_Animations.Find( pAnimation );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::FireGameEvent( IGameEvent * event )
{
const char *type = event->GetName();
if ( Q_strcmp( type, "game_newmap" ) == 0 )
{
// force the models to re-setup themselves
m_bPanelDirty = true;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::SetDefaultAnimation( const char *pszName )
{
if ( m_pModelInfo )
{
for ( int i = 0; i < m_pModelInfo->m_Animations.Count(); i++ )
{
if ( m_pModelInfo->m_Animations[i] && m_pModelInfo->m_Animations[i]->m_pszName )
{
if ( !Q_stricmp( m_pModelInfo->m_Animations[i]->m_pszName, pszName ) )
{
m_iDefaultAnimation = i;
return;
}
}
}
}
Assert( 0 );
}
//-----------------------------------------------------------------------------
// Purpose: Replaces the current model with a new one, without changing the camera settings
//-----------------------------------------------------------------------------
void CModelPanel::SwapModel( const char *pszName, const char *pszAttached )
{
if ( !m_pModelInfo || !pszName || !pszName[0] )
return;
int len = Q_strlen( pszName ) + 1;
char *pAlloced = new char[ len ];
Assert( pAlloced );
Q_strncpy( pAlloced, pszName, len );
m_pModelInfo->m_pszModelName = pAlloced;
ClearAttachedModelInfos();
if ( pszAttached )
{
CModelPanelAttachedModelInfo *pAttachedModelInfo = new CModelPanelAttachedModelInfo;
if ( pAttachedModelInfo )
{
len = Q_strlen( pszAttached ) + 1;
pAlloced = new char[ len ];
Assert( pAlloced );
Q_strncpy( pAlloced, pszAttached, len );
pAttachedModelInfo->m_pszModelName = pAlloced;
pAttachedModelInfo->m_nSkin = 0;
m_pModelInfo->m_AttachedModelsInfo.AddToTail( pAttachedModelInfo );
}
}
m_bPanelDirty = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::DeleteVCDData( void )
{
if ( m_hScene.Get() )
{
m_hScene->StopClientOnlyScene();
m_hScene->Remove();
m_hScene = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::SetupVCD( void )
{
if ( !m_pModelInfo )
return;
DeleteVCDData();
C_SceneEntity *pEnt = new class C_SceneEntity;
if ( !pEnt )
return;
if ( pEnt->InitializeAsClientEntity( "", RENDER_GROUP_OTHER ) == false )
{
// we failed to initialize this entity so just return gracefully
pEnt->Remove();
return;
}
// setup the handle
m_hScene = pEnt;
// setup the scene
pEnt->SetupClientOnlyScene( m_pModelInfo->m_pszVCD, m_hModel, true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::ClearAttachedModelInfos( void )
{
if ( m_pModelInfo )
{
m_pModelInfo->m_AttachedModelsInfo.PurgeAndDeleteElements();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::DeleteModelData( void )
{
if ( m_hModel.Get() )
{
m_hModel->Remove();
m_hModel = NULL;
m_flFrameDistance = 0;
}
for ( int i = 0 ; i < m_AttachedModels.Count() ; i++ )
{
if ( m_AttachedModels[i].Get() )
{
m_AttachedModels[i]->Remove();
}
m_AttachedModels.Remove( i );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CModelPanel::GetModelName( void )
{
if ( !m_pModelInfo )
return NULL;
// check to see if we want to use a HWM model
if ( UseHWMorphModels() )
{
// do we have a valid HWM model filename
if ( m_pModelInfo->m_pszModelName_HWM && ( Q_strlen( m_pModelInfo->m_pszModelName_HWM ) > 0 ) )
{
// does the file exist
model_t *pModel = (model_t *)engine->LoadModel( m_pModelInfo->m_pszModelName_HWM );
if ( pModel )
{
return m_pModelInfo->m_pszModelName_HWM;
}
}
}
return m_pModelInfo->m_pszModelName;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::SetupModel( void )
{
if ( !m_pModelInfo )
return;
MDLCACHE_CRITICAL_SECTION();
// remove any current models we're using
DeleteModelData();
const char *pszModelName = GetModelName();
if ( !pszModelName || !pszModelName[0] )
return;
// create the new model
CModelPanelModel *pEnt = new CModelPanelModel;
if ( !pEnt )
return;
if ( pEnt->InitializeAsClientEntity( pszModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
{
// we failed to initialize this entity so just return gracefully
pEnt->Remove();
return;
}
// setup the handle
m_hModel = pEnt;
pEnt->DontRecordInTools();
pEnt->AddEffects( EF_NODRAW ); // don't let the renderer draw the model normally
if ( m_pModelInfo->m_nSkin >= 0 )
{
pEnt->m_nSkin = m_pModelInfo->m_nSkin;
}
// do we have any animation information?
if ( m_pModelInfo->m_Animations.Count() > 0 && m_pModelInfo->m_Animations.IsValidIndex( m_iDefaultAnimation ) )
{
CModelPanelModelAnimation *pAnim = m_pModelInfo->m_Animations[ m_iDefaultAnimation ];
int sequence = ACT_INVALID;
if ( pAnim->m_pszActivity && pAnim->m_pszActivity[0] )
{
Activity activity = (Activity)ActivityList_IndexForName( pAnim->m_pszActivity );
sequence = pEnt->SelectWeightedSequence( activity );
}
else if ( pAnim->m_pszSequence && pAnim->m_pszSequence[0] )
{
sequence = pEnt->LookupSequence( pAnim->m_pszSequence );
}
if ( sequence != ACT_INVALID )
{
pEnt->ResetSequence( sequence );
pEnt->SetCycle( 0 );
if ( pAnim->m_pPoseParameters )
{
for ( KeyValues *pData = pAnim->m_pPoseParameters->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
{
const char *pName = pData->GetName();
float flValue = pData->GetFloat();
pEnt->SetPoseParameter( pName, flValue );
}
}
pEnt->m_flAnimTime = gpGlobals->curtime;
}
}
// setup any attached models
for ( int i = 0 ; i < m_pModelInfo->m_AttachedModelsInfo.Count() ; i++ )
{
CModelPanelAttachedModelInfo *pInfo = m_pModelInfo->m_AttachedModelsInfo[i];
C_BaseAnimating *pTemp = new C_BaseAnimating;
if ( pTemp )
{
if ( pTemp->InitializeAsClientEntity( pInfo->m_pszModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
{
// we failed to initialize this model so just skip it
pTemp->Remove();
continue;
}
pTemp->DontRecordInTools();
pTemp->AddEffects( EF_NODRAW ); // don't let the renderer draw the model normally
pTemp->FollowEntity( m_hModel.Get() ); // attach to parent model
if ( pInfo->m_nSkin >= 0 )
{
pTemp->m_nSkin = pInfo->m_nSkin;
}
pTemp->m_flAnimTime = gpGlobals->curtime;
m_AttachedModels.AddToTail( pTemp );
}
}
CalculateFrameDistance();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::InitCubeMaps()
{
ITexture *pCubemapTexture;
// Deal with the default cubemap
if ( g_pMaterialSystemHardwareConfig->GetHDREnabled() )
{
pCubemapTexture = materials->FindTexture( "editor/cubemap.hdr", NULL, true );
m_DefaultHDREnvCubemap.Init( pCubemapTexture );
}
else
{
pCubemapTexture = materials->FindTexture( "editor/cubemap", NULL, true );
m_DefaultEnvCubemap.Init( pCubemapTexture );
}
}
//-----------------------------------------------------------------------------
// Purpose: If the panel is marked as dirty, update it and mark it as clean
//-----------------------------------------------------------------------------
void CModelPanel::UpdateModel()
{
if ( m_bPanelDirty )
{
InitCubeMaps();
SetupModel();
// are we trying to play a VCD?
if ( Q_strlen( m_pModelInfo->m_pszVCD ) > 0 )
{
SetupVCD();
}
m_bPanelDirty = false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::Paint()
{
BaseClass::Paint();
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pLocalPlayer || !m_pModelInfo )
return;
MDLCACHE_CRITICAL_SECTION();
UpdateModel();
if ( !m_hModel.Get() )
return;
int i = 0;
int x, y, w, h;
GetBounds( x, y, w, h );
ParentLocalToScreen( x, y );
if ( !m_bAllowOffscreen && x < 0 )
{
// prevent x from being pushed off the left side of the screen
// for modes like 1280 x 1024 (prevents model from being drawn in the panel)
x = 0;
}
Vector vecExtraModelOffset( 0, 0, 0 );
float flWidthRatio = ((float)w / (float)h ) / ( 4.0f / 3.0f );
// is this a player model?
if ( Q_strstr( GetModelName(), "models/player/" ) )
{
// need to know if the ratio is not 4/3
// HACK! HACK! to get our player models to appear the way they do in 4/3 if we're using other aspect ratios
if ( flWidthRatio > 1.05f )
{
vecExtraModelOffset.Init( -60, 0, 0 );
}
else if ( flWidthRatio < 0.95f )
{
vecExtraModelOffset.Init( 15, 0, 0 );
}
}
m_hModel->SetAbsOrigin( m_pModelInfo->m_vecOriginOffset + vecExtraModelOffset );
m_hModel->SetAbsAngles( QAngle( m_pModelInfo->m_vecAbsAngles.x, m_pModelInfo->m_vecAbsAngles.y, m_pModelInfo->m_vecAbsAngles.z ) );
// do we have a valid sequence?
if ( m_hModel->GetSequence() != -1 )
{
m_hModel->FrameAdvance( gpGlobals->frametime );
}
CMatRenderContextPtr pRenderContext( materials );
// figure out what our viewport is right now
int viewportX, viewportY, viewportWidth, viewportHeight;
pRenderContext->GetViewport( viewportX, viewportY, viewportWidth, viewportHeight );
// Now draw it.
CViewSetup view;
view.x = x + m_pModelInfo->m_vecViewportOffset.x + viewportX; // we actually want to offset by the
view.y = y + m_pModelInfo->m_vecViewportOffset.y + viewportY; // viewport origin here because Push3DView expects global coords below
view.width = w;
view.height = h;
view.m_bOrtho = false;
// scale the FOV for aspect ratios other than 4/3
view.fov = ScaleFOVByWidthRatio( m_nFOV, flWidthRatio );
view.origin = vec3_origin;
view.angles.Init();
view.zNear = VIEW_NEARZ;
view.zFar = 1000;
// Not supported by queued material system - doesn't appear to be necessary
// ITexture *pLocalCube = pRenderContext->GetLocalCubemap();
if ( g_pMaterialSystemHardwareConfig->GetHDREnabled() )
{
pRenderContext->BindLocalCubemap( m_DefaultHDREnvCubemap );
}
else
{
pRenderContext->BindLocalCubemap( m_DefaultEnvCubemap );
}
pRenderContext->SetLightingOrigin( vec3_origin );
pRenderContext->SetAmbientLight( 0.4, 0.4, 0.4 );
static Vector white[6] =
{
Vector( 0.4, 0.4, 0.4 ),
Vector( 0.4, 0.4, 0.4 ),
Vector( 0.4, 0.4, 0.4 ),
Vector( 0.4, 0.4, 0.4 ),
Vector( 0.4, 0.4, 0.4 ),
Vector( 0.4, 0.4, 0.4 ),
};
g_pStudioRender->SetAmbientLightColors( white );
g_pStudioRender->SetLocalLights( 0, NULL );
if ( m_pModelInfo->m_bUseSpotlight )
{
Vector vecMins, vecMaxs;
m_hModel->GetRenderBounds( vecMins, vecMaxs );
LightDesc_t spotLight( vec3_origin + Vector( 0, 0, 200 ), Vector( 1, 1, 1 ), m_hModel->GetAbsOrigin() + Vector( 0, 0, ( vecMaxs.z - vecMins.z ) * 0.75 ), 0.035, 0.873 );
g_pStudioRender->SetLocalLights( 1, &spotLight );
}
Frustum dummyFrustum;
render->Push3DView( view, 0, NULL, dummyFrustum );
modelrender->SuppressEngineLighting( true );
float color[3] = { 1.0f, 1.0f, 1.0f };
render->SetColorModulation( color );
render->SetBlend( 1.0f );
m_hModel->DrawModel( STUDIO_RENDER );
for ( i = 0 ; i < m_AttachedModels.Count() ; i++ )
{
if ( m_AttachedModels[i].Get() )
{
m_AttachedModels[i]->DrawModel( STUDIO_RENDER );
}
}
modelrender->SuppressEngineLighting( false );
render->PopView( dummyFrustum );
pRenderContext->BindLocalCubemap( NULL );
/*
vgui::surface()->DrawSetColor( Color(0,0,0,255) );
vgui::surface()->DrawOutlinedRect( 0,0, GetWide(), GetTall() );
*/
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CModelPanel::FindAnimByName( const char *pszName )
{
// first try to find the sequence using pszName as the friendly name
for ( int iIndex = 0 ; iIndex < m_pModelInfo->m_Animations.Count() ; iIndex++ )
{
CModelPanelModelAnimation *pAnimation = m_pModelInfo->m_Animations[ iIndex ];
if ( FStrEq( pAnimation->m_pszName, pszName ) )
return iIndex;
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CModelPanel::SetSequence( const char *pszName )
{
bool bRetVal = false;
const char *pszAnim = NULL;
MDLCACHE_CRITICAL_SECTION();
if ( m_pModelInfo )
{
int iIndex = FindAnimByName(pszName);
if ( iIndex != -1 )
{
pszAnim = m_pModelInfo->m_Animations[iIndex]->m_pszSequence;
}
else
{
// if not, just use the passed name as the sequence
pszAnim = pszName;
}
if ( m_hModel.Get() )
{
int sequence = m_hModel->LookupSequence( pszAnim );
if ( sequence != ACT_INVALID )
{
m_hModel->ResetSequence( sequence );
m_hModel->SetCycle( 0 );
bRetVal = true;
}
}
}
return bRetVal;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModelPanel::OnSetAnimation( KeyValues *data )
{
UpdateModel();
// If there's no model, these commands will be ignored.
Assert(m_hModel);
if ( data )
{
const char *pszAnimation = data->GetString( "animation", "" );
const char *pszActivity = data->GetString( "activity", "" );
if ( pszActivity && pszActivity[0] )
{
if ( m_hModel )
{
int iIndex = FindAnimByName(pszActivity);
if ( iIndex != -1 )
{
pszActivity = m_pModelInfo->m_Animations[iIndex]->m_pszActivity;
}
Activity activity = (Activity)ActivityList_IndexForName( pszActivity );
int sequence = m_hModel->SelectWeightedSequence( activity );
if ( sequence != ACT_INVALID )
{
m_hModel->ResetSequence( sequence );
m_hModel->SetCycle( 0 );
}
}
}
else
{
SetSequence( pszAnimation );
}
}
}
void CModelPanel::CalculateFrameDistanceInternal( const model_t *pModel )
{
// Get the model space render bounds.
Vector vecMin, vecMax;
modelinfo->GetModelRenderBounds( pModel, vecMin, vecMax );
Vector vecCenter = ( vecMax + vecMin ) * 0.5f;
vecMin -= vecCenter;
vecMax -= vecCenter;
// Get the bounds points and transform them by the desired model panel rotation.
Vector aBoundsPoints[8];
aBoundsPoints[0].Init( vecMax.x, vecMax.y, vecMax.z );
aBoundsPoints[1].Init( vecMin.x, vecMax.y, vecMax.z );
aBoundsPoints[2].Init( vecMax.x, vecMin.y, vecMax.z );
aBoundsPoints[3].Init( vecMin.x, vecMin.y, vecMax.z );
aBoundsPoints[4].Init( vecMax.x, vecMax.y, vecMin.z );
aBoundsPoints[5].Init( vecMin.x, vecMax.y, vecMin.z );
aBoundsPoints[6].Init( vecMax.x, vecMin.y, vecMin.z );
aBoundsPoints[7].Init( vecMin.x, vecMin.y, vecMin.z );
// Translated center point (offset from camera center).
Vector vecTranslateCenter = -vecCenter;
// Build the rotation matrix.
QAngle angPanelAngles( m_pModelInfo->m_vecAbsAngles.x, m_pModelInfo->m_vecAbsAngles.y, m_pModelInfo->m_vecAbsAngles.z );
matrix3x4_t matRotation;
AngleMatrix( angPanelAngles, matRotation );
Vector aXFormPoints[8];
for ( int iPoint = 0; iPoint < 8; ++iPoint )
{
VectorTransform( aBoundsPoints[iPoint], matRotation, aXFormPoints[iPoint] );
}
Vector vecXFormCenter;
VectorTransform( -vecTranslateCenter, matRotation, vecXFormCenter );
int w, h;
GetSize( w, h );
float flW = (float)w;
float flH = (float)h;
float flFOVx = DEG2RAD( m_nFOV * 0.5f );
float flFOVy = CalcFovY( ( m_nFOV * 0.5f ), flW/flH );
flFOVy = DEG2RAD( flFOVy );
float flTanFOVx = tan( flFOVx );
float flTanFOVy = tan( flFOVy );
// Find the max value of x, y, or z
float flDist = 0.0f;
for ( int iPoint = 0; iPoint < 8; ++iPoint )
{
float flDistZ = fabs( aXFormPoints[iPoint].z / flTanFOVy - aXFormPoints[iPoint].x );
float flDistY = fabs( aXFormPoints[iPoint].y / flTanFOVx - aXFormPoints[iPoint].x );
float flTestDist = MAX( flDistZ, flDistY );
flDist = MAX( flDist, flTestDist );
}
// Scale the object down by 10%.
flDist *= 1.10f;
// Add the framing offset.
vecXFormCenter += m_pModelInfo->m_vecFramedOriginOffset;
// Zoom to the frame distance
m_pModelInfo->m_vecOriginOffset.x = flDist - vecXFormCenter.x;
m_pModelInfo->m_vecOriginOffset.y = -vecXFormCenter.y;
m_pModelInfo->m_vecOriginOffset.z = -vecXFormCenter.z;
// Screen space points.
Vector2D aScreenPoints[8];
Vector aCameraPoints[8];
for ( int iPoint = 0; iPoint < 8; ++iPoint )
{
aCameraPoints[iPoint] = aXFormPoints[iPoint];
aCameraPoints[iPoint].x += flDist;
aScreenPoints[iPoint].x = aCameraPoints[iPoint].y / ( flTanFOVx * aCameraPoints[iPoint].x );
aScreenPoints[iPoint].y = aCameraPoints[iPoint].z / ( flTanFOVy * aCameraPoints[iPoint].x );
aScreenPoints[iPoint].x = ( aScreenPoints[iPoint].x * 0.5f + 0.5f ) * flW;
aScreenPoints[iPoint].y = ( aScreenPoints[iPoint].y * 0.5f + 0.5f ) * flH;
}
// Find the min/max and center of the 2D bounding box of the object.
Vector2D vecScreenMin( 99999.0f, 99999.0f ), vecScreenMax( -99999.0f, -99999.0f );
for ( int iPoint = 0; iPoint < 8; ++iPoint )
{
vecScreenMin.x = MIN( vecScreenMin.x, aScreenPoints[iPoint].x );
vecScreenMin.y = MIN( vecScreenMin.y, aScreenPoints[iPoint].y );
vecScreenMax.x = MAX( vecScreenMax.x, aScreenPoints[iPoint].x );
vecScreenMax.y = MAX( vecScreenMax.y, aScreenPoints[iPoint].y );
}
vecScreenMin.x = clamp( vecScreenMin.x, 0.0f, flW );
vecScreenMin.y = clamp( vecScreenMin.y, 0.0f, flH );
vecScreenMax.x = clamp( vecScreenMax.x, 0.0f, flW );
vecScreenMax.y = clamp( vecScreenMax.y, 0.0f, flH );
// Offset the view port based on the calculated model 2D center and the center of the viewport.
Vector2D vecScreenCenter = ( vecScreenMax + vecScreenMin ) * 0.5f;
m_pModelInfo->m_vecViewportOffset.x = -( ( flW * 0.5f ) - vecScreenCenter.x );
m_pModelInfo->m_vecViewportOffset.y = -( ( flH * 0.5f ) - vecScreenCenter.y );
}
//-----------------------------------------------------------------------------
// Purpose: Calculates the distance the camera should be at to frame the model on the screen.
//-----------------------------------------------------------------------------
void CModelPanel::CalculateFrameDistance( void )
{
m_flFrameDistance = 0;
if ( !m_hModel )
return;
// Compute a bounding radius for the model
const model_t *mod = modelinfo->GetModel( m_hModel->GetModelIndex() );
if ( !mod )
return;
if ( m_bStartFramed )
{
CalculateFrameDistanceInternal( mod );
}
}
//-----------------------------------------------------------------------------
// Purpose: Moves the camera forward/backward along the current view angle to
// frame the model on the screen.
//-----------------------------------------------------------------------------
void CModelPanel::ZoomToFrameDistance( void )
{
if ( !m_flFrameDistance || !m_hModel )
return;
const model_t *mod = modelinfo->GetModel( m_hModel->GetModelIndex() );
if ( !mod )
return;
// Move the model to the midpoint
Vector mins, maxs, vecModelCenter;
modelinfo->GetModelRenderBounds( mod, mins, maxs );
VectorLerp( mins, maxs, 0.5f, vecModelCenter );
vecModelCenter += m_pModelInfo->m_vecFramedOriginOffset;
// Zoom to the frame distance
m_pModelInfo->m_vecOriginOffset.x = m_flFrameDistance;
m_pModelInfo->m_vecOriginOffset.y = -vecModelCenter.y;
m_pModelInfo->m_vecOriginOffset.z = -vecModelCenter.z;
}

View File

@ -0,0 +1,233 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BASEMODELPANEL_H
#define BASEMODELPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/IScheme.h>
#include <vgui_controls/ImagePanel.h>
#include <vgui_controls/EditablePanel.h>
#include "GameEventListener.h"
#include "KeyValues.h"
class C_SceneEntity;
class CModelPanelModel : public C_BaseFlex
{
public:
CModelPanelModel(){}
DECLARE_CLASS( CModelPanelModel, C_BaseFlex );
virtual bool IsMenuModel() const{ return true; }
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CModelPanelModelAnimation
{
public:
CModelPanelModelAnimation()
{
m_pszName = NULL;
m_pszSequence = NULL;
m_pszActivity = NULL;
m_pPoseParameters = NULL;
m_bDefault = false;
}
~CModelPanelModelAnimation()
{
if ( m_pszName && m_pszName[0] )
{
delete [] m_pszName;
m_pszName = NULL;
}
if ( m_pszSequence && m_pszSequence[0] )
{
delete [] m_pszSequence;
m_pszSequence = NULL;
}
if ( m_pszActivity && m_pszActivity[0] )
{
delete [] m_pszActivity;
m_pszActivity = NULL;
}
if ( m_pPoseParameters )
{
m_pPoseParameters->deleteThis();
m_pPoseParameters = NULL;
}
}
public:
const char *m_pszName;
const char *m_pszSequence;
const char *m_pszActivity;
KeyValues *m_pPoseParameters;
bool m_bDefault;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CModelPanelAttachedModelInfo
{
public:
CModelPanelAttachedModelInfo()
{
m_pszModelName = NULL;
m_nSkin = 0;
}
~CModelPanelAttachedModelInfo()
{
if ( m_pszModelName && m_pszModelName[0] )
{
delete [] m_pszModelName;
m_pszModelName = NULL;
}
}
public:
const char *m_pszModelName;
int m_nSkin;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CModelPanelModelInfo
{
public:
CModelPanelModelInfo()
{
m_pszModelName = NULL;
m_pszModelName_HWM = NULL;
m_nSkin = -1;
m_vecAbsAngles.Init();
m_vecOriginOffset.Init();
m_vecFramedOriginOffset.Init();
m_bUseSpotlight = false;
}
~CModelPanelModelInfo()
{
if ( m_pszModelName && m_pszModelName[0] )
{
delete [] m_pszModelName;
m_pszModelName = NULL;
}
if ( m_pszModelName_HWM && m_pszModelName_HWM[0] )
{
delete [] m_pszModelName_HWM;
m_pszModelName_HWM = NULL;
}
if ( m_pszVCD && m_pszVCD[0] )
{
delete [] m_pszVCD;
m_pszVCD = NULL;
}
m_Animations.PurgeAndDeleteElements();
m_AttachedModelsInfo.PurgeAndDeleteElements();
}
public:
const char *m_pszModelName;
const char *m_pszModelName_HWM;
int m_nSkin;
const char *m_pszVCD;
Vector m_vecAbsAngles;
Vector m_vecOriginOffset;
Vector2D m_vecViewportOffset;
Vector m_vecFramedOriginOffset;
bool m_bUseSpotlight;
CUtlVector<CModelPanelModelAnimation*> m_Animations;
CUtlVector<CModelPanelAttachedModelInfo*> m_AttachedModelsInfo;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CModelPanel : public vgui::EditablePanel, public CGameEventListener
{
public:
DECLARE_CLASS_SIMPLE( CModelPanel, vgui::EditablePanel );
CModelPanel( vgui::Panel *parent, const char *name );
virtual ~CModelPanel();
virtual void Paint();
virtual void ApplySettings( KeyValues *inResourceData );
virtual void DeleteVCDData( void );
virtual void DeleteModelData( void );
virtual void SetFOV( int nFOV ){ m_nFOV = nFOV; }
virtual void SetPanelDirty( void ){ m_bPanelDirty = true; }
virtual bool SetSequence( const char *pszSequence );
MESSAGE_FUNC_PARAMS( OnAddAnimation, "AddAnimation", data );
MESSAGE_FUNC_PARAMS( OnSetAnimation, "SetAnimation", data );
void SetDefaultAnimation( const char *pszName );
void SwapModel( const char *pszName, const char *pszAttached = NULL );
virtual void ParseModelInfo( KeyValues *inResourceData );
void ClearAttachedModelInfos( void );
void CalculateFrameDistance( void );
void ZoomToFrameDistance( void );
void UpdateModel();
public: // IGameEventListener:
virtual void FireGameEvent( IGameEvent * event );
protected:
virtual void SetupModel( void );
virtual void SetupVCD( void );
virtual const char *GetModelName( void );
private:
void InitCubeMaps();
int FindAnimByName( const char *pszName );
void CalculateFrameDistanceInternal( const model_t *pModel );
public:
int m_nFOV;
float m_flFrameDistance;
bool m_bStartFramed;
CModelPanelModelInfo *m_pModelInfo;
CHandle<CModelPanelModel> m_hModel;
CUtlVector<CHandle<C_BaseAnimating> > m_AttachedModels;
CHandle<C_SceneEntity> m_hScene;
private:
bool m_bPanelDirty;
int m_iDefaultAnimation;
bool m_bAllowOffscreen;
CTextureReference m_DefaultEnvCubemap;
CTextureReference m_DefaultHDREnvCubemap;
};
#endif // BASEMODELPANEL_H

View File

@ -0,0 +1,721 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Client DLL VGUI2 Viewport
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#pragma warning( disable : 4800 ) // disable forcing int to bool performance warning
#include "cbase.h"
#include <cdll_client_int.h>
#include <cdll_util.h>
#include <globalvars_base.h>
// VGUI panel includes
#include <vgui_controls/Panel.h>
#include <vgui_controls/AnimationController.h>
#include <vgui/ISurface.h>
#include <KeyValues.h>
#include <vgui/IScheme.h>
#include <vgui/IVGui.h>
#include <vgui/ILocalize.h>
#include <vgui/IPanel.h>
#include <vgui_controls/Button.h>
#include <igameresources.h>
// sub dialogs
#include "clientscoreboarddialog.h"
#include "spectatorgui.h"
#include "teammenu.h"
#include "vguitextwindow.h"
#include "IGameUIFuncs.h"
#include "mapoverview.h"
#include "hud.h"
#include "NavProgress.h"
#include "commentary_modelviewer.h"
// our definition
#include "baseviewport.h"
#include <filesystem.h>
#include <convar.h>
#include "ienginevgui.h"
#include "iclientmode.h"
#include "tier0/etwprof.h"
#if defined( REPLAY_ENABLED )
#include "replay/ireplaysystem.h"
#include "replay/ienginereplay.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IViewPort *gViewPortInterface = NULL;
vgui::Panel *g_lastPanel = NULL; // used for mouseover buttons, keeps track of the last active panel
vgui::Button *g_lastButton = NULL; // used for mouseover buttons, keeps track of the last active button
using namespace vgui;
ConVar hud_autoreloadscript("hud_autoreloadscript", "0", FCVAR_NONE, "Automatically reloads the animation script each time one is ran");
static ConVar cl_leveloverviewmarker( "cl_leveloverviewmarker", "0", FCVAR_CHEAT );
CON_COMMAND( showpanel, "Shows a viewport panel <name>" )
{
if ( !gViewPortInterface )
return;
if ( args.ArgC() != 2 )
return;
gViewPortInterface->ShowPanel( args[ 1 ], true );
}
CON_COMMAND( hidepanel, "Hides a viewport panel <name>" )
{
if ( !gViewPortInterface )
return;
if ( args.ArgC() != 2 )
return;
gViewPortInterface->ShowPanel( args[ 1 ], false );
}
/* global helper functions
bool Helper_LoadFile( IBaseFileSystem *pFileSystem, const char *pFilename, CUtlVector<char> &buf )
{
FileHandle_t hFile = pFileSystem->Open( pFilename, "rt" );
if ( hFile == FILESYSTEM_INVALID_HANDLE )
{
Warning( "Helper_LoadFile: missing %s\n", pFilename );
return false;
}
unsigned long len = pFileSystem->Size( hFile );
buf.SetSize( len );
pFileSystem->Read( buf.Base(), buf.Count(), hFile );
pFileSystem->Close( hFile );
return true;
} */
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CBaseViewport::LoadHudAnimations( void )
{
const char *HUDANIMATION_MANIFEST_FILE = "scripts/hudanimations_manifest.txt";
KeyValues *manifest = new KeyValues( HUDANIMATION_MANIFEST_FILE );
if ( manifest->LoadFromFile( g_pFullFileSystem, HUDANIMATION_MANIFEST_FILE, "GAME" ) == false )
{
manifest->deleteThis();
return false;
}
bool bClearScript = true;
// Load each file defined in the text
for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() )
{
if ( !Q_stricmp( sub->GetName(), "file" ) )
{
// Add it
if ( m_pAnimController->SetScriptFile( GetVPanel(), sub->GetString(), bClearScript ) == false )
{
Assert( 0 );
}
bClearScript = false;
continue;
}
}
manifest->deleteThis();
return true;
}
//================================================================
CBaseViewport::CBaseViewport() : vgui::EditablePanel( NULL, "CBaseViewport")
{
SetSize( 10, 10 ); // Quiet "parent not sized yet" spew
gViewPortInterface = this;
m_bInitialized = false;
m_GameuiFuncs = NULL;
m_GameEventManager = NULL;
SetKeyBoardInputEnabled( false );
SetMouseInputEnabled( false );
#ifndef _XBOX
m_pBackGround = NULL;
#endif
m_bHasParent = false;
m_pActivePanel = NULL;
m_pLastActivePanel = NULL;
g_lastPanel = NULL;
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
SetScheme(scheme);
SetProportional( true );
m_pAnimController = new vgui::AnimationController(this);
// create our animation controller
m_pAnimController->SetScheme(scheme);
m_pAnimController->SetProportional(true);
// Attempt to load all hud animations
if ( LoadHudAnimations() == false )
{
// Fall back to just the main
if ( m_pAnimController->SetScriptFile( GetVPanel(), "scripts/HudAnimations.txt", true ) == false )
{
Assert(0);
}
}
m_OldSize[ 0 ] = m_OldSize[ 1 ] = -1;
}
//-----------------------------------------------------------------------------
// Purpose: Updates hud to handle the new screen size
//-----------------------------------------------------------------------------
void CBaseViewport::OnScreenSizeChanged(int iOldWide, int iOldTall)
{
BaseClass::OnScreenSizeChanged(iOldWide, iOldTall);
IViewPortPanel* pSpecGuiPanel = FindPanelByName(PANEL_SPECGUI);
bool bSpecGuiWasVisible = pSpecGuiPanel && pSpecGuiPanel->IsVisible();
// reload the script file, so the screen positions in it are correct for the new resolution
ReloadScheme( NULL );
// recreate all the default panels
RemoveAllPanels();
#ifndef _XBOX
m_pBackGround = new CBackGroundPanel( NULL );
m_pBackGround->SetZPos( -20 ); // send it to the back
m_pBackGround->SetVisible( false );
#endif
CreateDefaultPanels();
#ifndef _XBOX
vgui::ipanel()->MoveToBack( m_pBackGround->GetVPanel() ); // really send it to the back
#endif
// hide all panels when reconnecting
ShowPanel( PANEL_ALL, false );
// re-enable the spectator gui if it was previously visible
if ( bSpecGuiWasVisible )
{
ShowPanel( PANEL_SPECGUI, true );
}
}
void CBaseViewport::CreateDefaultPanels( void )
{
#ifndef _XBOX
AddNewPanel( CreatePanelByName( PANEL_SCOREBOARD ), "PANEL_SCOREBOARD" );
AddNewPanel( CreatePanelByName( PANEL_INFO ), "PANEL_INFO" );
AddNewPanel( CreatePanelByName( PANEL_SPECGUI ), "PANEL_SPECGUI" );
AddNewPanel( CreatePanelByName( PANEL_SPECMENU ), "PANEL_SPECMENU" );
AddNewPanel( CreatePanelByName( PANEL_NAV_PROGRESS ), "PANEL_NAV_PROGRESS" );
// AddNewPanel( CreatePanelByName( PANEL_TEAM ), "PANEL_TEAM" );
// AddNewPanel( CreatePanelByName( PANEL_CLASS ), "PANEL_CLASS" );
// AddNewPanel( CreatePanelByName( PANEL_BUY ), "PANEL_BUY" );
#endif
}
void CBaseViewport::UpdateAllPanels( void )
{
int count = m_Panels.Count();
for (int i=0; i< count; i++ )
{
IViewPortPanel *p = m_Panels[i];
if ( p->IsVisible() )
{
p->Update();
}
}
}
IViewPortPanel* CBaseViewport::CreatePanelByName(const char *szPanelName)
{
IViewPortPanel* newpanel = NULL;
#ifndef _XBOX
if ( Q_strcmp(PANEL_SCOREBOARD, szPanelName) == 0 )
{
newpanel = new CClientScoreBoardDialog( this );
}
else if ( Q_strcmp(PANEL_INFO, szPanelName) == 0 )
{
newpanel = new CTextWindow( this );
}
/* else if ( Q_strcmp(PANEL_OVERVIEW, szPanelName) == 0 )
{
newpanel = new CMapOverview( this );
}
*/
else if ( Q_strcmp(PANEL_TEAM, szPanelName) == 0 )
{
newpanel = new CTeamMenu( this );
}
else if ( Q_strcmp(PANEL_SPECMENU, szPanelName) == 0 )
{
newpanel = new CSpectatorMenu( this );
}
else if ( Q_strcmp(PANEL_SPECGUI, szPanelName) == 0 )
{
newpanel = new CSpectatorGUI( this );
}
#if !defined( TF_CLIENT_DLL )
else if ( Q_strcmp(PANEL_NAV_PROGRESS, szPanelName) == 0 )
{
newpanel = new CNavProgress( this );
}
#endif // TF_CLIENT_DLL
#endif
if ( Q_strcmp(PANEL_COMMENTARY_MODELVIEWER, szPanelName) == 0 )
{
newpanel = new CCommentaryModelViewer( this );
}
return newpanel;
}
bool CBaseViewport::AddNewPanel( IViewPortPanel* pPanel, char const *pchDebugName )
{
if ( !pPanel )
{
DevMsg("CBaseViewport::AddNewPanel(%s): NULL panel.\n", pchDebugName );
return false;
}
// we created a new panel, initialize it
if ( FindPanelByName( pPanel->GetName() ) != NULL )
{
DevMsg("CBaseViewport::AddNewPanel: panel with name '%s' already exists.\n", pPanel->GetName() );
return false;
}
m_Panels.AddToTail( pPanel );
pPanel->SetParent( GetVPanel() );
return true;
}
IViewPortPanel* CBaseViewport::FindPanelByName(const char *szPanelName)
{
int count = m_Panels.Count();
for (int i=0; i< count; i++ )
{
if ( Q_strcmp(m_Panels[i]->GetName(), szPanelName) == 0 )
return m_Panels[i];
}
return NULL;
}
void CBaseViewport::PostMessageToPanel( IViewPortPanel* pPanel, KeyValues *pKeyValues )
{
PostMessage( pPanel->GetVPanel(), pKeyValues );
}
void CBaseViewport::PostMessageToPanel( const char *pName, KeyValues *pKeyValues )
{
if ( Q_strcmp( pName, PANEL_ALL ) == 0 )
{
for (int i=0; i< m_Panels.Count(); i++ )
{
PostMessageToPanel( m_Panels[i], pKeyValues );
}
return;
}
IViewPortPanel * panel = NULL;
if ( Q_strcmp( pName, PANEL_ACTIVE ) == 0 )
{
panel = m_pActivePanel;
}
else
{
panel = FindPanelByName( pName );
}
if ( !panel )
return;
PostMessageToPanel( panel, pKeyValues );
}
void CBaseViewport::ShowPanel( const char *pName, bool state )
{
if ( Q_strcmp( pName, PANEL_ALL ) == 0 )
{
for (int i=0; i< m_Panels.Count(); i++ )
{
ShowPanel( m_Panels[i], state );
}
return;
}
IViewPortPanel * panel = NULL;
if ( Q_strcmp( pName, PANEL_ACTIVE ) == 0 )
{
panel = m_pActivePanel;
}
else
{
panel = FindPanelByName( pName );
}
if ( !panel )
return;
ShowPanel( panel, state );
}
void CBaseViewport::ShowPanel( IViewPortPanel* pPanel, bool state )
{
if ( state )
{
// if this is an 'active' panel, deactivate old active panel
if ( pPanel->HasInputElements() )
{
// don't show input panels during normal demo playback
#if defined( REPLAY_ENABLED )
if ( engine->IsPlayingDemo() && !engine->IsHLTV() && !g_pEngineClientReplay->IsPlayingReplayDemo() )
#else
if ( engine->IsPlayingDemo() && !engine->IsHLTV() )
#endif
return;
if ( (m_pActivePanel != NULL) && (m_pActivePanel != pPanel) && (m_pActivePanel->IsVisible()) )
{
// store a pointer to the currently active panel
// so we can restore it later
m_pLastActivePanel = m_pActivePanel;
m_pActivePanel->ShowPanel( false );
}
m_pActivePanel = pPanel;
}
}
else
{
// if this is our current active panel
// update m_pActivePanel pointer
if ( m_pActivePanel == pPanel )
{
m_pActivePanel = NULL;
}
// restore the previous active panel if it exists
if( m_pLastActivePanel )
{
m_pActivePanel = m_pLastActivePanel;
m_pLastActivePanel = NULL;
m_pActivePanel->ShowPanel( true );
}
}
// just show/hide panel
pPanel->ShowPanel( state );
UpdateAllPanels(); // let other panels rearrange
}
IViewPortPanel* CBaseViewport::GetActivePanel( void )
{
return m_pActivePanel;
}
void CBaseViewport::RemoveAllPanels( void)
{
g_lastPanel = NULL;
for ( int i=0; i < m_Panels.Count(); i++ )
{
vgui::VPANEL vPanel = m_Panels[i]->GetVPanel();
vgui::ipanel()->DeletePanel( vPanel );
}
#ifndef _XBOX
if ( m_pBackGround )
{
m_pBackGround->MarkForDeletion();
m_pBackGround = NULL;
}
#endif
m_Panels.Purge();
m_pActivePanel = NULL;
m_pLastActivePanel = NULL;
}
CBaseViewport::~CBaseViewport()
{
m_bInitialized = false;
#ifndef _XBOX
if ( !m_bHasParent && m_pBackGround )
{
m_pBackGround->MarkForDeletion();
}
m_pBackGround = NULL;
#endif
RemoveAllPanels();
gameeventmanager->RemoveListener( this );
}
//-----------------------------------------------------------------------------
// Purpose: called when the VGUI subsystem starts up
// Creates the sub panels and initialises them
//-----------------------------------------------------------------------------
void CBaseViewport::Start( IGameUIFuncs *pGameUIFuncs, IGameEventManager2 * pGameEventManager )
{
m_GameuiFuncs = pGameUIFuncs;
m_GameEventManager = pGameEventManager;
#ifndef _XBOX
m_pBackGround = new CBackGroundPanel( NULL );
m_pBackGround->SetZPos( -20 ); // send it to the back
m_pBackGround->SetVisible( false );
#endif
CreateDefaultPanels();
m_GameEventManager->AddListener( this, "game_newmap", false );
m_bInitialized = true;
}
/*
//-----------------------------------------------------------------------------
// Purpose: Updates the spectator panel with new player info
//-----------------------------------------------------------------------------
void CBaseViewport::UpdateSpectatorPanel()
{
char bottomText[128];
int player = -1;
const char *name;
Q_snprintf(bottomText,sizeof( bottomText ), "#Spec_Mode%d", m_pClientDllInterface->SpectatorMode() );
m_pClientDllInterface->CheckSettings();
// check if we're locked onto a target, show the player's name
if ( (m_pClientDllInterface->SpectatorTarget() > 0) && (m_pClientDllInterface->SpectatorTarget() <= m_pClientDllInterface->GetMaxPlayers()) && (m_pClientDllInterface->SpectatorMode() != OBS_ROAMING) )
{
player = m_pClientDllInterface->SpectatorTarget();
}
// special case in free map and inset off, don't show names
if ( ((m_pClientDllInterface->SpectatorMode() == OBS_MAP_FREE) && !m_pClientDllInterface->PipInsetOff()) || player == -1 )
name = NULL;
else
name = m_pClientDllInterface->GetPlayerInfo(player).name;
// create player & health string
if ( player && name )
{
Q_strncpy( bottomText, name, sizeof( bottomText ) );
}
char szMapName[64];
Q_FileBase( const_cast<char *>(m_pClientDllInterface->GetLevelName()), szMapName );
m_pSpectatorGUI->Update(bottomText, player, m_pClientDllInterface->SpectatorMode(), m_pClientDllInterface->IsSpectateOnly(), m_pClientDllInterface->SpectatorNumber(), szMapName );
m_pSpectatorGUI->UpdateSpectatorPlayerList();
} */
// Return TRUE if the HUD's allowed to print text messages
bool CBaseViewport::AllowedToPrintText( void )
{
/* int iId = GetCurrentMenuID();
if ( iId == MENU_TEAM || iId == MENU_CLASS || iId == MENU_INTRO || iId == MENU_CLASSHELP )
return false; */
// TODO ask every aktive elemet if it allows to draw text while visible
return ( m_pActivePanel == NULL);
}
void CBaseViewport::OnThink()
{
// Clear our active panel pointer if the panel has made
// itself invisible. Need this so we don't bring up dead panels
// if they are stored as the last active panel
if( m_pActivePanel && !m_pActivePanel->IsVisible() )
{
if( m_pLastActivePanel )
{
m_pActivePanel = m_pLastActivePanel;
ShowPanel( m_pActivePanel, true );
m_pLastActivePanel = NULL;
}
else
m_pActivePanel = NULL;
}
m_pAnimController->UpdateAnimations( gpGlobals->curtime );
// check the auto-reload cvar
m_pAnimController->SetAutoReloadScript(hud_autoreloadscript.GetBool());
int count = m_Panels.Count();
for (int i=0; i< count; i++ )
{
IViewPortPanel *panel = m_Panels[i];
if ( panel->NeedsUpdate() && panel->IsVisible() )
{
panel->Update();
}
}
int w, h;
vgui::ipanel()->GetSize( enginevgui->GetPanel( PANEL_CLIENTDLL ), w, h );
if ( m_OldSize[ 0 ] != w || m_OldSize[ 1 ] != h )
{
m_OldSize[ 0 ] = w;
m_OldSize[ 1 ] = h;
g_pClientMode->Layout();
}
BaseClass::OnThink();
}
//-----------------------------------------------------------------------------
// Purpose: Sets the parent for each panel to use
//-----------------------------------------------------------------------------
void CBaseViewport::SetParent(vgui::VPANEL parent)
{
EditablePanel::SetParent( parent );
// force ourselves to be proportional - when we set our parent above, if our new
// parent happened to be non-proportional (such as the vgui root panel), we got
// slammed to be nonproportional
EditablePanel::SetProportional( true );
#ifndef _XBOX
m_pBackGround->SetParent( (vgui::VPANEL)parent );
#endif
// set proportionality on animation controller
m_pAnimController->SetProportional( true );
m_bHasParent = (parent != 0);
}
//-----------------------------------------------------------------------------
// Purpose: called when the engine shows the base client VGUI panel (i.e when entering a new level or exiting GameUI )
//-----------------------------------------------------------------------------
void CBaseViewport::ActivateClientUI()
{
}
//-----------------------------------------------------------------------------
// Purpose: called when the engine hides the base client VGUI panel (i.e when the GameUI is comming up )
//-----------------------------------------------------------------------------
void CBaseViewport::HideClientUI()
{
}
//-----------------------------------------------------------------------------
// Purpose: passes death msgs to the scoreboard to display specially
//-----------------------------------------------------------------------------
void CBaseViewport::FireGameEvent( IGameEvent * event)
{
const char * type = event->GetName();
if ( Q_strcmp(type, "game_newmap") == 0 )
{
// hide all panels when reconnecting
ShowPanel( PANEL_ALL, false );
if ( engine->IsHLTV() )
{
ShowPanel( PANEL_SPECGUI, true );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseViewport::ReloadScheme(const char *fromFile)
{
CETWScope timer( "CBaseViewport::ReloadScheme" );
// See if scheme should change
if ( fromFile != NULL )
{
// "resource/ClientScheme.res"
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), fromFile, "HudScheme" );
SetScheme(scheme);
SetProportional( true );
m_pAnimController->SetScheme(scheme);
}
// Force a reload
if ( LoadHudAnimations() == false )
{
// Fall back to just the main
if ( m_pAnimController->SetScriptFile( GetVPanel(), "scripts/HudAnimations.txt", true ) == false )
{
Assert(0);
}
}
SetProportional( true );
KeyValuesAD pConditions( "conditions" );
g_pClientMode->ComputeVguiResConditions( pConditions );
// reload the .res file from disk
LoadControlSettings( "scripts/HudLayout.res", NULL, NULL, pConditions );
gHUD.RefreshHudTextures();
InvalidateLayout( true, true );
// reset the hud
gHUD.ResetHUD();
}
int CBaseViewport::GetDeathMessageStartHeight( void )
{
return YRES(2);
}
void CBaseViewport::Paint()
{
if ( cl_leveloverviewmarker.GetInt() > 0 )
{
int size = cl_leveloverviewmarker.GetInt();
// draw a 1024x1024 pixel box
vgui::surface()->DrawSetColor( 255, 0, 0, 255 );
vgui::surface()->DrawLine( size, 0, size, size );
vgui::surface()->DrawLine( 0, size, size, size );
}
}

View File

@ -0,0 +1,148 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TEAMFORTRESSVIEWPORT_H
#define TEAMFORTRESSVIEWPORT_H
// viewport interface for the rest of the dll
#include <game/client/iviewport.h>
#include <utlqueue.h> // a vector based queue template to manage our VGUI menu queue
#include <vgui_controls/Frame.h>
#include "vguitextwindow.h"
#include "vgui/ISurface.h"
#include "commandmenu.h"
#include <igameevents.h>
using namespace vgui;
class IBaseFileSystem;
class IGameUIFuncs;
class IGameEventManager;
//==============================================================================
class CBaseViewport : public vgui::EditablePanel, public IViewPort, public IGameEventListener2
{
DECLARE_CLASS_SIMPLE( CBaseViewport, vgui::EditablePanel );
public:
CBaseViewport();
virtual ~CBaseViewport();
virtual IViewPortPanel* CreatePanelByName(const char *szPanelName);
virtual IViewPortPanel* FindPanelByName(const char *szPanelName);
virtual IViewPortPanel* GetActivePanel( void );
virtual void RemoveAllPanels( void);
virtual void ShowPanel( const char *pName, bool state );
virtual void ShowPanel( IViewPortPanel* pPanel, bool state );
virtual bool AddNewPanel( IViewPortPanel* pPanel, char const *pchDebugName );
virtual void CreateDefaultPanels( void );
virtual void UpdateAllPanels( void );
virtual void PostMessageToPanel( const char *pName, KeyValues *pKeyValues );
virtual void Start( IGameUIFuncs *pGameUIFuncs, IGameEventManager2 *pGameEventManager );
virtual void SetParent(vgui::VPANEL parent);
virtual void ReloadScheme(const char *fromFile);
virtual void ActivateClientUI();
virtual void HideClientUI();
virtual bool AllowedToPrintText( void );
#ifndef _XBOX
virtual int GetViewPortScheme() { return m_pBackGround->GetScheme(); }
virtual VPANEL GetViewPortPanel() { return m_pBackGround->GetVParent(); }
#endif
virtual AnimationController *GetAnimationController() { return m_pAnimController; }
virtual void ShowBackGround(bool bShow)
{
#ifndef _XBOX
m_pBackGround->SetVisible( bShow );
#endif
}
virtual int GetDeathMessageStartHeight( void );
// virtual void ChatInputPosition( int *x, int *y );
public: // IGameEventListener:
virtual void FireGameEvent( IGameEvent * event);
protected:
bool LoadHudAnimations( void );
#ifndef _XBOX
class CBackGroundPanel : public vgui::Frame
{
private:
typedef vgui::Frame BaseClass;
public:
CBackGroundPanel( vgui::Panel *parent) : Frame( parent, "ViewPortBackGround" )
{
SetScheme("ClientScheme");
SetTitleBarVisible( false );
SetMoveable(false);
SetSizeable(false);
SetProportional(true);
}
private:
virtual void ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetBgColor(pScheme->GetColor("ViewportBG", Color( 0,0,0,0 ) ));
}
virtual void PerformLayout()
{
int w,h;
GetHudSize(w, h);
// fill the screen
SetBounds(0,0,w,h);
BaseClass::PerformLayout();
}
virtual void OnMousePressed(MouseCode code) { }// don't respond to mouse clicks
virtual vgui::VPANEL IsWithinTraverse( int x, int y, bool traversePopups )
{
return ( vgui::VPANEL )0;
}
};
#endif
protected:
virtual void Paint();
virtual void OnThink();
virtual void OnScreenSizeChanged(int iOldWide, int iOldTall);
void PostMessageToPanel( IViewPortPanel* pPanel, KeyValues *pKeyValues );
protected:
IGameUIFuncs* m_GameuiFuncs; // for key binding details
IGameEventManager2* m_GameEventManager;
#ifndef _XBOX
CBackGroundPanel *m_pBackGround;
#endif
CUtlVector<IViewPortPanel*> m_Panels;
bool m_bHasParent; // Used to track if child windows have parents or not.
bool m_bInitialized;
IViewPortPanel *m_pActivePanel;
IViewPortPanel *m_pLastActivePanel;
vgui::HCursor m_hCursorNone;
vgui::AnimationController *m_pAnimController;
int m_OldSize[2];
};
#endif

View File

@ -0,0 +1,150 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "buymenu.h"
#include "buysubmenu.h"
using namespace vgui;
#include "mouseoverpanelbutton.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CBuyMenu::CBuyMenu(IViewPort *pViewPort) : WizardPanel( NULL, PANEL_BUY )
{
SetScheme("ClientScheme");
SetTitle( "#Cstrike_Buy_Menu", true);
SetMoveable(false);
SetSizeable(false);
SetProportional(true);
// hide the system buttons
SetTitleBarVisible( false );
SetAutoDelete( false ); // we reuse this panel, don't let WizardPanel delete us
LoadControlSettings( "Resource/UI/BuyMenu.res" );
ShowButtons( false );
m_pViewPort = pViewPort;
m_pMainMenu = new CBuySubMenu( this, "mainmenu" );
m_pMainMenu->LoadControlSettings( "Resource/UI/MainBuyMenu.res" );
m_pMainMenu->SetVisible( false );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CBuyMenu::~CBuyMenu()
{
if ( m_pMainMenu )
m_pMainMenu->DeleteSubPanels(); //?
}
//-----------------------------------------------------------------------------
// Purpose: shows/hides the buy menu
//-----------------------------------------------------------------------------
void CBuyMenu::ShowPanel(bool bShow)
{
if ( BaseClass::IsVisible() == bShow )
return;
if ( bShow )
{
Update();
Run( m_pMainMenu );
SetMouseInputEnabled( true );
engine->ClientCmd_Unrestricted( "gameui_preventescapetoshow\n" );
}
else
{
engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" );
SetVisible( false );
SetMouseInputEnabled( false );
}
m_pViewPort->ShowBackGround( bShow );
}
void CBuyMenu::Update()
{
//Don't need to do anything, but do need to implement this function as base is pure virtual
NULL;
}
void CBuyMenu::OnClose()
{
engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" );
BaseClass::OnClose();
ResetHistory();
}
void CBuyMenu::OnKeyCodePressed( vgui::KeyCode code )
{
int nDir = 0;
switch ( code )
{
case KEY_XBUTTON_UP:
case KEY_XSTICK1_UP:
case KEY_XSTICK2_UP:
case KEY_UP:
nDir = -1;
break;
case KEY_XBUTTON_DOWN:
case KEY_XSTICK1_DOWN:
case KEY_XSTICK2_DOWN:
case KEY_DOWN:
nDir = 1;
break;
}
if ( nDir != 0 )
{
Panel *pSubPanel = ( GetCurrentSubPanel() ? GetCurrentSubPanel() : m_pMainMenu );
CUtlSortVector< SortedPanel_t, CSortedPanelYLess > vecSortedButtons;
VguiPanelGetSortedChildButtonList( pSubPanel, (void*)&vecSortedButtons, "&", 0 );
if ( VguiPanelNavigateSortedChildButtonList( (void*)&vecSortedButtons, nDir ) != -1 )
{
// Handled!
return;
}
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}
void CBuyMenu::OnKeyCodeTyped( KeyCode code )
{
if ( code == KEY_ESCAPE )
{
OnClose();
}
else
{
BaseClass::OnKeyCodeTyped( code );
}
}

View File

@ -0,0 +1,66 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BUYMENU_H
#define BUYMENU_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/WizardPanel.h>
#include <game/client/iviewport.h>
#include "vgui/KeyCode.h"
class CBuySubMenu;
namespace vgui
{
class Panel;
}
//-----------------------------------------------------------------------------
// Purpose: Draws the class menu
//-----------------------------------------------------------------------------
class CBuyMenu : public vgui::WizardPanel, public IViewPortPanel
{
private:
DECLARE_CLASS_SIMPLE( CBuyMenu, vgui::WizardPanel );
public:
CBuyMenu(IViewPort *pViewPort);
~CBuyMenu();
virtual const char *GetName( void ) { return PANEL_BUY; }
virtual void SetData(KeyValues *data) {};
virtual void Reset() {};
virtual void Update();
virtual bool NeedsUpdate( void ) { return false; }
virtual bool HasInputElements( void ) { return true; }
virtual void ShowPanel( bool bShow );
// 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 void OnKeyCodePressed( vgui::KeyCode code );
virtual void OnKeyCodeTyped( vgui::KeyCode code );
public:
virtual void OnClose();
protected:
CBuySubMenu *m_pMainMenu;
IViewPort *m_pViewPort;
int m_iTeam;
int m_iClass;
};
#endif // BUYMENU_H

View File

@ -0,0 +1,171 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "buysubmenu.h"
#include <KeyValues.h>
#include <vgui_controls/WizardPanel.h>
#include <filesystem.h>
#include <game/client/iviewport.h>
#include <cdll_client_int.h>
#include "mouseoverpanelbutton.h"
// #include "cs_gamerules.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CBuySubMenu::CBuySubMenu(vgui::Panel *parent, const char *name) : WizardSubPanel(parent, name)
{
m_NextPanel = NULL;
m_pFirstButton = NULL;
SetProportional(true);
m_pPanel = new EditablePanel( this, "ItemInfo" );// info window about these items
m_pPanel->SetProportional( true );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CBuySubMenu::~CBuySubMenu()
{
}
//-----------------------------------------------------------------------------
// Purpose: magic override to allow vgui to create mouse over buttons for us
//-----------------------------------------------------------------------------
Panel *CBuySubMenu::CreateControlByName( const char *controlName )
{
if( !Q_stricmp( "MouseOverPanelButton", controlName ) )
{
MouseOverPanelButton *newButton = CreateNewMouseOverPanelButton( m_pPanel );
if( !m_pFirstButton )
{
m_pFirstButton = newButton;
}
return newButton;
}
else
{
return BaseClass::CreateControlByName( controlName );
}
}
//-----------------------------------------------------------------------------
// Purpose: Make the first buttons page get displayed when the menu becomes visible
//-----------------------------------------------------------------------------
void CBuySubMenu::SetVisible( bool state )
{
BaseClass::SetVisible( state );
for( int i = 0; i< GetChildCount(); i++ ) // get all the buy buttons to performlayout
{
MouseOverPanelButton *buyButton = dynamic_cast<MouseOverPanelButton *>(GetChild(i));
if ( buyButton )
{
if( buyButton == m_pFirstButton && state == true )
buyButton->ShowPage();
else
buyButton->HidePage();
buyButton->InvalidateLayout();
}
}
}
CBuySubMenu* CBuySubMenu::CreateNewSubMenu()
{
return new CBuySubMenu( this );
}
MouseOverPanelButton* CBuySubMenu::CreateNewMouseOverPanelButton(EditablePanel *panel)
{
return new MouseOverPanelButton(this, NULL, panel);
}
//-----------------------------------------------------------------------------
// Purpose: Called when the user picks a class
//-----------------------------------------------------------------------------
void CBuySubMenu::OnCommand( const char *command)
{
if ( Q_strstr( command, ".res" ) ) // if its a .res file then its a new menu
{
int i;
// check the cache
for ( i = 0; i < m_SubMenus.Count(); i++ )
{
if ( !Q_stricmp( m_SubMenus[i].filename, command ) )
{
m_NextPanel = m_SubMenus[i].panel;
Assert( m_NextPanel );
m_NextPanel->InvalidateLayout(); // force it to reset it prices
break;
}
}
if ( i == m_SubMenus.Count() )
{
// not there, add a new entry
SubMenuEntry_t newEntry;
memset( &newEntry, 0x0, sizeof( newEntry ) );
CBuySubMenu *newMenu = CreateNewSubMenu();
newMenu->LoadControlSettings( command );
m_NextPanel = newMenu;
Q_strncpy( newEntry.filename, command, sizeof( newEntry.filename ) );
newEntry.panel = newMenu;
m_SubMenus.AddToTail( newEntry );
}
GetWizardPanel()->OnNextButton();
}
else
{
GetWizardPanel()->Close();
gViewPortInterface->ShowBackGround( false );
if ( Q_stricmp( command, "vguicancel" ) != 0 )
engine->ClientCmd( command );
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: Causes the panel to delete itself when it closes
//-----------------------------------------------------------------------------
void CBuySubMenu::DeleteSubPanels()
{
if ( m_NextPanel )
{
m_NextPanel->SetVisible( false );
m_NextPanel = NULL;
}
m_pFirstButton = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: return the next panel to show
//-----------------------------------------------------------------------------
vgui::WizardSubPanel *CBuySubMenu::GetNextSubPanel()
{
return m_NextPanel;
}

View File

@ -0,0 +1,59 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BUYSUBMENU_H
#define BUYSUBMENU_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/WizardSubPanel.h>
#include <vgui_controls/Button.h>
#include <utlvector.h>
#include "mouseoverpanelbutton.h"
class CBuyMenu;
//-----------------------------------------------------------------------------
// Purpose: Draws the class menu
//-----------------------------------------------------------------------------
class CBuySubMenu : public vgui::WizardSubPanel
{
private:
DECLARE_CLASS_SIMPLE( CBuySubMenu, vgui::WizardSubPanel );
public:
CBuySubMenu(vgui::Panel *parent,const char *name = "BuySubMenu");
~CBuySubMenu();
virtual void SetVisible( bool state );
virtual void DeleteSubPanels();
protected:
// command callbacks
virtual void OnCommand( const char *command );
virtual vgui::WizardSubPanel *GetNextSubPanel(); // this is the last menu in the list
virtual vgui::Panel *CreateControlByName(const char *controlName);
virtual CBuySubMenu* CreateNewSubMenu();
virtual MouseOverPanelButton* CreateNewMouseOverPanelButton(vgui::EditablePanel *panel);
typedef struct
{
char filename[_MAX_PATH];
CBuySubMenu *panel;
} SubMenuEntry_t;
vgui::EditablePanel *m_pPanel;
MouseOverPanelButton *m_pFirstButton;
CUtlVector<SubMenuEntry_t> m_SubMenus; // a cache of buy submenus, so we don't need to construct them each time
vgui::WizardSubPanel *m_NextPanel;
};
#endif // BUYSUBMENU_H

View File

@ -0,0 +1,316 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include <stdio.h>
#include <cdll_client_int.h>
#include "classmenu.h"
#include <vgui/IScheme.h>
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <KeyValues.h>
#include <vgui_controls/ImageList.h>
#include <filesystem.h>
#include <vgui_controls/TextEntry.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/Panel.h>
#include "cdll_util.h"
#include "IGameUIFuncs.h" // for key bindings
#ifndef _XBOX
extern IGameUIFuncs *gameuifuncs; // for key binding details
#endif
#include <game/client/iviewport.h>
#include <stdlib.h> // MAX_PATH define
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
#ifdef TF_CLIENT_DLL
#define HUD_CLASSAUTOKILL_FLAGS ( FCVAR_CLIENTDLL | FCVAR_ARCHIVE | FCVAR_USERINFO )
#else
#define HUD_CLASSAUTOKILL_FLAGS ( FCVAR_CLIENTDLL | FCVAR_ARCHIVE )
#endif // !TF_CLIENT_DLL
ConVar hud_classautokill( "hud_classautokill", "1", HUD_CLASSAUTOKILL_FLAGS, "Automatically kill player after choosing a new playerclass." );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CClassMenu::CClassMenu(IViewPort *pViewPort) : Frame(NULL, PANEL_CLASS)
{
m_pViewPort = pViewPort;
m_iScoreBoardKey = BUTTON_CODE_INVALID; // this is looked up in Activate()
m_iTeam = 0;
// initialize dialog
SetTitle("", true);
// load the new scheme early!!
SetScheme("ClientScheme");
SetMoveable(false);
SetSizeable(false);
// hide the system buttons
SetTitleBarVisible( false );
SetProportional(true);
// info window about this class
m_pPanel = new EditablePanel( this, "ClassInfo" );
LoadControlSettings( "Resource/UI/ClassMenu.res" );
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CClassMenu::CClassMenu(IViewPort *pViewPort, const char *panelName) : Frame(NULL, panelName)
{
m_pViewPort = pViewPort;
m_iScoreBoardKey = BUTTON_CODE_INVALID; // this is looked up in Activate()
m_iTeam = 0;
// initialize dialog
SetTitle("", true);
// load the new scheme early!!
SetScheme("ClientScheme");
SetMoveable(false);
SetSizeable(false);
// hide the system buttons
SetTitleBarVisible( false );
SetProportional(true);
// info window about this class
m_pPanel = new EditablePanel( this, "ClassInfo" );
// Inheriting classes are responsible for calling LoadControlSettings()!
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CClassMenu::~CClassMenu()
{
}
MouseOverPanelButton* CClassMenu::CreateNewMouseOverPanelButton(EditablePanel *panel)
{
return new MouseOverPanelButton(this, "MouseOverPanelButton", panel);
}
Panel *CClassMenu::CreateControlByName(const char *controlName)
{
if( !Q_stricmp( "MouseOverPanelButton", controlName ) )
{
MouseOverPanelButton *newButton = CreateNewMouseOverPanelButton( m_pPanel );
m_mouseoverButtons.AddToTail( newButton );
return newButton;
}
else
{
return BaseClass::CreateControlByName( controlName );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CClassMenu::Reset()
{
for ( int i = 0 ; i < GetChildCount() ; ++i )
{
// Hide the subpanel for the MouseOverPanelButtons
MouseOverPanelButton *pPanel = dynamic_cast<MouseOverPanelButton *>( GetChild( i ) );
if ( pPanel )
{
pPanel->HidePage();
}
}
// Turn the first button back on again (so we have a default description shown)
Assert( m_mouseoverButtons.Count() );
for ( int i=0; i<m_mouseoverButtons.Count(); ++i )
{
if ( i == 0 )
{
m_mouseoverButtons[i]->ShowPage(); // Show the first page
}
else
{
m_mouseoverButtons[i]->HidePage(); // Hide the rest
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Called when the user picks a class
//-----------------------------------------------------------------------------
void CClassMenu::OnCommand( const char *command )
{
if ( Q_stricmp( command, "vguicancel" ) )
{
engine->ClientCmd( const_cast<char *>( command ) );
#if !defined( CSTRIKE_DLL ) && !defined( TF_CLIENT_DLL )
// They entered a command to change their class, kill them so they spawn with
// the new class right away
if ( hud_classautokill.GetBool() )
{
engine->ClientCmd( "kill" );
}
#endif // !CSTRIKE_DLL && !TF_CLIENT_DLL
}
Close();
gViewPortInterface->ShowBackGround( false );
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose: shows the class menu
//-----------------------------------------------------------------------------
void CClassMenu::ShowPanel(bool bShow)
{
if ( bShow )
{
Activate();
SetMouseInputEnabled( true );
// load a default class page
for ( int i=0; i<m_mouseoverButtons.Count(); ++i )
{
if ( i == 0 )
{
m_mouseoverButtons[i]->ShowPage(); // Show the first page
}
else
{
m_mouseoverButtons[i]->HidePage(); // Hide the rest
}
}
if ( m_iScoreBoardKey == BUTTON_CODE_INVALID )
{
m_iScoreBoardKey = gameuifuncs->GetButtonCodeForBind( "showscores" );
}
}
else
{
SetVisible( false );
SetMouseInputEnabled( false );
}
m_pViewPort->ShowBackGround( bShow );
}
void CClassMenu::SetData(KeyValues *data)
{
m_iTeam = data->GetInt( "team" );
}
//-----------------------------------------------------------------------------
// Purpose: Sets the text of a control by name
//-----------------------------------------------------------------------------
void CClassMenu::SetLabelText(const char *textEntryName, const char *text)
{
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
if (entry)
{
entry->SetText(text);
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets the visibility of a button by name
//-----------------------------------------------------------------------------
void CClassMenu::SetVisibleButton(const char *textEntryName, bool state)
{
Button *entry = dynamic_cast<Button *>(FindChildByName(textEntryName));
if (entry)
{
entry->SetVisible(state);
}
}
void CClassMenu::OnKeyCodePressed(KeyCode code)
{
int nDir = 0;
switch ( code )
{
case KEY_XBUTTON_UP:
case KEY_XSTICK1_UP:
case KEY_XSTICK2_UP:
case KEY_UP:
case KEY_XBUTTON_LEFT:
case KEY_XSTICK1_LEFT:
case KEY_XSTICK2_LEFT:
case KEY_LEFT:
nDir = -1;
break;
case KEY_XBUTTON_DOWN:
case KEY_XSTICK1_DOWN:
case KEY_XSTICK2_DOWN:
case KEY_DOWN:
case KEY_XBUTTON_RIGHT:
case KEY_XSTICK1_RIGHT:
case KEY_XSTICK2_RIGHT:
case KEY_RIGHT:
nDir = 1;
break;
}
if ( m_iScoreBoardKey != BUTTON_CODE_INVALID && m_iScoreBoardKey == code )
{
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, true );
gViewPortInterface->PostMessageToPanel( PANEL_SCOREBOARD, new KeyValues( "PollHideCode", "code", code ) );
}
else if ( nDir != 0 )
{
CUtlSortVector< SortedPanel_t, CSortedPanelYLess > vecSortedButtons;
VguiPanelGetSortedChildButtonList( this, (void*)&vecSortedButtons, "&", 0 );
int nNewArmed = VguiPanelNavigateSortedChildButtonList( (void*)&vecSortedButtons, nDir );
if ( nNewArmed != -1 )
{
// Handled!
if ( nNewArmed < m_mouseoverButtons.Count() )
{
m_mouseoverButtons[ nNewArmed ]->OnCursorEntered();
}
return;
}
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}

View File

@ -0,0 +1,79 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CLASSMENU_H
#define CLASSMENU_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Frame.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/HTML.h>
#include <utlvector.h>
#include <vgui/ILocalize.h>
#include <vgui/KeyCode.h>
#include <game/client/iviewport.h>
#include "mouseoverpanelbutton.h"
namespace vgui
{
class TextEntry;
}
//-----------------------------------------------------------------------------
// Purpose: Draws the class menu
//-----------------------------------------------------------------------------
class CClassMenu : public vgui::Frame, public IViewPortPanel
{
private:
DECLARE_CLASS_SIMPLE( CClassMenu, vgui::Frame );
public:
CClassMenu(IViewPort *pViewPort);
CClassMenu(IViewPort *pViewPort, const char *panelName );
virtual ~CClassMenu();
virtual const char *GetName( void ) { return PANEL_CLASS; }
virtual void SetData(KeyValues *data);
virtual void Reset();
virtual void Update() {};
virtual bool NeedsUpdate( void ) { return false; }
virtual bool HasInputElements( void ) { return true; }
virtual void ShowPanel( bool bShow );
// 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 ); }
protected:
virtual vgui::Panel *CreateControlByName(const char *controlName);
virtual MouseOverPanelButton* CreateNewMouseOverPanelButton(vgui::EditablePanel *panel);
//vgui2 overrides
virtual void OnKeyCodePressed(vgui::KeyCode code);
// helper functions
void SetLabelText(const char *textEntryName, const char *text);
void SetVisibleButton(const char *textEntryName, bool state);
// command callbacks
void OnCommand( const char *command );
IViewPort *m_pViewPort;
ButtonCode_t m_iScoreBoardKey;
int m_iTeam;
vgui::EditablePanel *m_pPanel;
CUtlVector< MouseOverPanelButton * > m_mouseoverButtons;
};
#endif // CLASSMENU_H

View File

@ -0,0 +1,127 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CLIENTSCOREBOARDDIALOG_H
#define CLIENTSCOREBOARDDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/EditablePanel.h>
#include <game/client/iviewport.h>
#include "GameEventListener.h"
#define TYPE_NOTEAM 0 // NOTEAM must be zero :)
#define TYPE_TEAM 1 // a section for a single team
#define TYPE_PLAYERS 2
#define TYPE_SPECTATORS 3 // a section for a spectator group
#define TYPE_BLANK 4
//-----------------------------------------------------------------------------
// Purpose: Game ScoreBoard
//-----------------------------------------------------------------------------
class CClientScoreBoardDialog : public vgui::EditablePanel, public IViewPortPanel, public CGameEventListener
{
private:
DECLARE_CLASS_SIMPLE( CClientScoreBoardDialog, vgui::EditablePanel );
protected:
// column widths at 640
enum { NAME_WIDTH = 160, SCORE_WIDTH = 60, DEATH_WIDTH = 60, PING_WIDTH = 80, VOICE_WIDTH = 0, FRIENDS_WIDTH = 0 };
// total = 340
public:
CClientScoreBoardDialog( IViewPort *pViewPort );
~CClientScoreBoardDialog();
virtual const char *GetName( void ) { return PANEL_SCOREBOARD; }
virtual void SetData(KeyValues *data) {};
virtual void Reset();
virtual void Update();
virtual bool NeedsUpdate( void );
virtual bool HasInputElements( void ) { return true; }
virtual void ShowPanel( bool bShow );
virtual bool ShowAvatars()
{
#ifdef CSS_PERF_TEST
return false;
#endif
return IsPC();
}
// 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 ); }
// IGameEventListener interface:
virtual void FireGameEvent( IGameEvent *event);
virtual void UpdatePlayerAvatar( int playerIndex, KeyValues *kv );
protected:
MESSAGE_FUNC_INT( OnPollHideCode, "PollHideCode", code );
// functions to override
virtual bool GetPlayerScoreInfo(int playerIndex, KeyValues *outPlayerInfo);
virtual void InitScoreboardSections();
virtual void UpdateTeamInfo();
virtual void UpdatePlayerInfo();
virtual void OnThink();
virtual void AddHeader(); // add the start header of the scoreboard
virtual void AddSection(int teamType, int teamNumber); // add a new section header for a team
virtual int GetAdditionalHeight() { return 0; }
// sorts players within a section
static bool StaticPlayerSortFunc(vgui::SectionedListPanel *list, int itemID1, int itemID2);
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void PostApplySchemeSettings( vgui::IScheme *pScheme );
// finds the player in the scoreboard
int FindItemIDForPlayerIndex(int playerIndex);
int m_iNumTeams;
vgui::SectionedListPanel *m_pPlayerList;
int m_iSectionId; // the current section we are entering into
int s_VoiceImage[5];
int TrackerImage;
int m_HLTVSpectators;
int m_ReplaySpectators;
float m_fNextUpdateTime;
void MoveLabelToFront(const char *textEntryName);
void MoveToCenterOfScreen();
vgui::ImageList *m_pImageList;
CUtlMap<CSteamID,int> m_mapAvatarsToImageList;
CPanelAnimationVar( int, m_iAvatarWidth, "avatar_width", "34" ); // Avatar width doesn't scale with resolution
CPanelAnimationVarAliasType( int, m_iNameWidth, "name_width", "136", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iClassWidth, "class_width", "35", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iScoreWidth, "score_width", "35", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iDeathWidth, "death_width", "35", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iPingWidth, "ping_width", "23", "proportional_int" );
private:
int m_iPlayerIndexSymbol;
int m_iDesiredHeight;
IViewPort *m_pViewPort;
ButtonCode_t m_nCloseKey;
// methods
void FillScoreBoard();
};
#endif // CLIENTSCOREBOARDDIALOG_H

View File

@ -0,0 +1,361 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include <cdll_client_int.h>
#include <cdll_util.h>
#include <globalvars_base.h>
#include <icvar.h>
#include <filesystem.h>
#include "commandmenu.h"
#include "vgui_controls/MenuItem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CommandMenu::CommandMenu( Panel *parent, const char *panelName, IViewPort * viewport) : Menu( parent, panelName )
{
if ( !viewport )
return;
m_ViewPort = viewport;
SetVisible( false );
m_CurrentMenu = this;
m_MenuKeys = NULL;
}
bool CommandMenu::LoadFromFile( const char * fileName) // load menu from KeyValues
{
KeyValues * kv = new KeyValues(fileName);
if ( !kv->LoadFromFile( g_pFullFileSystem, fileName, "GAME" ) )
return false;
bool ret = LoadFromKeyValues( kv );
kv->deleteThis();
return ret;
}
CommandMenu::~CommandMenu()
{
ClearMenu();
}
void CommandMenu::OnMessage(const KeyValues *params, VPANEL fromPanel)
{
char text[255];
bool bHandled = false;
KeyValues *param1 = const_cast<KeyValues *>(params);
// toggle attached cvar, if any
Q_strncpy( text, param1->GetString("toggle"), sizeof( text ) );
if ( text[0] )
{
ConVarRef convar( text );
if ( convar.IsValid() )
{
// toggle cvar
if ( convar.GetInt() )
{
convar.SetValue( 0 );
}
else
{
convar.SetValue( 1 );
}
UpdateMenu();
}
else
{
Msg("CommandComboBox::OnMessage: cvar %s not found.\n", param1->GetString("typedata") );
}
bHandled = true;
}
// execute attached command, if any
Q_strncpy( text, param1->GetString("command"), sizeof( text ) );
if ( text[0] )
{
engine->ClientCmd( text );
bHandled = true;
}
// fire custom message, if any
Q_strncpy( text, param1->GetString("custom"), sizeof( text ) );
if ( text[0] )
{
OnCustomItem( param1 ); // let derived class decide what to do
bHandled = true;
}
if ( bHandled )
{
PostMessage( GetParent(), new KeyValues("CommandMenuClosed") );
}
BaseClass::OnMessage( params, fromPanel );
}
void CommandMenu::StartNewSubMenu(KeyValues * params)
{
CommandMenuItem menuitem;
menuitem.menu = m_CurrentMenu;
Menu * menu = new Menu( this, params->GetString("name") ); // create new menu
menuitem.itemnr = m_CurrentMenu->AddCascadingMenuItem( params->GetString("label"), this, menu, params ); // add to current menu as item
m_MenuItems.AddToTail( menuitem ); // add to global list
m_pMenuStack.Push( m_CurrentMenu ); // remember current menu
m_CurrentMenu = menu; // continue adding items in new menu
}
void CommandMenu::FinishSubMenu()
{
m_CurrentMenu = m_pMenuStack.Top(); // get menu one level above
m_pMenuStack.Pop(); // remove it from stack
}
void CommandMenu::AddMenuCommandItem(KeyValues * params)
{
CommandMenuItem menuitem; // create new menuItem
menuitem.menu = m_CurrentMenu; // save the current menu context
menuitem.itemnr = m_CurrentMenu->AddMenuItem( params->GetString("label"), params->MakeCopy(), this, params ); // add it
m_MenuItems.AddToTail( menuitem ); // add to global list
}
void CommandMenu::AddMenuToggleItem(KeyValues * params)
{
CommandMenuItem menuitem; // create new menuItem
menuitem.menu = m_CurrentMenu; // save the current menu context
menuitem.itemnr = m_CurrentMenu->AddCheckableMenuItem( params->GetString("label"), params->MakeCopy(), this, params ); // add it
m_MenuItems.AddToTail( menuitem ); // add to global list
}
void CommandMenu::AddMenuCustomItem(KeyValues * params)
{
CommandMenuItem menuitem; // create new menuItem
menuitem.menu = m_CurrentMenu; // save the current menu context
menuitem.itemnr = AddCustomItem( params, m_CurrentMenu );
m_MenuItems.AddToTail( menuitem ); // add to global list
}
void CommandMenu::ClearMenu()
{
SetVisible( false );
m_pMenuStack.Clear();
m_MenuItems.RemoveAll();
// DeleteAllItems();
MarkForDeletion();
if ( m_MenuKeys )
{
m_MenuKeys->deleteThis();
m_MenuKeys = NULL;
}
}
void CommandMenu::RebuildMenu()
{
if ( !m_MenuKeys )
return;
m_pMenuStack.Clear();
m_MenuItems.RemoveAll();
DeleteAllItems();
LoadFromKeyValues( m_MenuKeys ); // and reload respecting new team, mapname etc.
}
void CommandMenu::UpdateMenu()
{
char text[255];
int num = m_MenuItems.Count();
for (int i=0; i < num; i++)
{
CommandMenuItem menuitem = m_MenuItems.Element(i);
KeyValues * keys = menuitem.menu->GetItemUserData( menuitem.itemnr );
if ( !keys )
continue;
// let custom menu items update themself
Q_strncpy( text, keys->GetString("custom"), sizeof(text) );
if ( text[0] )
{
// let derived class modify the menu item
UpdateCustomItem( keys, menuitem.menu->GetMenuItem(menuitem.itemnr) );
continue;
}
// update toggle buttons
Q_strncpy( text, keys->GetString("toggle"), sizeof(text) );
if ( text[0] )
{
// set toggle state equal to cvar state
ConVarRef convar( text );
if ( convar.IsValid() )
{
menuitem.menu->SetMenuItemChecked( menuitem.itemnr, convar.GetBool() );
}
}
}
}
void CommandMenu::SetVisible(bool state)
{
if ( state && !IsVisible() )
{
UpdateMenu();
}
BaseClass::SetVisible( state );
}
bool CommandMenu::CheckRules(const char *rule, const char *ruledata)
{
if ( !rule || !ruledata )
{
return true; // no rule defined, show item
}
if ( Q_strcmp( rule, "team") == 0 )
{
// if team is same as specified in rule, show item
return ( Q_strcmp( m_CurrentTeam, ruledata ) == 0 );
}
else if ( Q_strcmp( rule, "map") == 0 )
{
// if team is same as specified in rule, show item
return ( Q_strcmp( m_CurrentMap, ruledata ) == 0 );
}
return true;
}
KeyValues * CommandMenu::GetKeyValues()
{
return m_MenuKeys;
}
bool CommandMenu::LoadFromKeyValues( KeyValues * params )
{
if ( !params )
return false;
Q_snprintf( m_CurrentTeam, 4, "%i", GetLocalPlayerTeam() );
Q_FileBase( engine->GetLevelName(), m_CurrentMap, sizeof(m_CurrentMap) );
if ( params != m_MenuKeys )
{
if ( m_MenuKeys )
m_MenuKeys->deleteThis();
m_MenuKeys = params->MakeCopy(); // save keyvalues
}
// iterate through all menu items
KeyValues * subkey = m_MenuKeys->GetFirstSubKey();
while ( subkey )
{
if ( subkey->GetDataType() == KeyValues::TYPE_NONE )
{
if ( !LoadFromKeyValuesInternal( subkey, 0 ) ) // recursive call
return false;
}
subkey = subkey->GetNextKey();
}
UpdateMenu();
return true;
}
bool CommandMenu::LoadFromKeyValuesInternal(KeyValues * key, int depth)
{
char text[255];
KeyValues * subkey = NULL;
if ( depth > 100 )
{
Msg("CommandMenu::LoadFromKeyValueInternal: depth > 100.\n");
return false;
}
Q_strncpy( text, key->GetString("custom"), sizeof(text) ); // get type
if ( text[0] )
{
AddMenuCustomItem( key ); // do whatever custom item wants to
return true;
}
if ( !CheckRules( key->GetString("rule"), key->GetString("ruledata") ) )
{
return true;
}
// rules OK add subkey
Q_strncpy( text, key->GetString("toggle"), sizeof(text) ); // get type
if ( text[0] )
{
AddMenuToggleItem( key );
return true;
}
Q_strncpy( text, key->GetString("command"), sizeof(text) ); // get type
if ( text[0] )
{
AddMenuCommandItem( key );
return true;
}
// not a command, nor a toggle. Must be a submenu:
StartNewSubMenu( key ); // create submenu
// iterate through all subkeys
subkey = key->GetFirstSubKey();
while ( subkey )
{
if ( subkey->GetDataType() == KeyValues::TYPE_NONE )
{
LoadFromKeyValuesInternal( subkey, depth+1 ); // recursive call
}
subkey = subkey->GetNextKey();
}
FinishSubMenu(); // go one level back
return true;
}

View File

@ -0,0 +1,77 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef COMMANDMENU_H
#define COMMANDMENU_H
#include <vgui_controls/Menu.h>
#include <game/client/iviewport.h>
#include <filesystem.h>
#include "utlstack.h"
#include "utlvector.h"
#include <KeyValues.h>
using namespace vgui;
class CommandMenu : public Menu
{
private:
DECLARE_CLASS_SIMPLE( CommandMenu, Menu );
typedef struct
{
Menu * menu;
int itemnr;
} CommandMenuItem;
public:
CommandMenu( Panel *parent, const char *panelName, IViewPort * viewport );
~CommandMenu();
bool LoadFromFile(const char * fileName); // load menu from file (via KeyValues)
void UpdateMenu(); // call to update all menu items, check buttons etc
void RebuildMenu(); // rebuilds menu respecting changed game state (map, team etc)
void ClearMenu(); // destroy menu
public:
// overwrite these in your derived class
// virtual CommandMenu * CommandMenu::Factory(Panel *parent, const char *panelName, IViewPort * viewport = NULL, IFileSystem * pFileSytem = NULL); // overwrite
virtual int AddCustomItem(KeyValues * params, Menu * menu) {return 0;} // return MenuItem nr
virtual void UpdateCustomItem(KeyValues * params, MenuItem * item ) {}; // maybe change your item
virtual void OnCustomItem(KeyValues * params) {}; // a custom item was pressed
virtual bool CheckRules(const char *rule, const char *ruledata); // check a menu item rule
virtual void SetVisible(bool state);
// DON'T touch anything below !
protected:
void OnMessage(const KeyValues *params, VPANEL fromPanel);
void StartNewSubMenu(KeyValues * params);
void FinishSubMenu();
void AddMenuCommandItem(KeyValues * params);
void AddMenuCustomItem(KeyValues * params);
void AddMenuToggleItem(KeyValues * params);
bool LoadFromKeyValuesInternal(KeyValues * key, int depth);
bool LoadFromKeyValues( KeyValues * key); //
KeyValues * GetKeyValues(); // returns keyValues for current menu or NULL
IViewPort * m_ViewPort; // viewport interface
Menu * m_CurrentMenu; // Current menu while building CommandComoboBox
char m_CurrentTeam[4];
char m_CurrentMap[256];
KeyValues* m_MenuKeys;
CUtlStack<vgui::Menu*>m_pMenuStack;
CUtlVector<CommandMenuItem>m_MenuItems;
};
#endif // COMMANDMENU_H

View File

@ -0,0 +1,256 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IMAGE_MOUSE_OVER_BUTTON_H
#define IMAGE_MOUSE_OVER_BUTTON_H
#include "vgui/ISurface.h"
#include "vgui/IScheme.h"
#include "mouseoverpanelbutton.h"
//===============================================
// CImageMouseOverButton - used for class images
//===============================================
template <class T>
class CImageMouseOverButton : public MouseOverButton<T>
{
private:
//DECLARE_CLASS_SIMPLE( CImageMouseOverButton, MouseOverButton );
public:
CImageMouseOverButton( vgui::Panel *parent, const char *panelName, T *templatePanel );
virtual void ApplySettings( KeyValues *inResourceData );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnSizeChanged( int newWide, int newTall );
void RecalculateImageSizes( void );
void SetActiveImage( const char *imagename );
void SetInactiveImage( const char *imagename );
void SetActiveImage( vgui::IImage *image );
void SetInactiveImage( vgui::IImage *image );
public:
virtual void Paint();
virtual void ShowPage( void );
virtual void HidePage( void );
private:
vgui::IImage *m_pActiveImage;
char *m_pszActiveImageName;
vgui::IImage *m_pInactiveImage;
char *m_pszInactiveImageName;
bool m_bScaleImage;
};
template <class T>
CImageMouseOverButton<T>::CImageMouseOverButton( vgui::Panel *parent, const char *panelName, T *templatePanel ) :
MouseOverButton<T>( parent, panelName, templatePanel )
{
m_pszActiveImageName = NULL;
m_pszInactiveImageName = NULL;
m_pActiveImage = NULL;
m_pInactiveImage = NULL;
}
template <class T>
void CImageMouseOverButton<T>::ApplySettings( KeyValues *inResourceData )
{
m_bScaleImage = inResourceData->GetInt( "scaleImage", 0 );
// Active Image
delete [] m_pszActiveImageName;
m_pszActiveImageName = NULL;
const char *activeImageName = inResourceData->GetString( "activeimage", "" );
if ( *activeImageName )
{
this->SetActiveImage( activeImageName );
}
// Inactive Image
delete [] m_pszInactiveImageName;
m_pszInactiveImageName = NULL;
const char *inactiveImageName = inResourceData->GetString( "inactiveimage", "" );
if ( *inactiveImageName )
{
this->SetInactiveImage( inactiveImageName );
}
MouseOverButton<T>::ApplySettings( inResourceData );
this->InvalidateLayout( false, true ); // force applyschemesettings to run
}
template <class T>
void CImageMouseOverButton<T>::ApplySchemeSettings( vgui::IScheme *pScheme )
{
MouseOverButton<T>::ApplySchemeSettings( pScheme );
if ( m_pszActiveImageName && strlen( m_pszActiveImageName ) > 0 )
{
this->SetActiveImage( vgui::scheme()->GetImage( m_pszActiveImageName, m_bScaleImage ) );
}
if ( m_pszInactiveImageName && strlen( m_pszInactiveImageName ) > 0 )
{
this->SetInactiveImage( vgui::scheme()->GetImage( m_pszInactiveImageName, m_bScaleImage ) );
}
vgui::IBorder *pBorder = pScheme->GetBorder( "NoBorder" );
this->SetDefaultBorder( pBorder);
this->SetDepressedBorder( pBorder );
this->SetKeyFocusBorder( pBorder );
Color blank(0,0,0,0);
this->SetDefaultColor( this->GetButtonFgColor(), blank );
this->SetArmedColor( this->GetButtonArmedFgColor(), blank );
this->SetDepressedColor( this->GetButtonDepressedFgColor(), blank );
}
template <class T>
void CImageMouseOverButton<T>::RecalculateImageSizes( void )
{
// Reset our images, which will force them to recalculate their size.
// Necessary for images shared with other scaling buttons.
this->SetActiveImage( m_pActiveImage );
this->SetInactiveImage( m_pInactiveImage );
}
template <class T>
void CImageMouseOverButton<T>::SetActiveImage( const char *imagename )
{
int len = Q_strlen( imagename ) + 1;
m_pszActiveImageName = new char[ len ];
Q_strncpy( m_pszActiveImageName, imagename, len );
}
template <class T>
void CImageMouseOverButton<T>::SetInactiveImage( const char *imagename )
{
int len = Q_strlen( imagename ) + 1;
m_pszInactiveImageName = new char[ len ];
Q_strncpy( m_pszInactiveImageName, imagename, len );
}
template <class T>
void CImageMouseOverButton<T>::SetActiveImage( vgui::IImage *image )
{
m_pActiveImage = image;
if ( m_pActiveImage )
{
int wide, tall;
if ( m_bScaleImage )
{
// scaling, force the image size to be our size
this->GetSize( wide, tall );
m_pActiveImage->SetSize( wide, tall );
}
else
{
// not scaling, so set our size to the image size
m_pActiveImage->GetSize( wide, tall );
this->SetSize( wide, tall );
}
}
this->Repaint();
}
template <class T>
void CImageMouseOverButton<T>::SetInactiveImage( vgui::IImage *image )
{
m_pInactiveImage = image;
if ( m_pInactiveImage )
{
int wide, tall;
if ( m_bScaleImage)
{
// scaling, force the image size to be our size
this->GetSize( wide, tall );
m_pInactiveImage->SetSize( wide, tall );
}
else
{
// not scaling, so set our size to the image size
m_pInactiveImage->GetSize( wide, tall );
this->SetSize( wide, tall );
}
}
this->Repaint();
}
template <class T>
void CImageMouseOverButton<T>::OnSizeChanged( int newWide, int newTall )
{
if ( m_bScaleImage )
{
// scaling, force the image size to be our size
if ( m_pActiveImage )
m_pActiveImage->SetSize( newWide, newTall );
if ( m_pInactiveImage )
m_pInactiveImage->SetSize( newWide, newTall );
}
MouseOverButton<T>::OnSizeChanged( newWide, newTall );
}
template <class T>
void CImageMouseOverButton<T>::Paint()
{
this->SetActiveImage( m_pActiveImage );
this->SetInactiveImage( m_pInactiveImage );
if ( this->IsArmed() )
{
// draw the active image
if ( m_pActiveImage )
{
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
m_pActiveImage->SetPos( 0, 0 );
m_pActiveImage->Paint();
}
}
else
{
// draw the inactive image
if ( m_pInactiveImage )
{
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
m_pInactiveImage->SetPos( 0, 0 );
m_pInactiveImage->Paint();
}
}
MouseOverButton<T>::Paint();
}
template <class T>
void CImageMouseOverButton<T>::ShowPage( void )
{
MouseOverButton<T>::ShowPage();
// send message to parent that we triggered something
this->PostActionSignal( new KeyValues( "ShowPage", "page", this->GetName() ) );
}
template <class T>
void CImageMouseOverButton<T>::HidePage( void )
{
MouseOverButton<T>::HidePage();
}
#endif //IMAGE_MOUSE_OVER_BUTTON_H

View File

@ -0,0 +1,122 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "intromenu.h"
#include <networkstringtabledefs.h>
#include <cdll_client_int.h>
#include <vgui/IScheme.h>
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <filesystem.h>
#include <KeyValues.h>
#include <convar.h>
#include <game/client/iviewport.h>
#include "spectatorgui.h"
#include "gamerules.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CIntroMenu::CIntroMenu( IViewPort *pViewPort ) : Frame( NULL, PANEL_INTRO )
{
// initialize dialog
m_pViewPort = pViewPort;
m_pTitleLabel = NULL;
// load the new scheme early!!
SetScheme( "ClientScheme" );
SetMoveable( false );
SetSizeable( false );
SetProportional( true );
// hide the system buttons
SetTitleBarVisible( false );
Reset();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CIntroMenu::~CIntroMenu()
{
}
//-----------------------------------------------------------------------------
// Purpose: Sets the color of the top and bottom bars
//-----------------------------------------------------------------------------
void CIntroMenu::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings("Resource/UI/IntroMenu.res");
m_pTitleLabel = dynamic_cast<Label *>( FindChildByName( "titlelabel" ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CIntroMenu::Reset( void )
{
Update();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CIntroMenu::Update( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CIntroMenu::OnCommand( const char *command )
{
if ( !Q_strcmp( command, "skip" ) )
{
engine->ClientCmd( "intro_skip" );
m_pViewPort->ShowPanel( this, false );
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CIntroMenu::ShowPanel( bool bShow )
{
if ( BaseClass::IsVisible() == bShow )
return;
m_pViewPort->ShowBackGround( bShow );
if ( bShow )
{
Activate();
if ( GameRules() )
{
SetDialogVariable( "gamemode", g_pVGuiLocalize->Find( GameRules()->GetGameTypeName() ) );
}
SetMouseInputEnabled( true );
}
else
{
SetVisible( false );
SetMouseInputEnabled( false );
}
}

View File

@ -0,0 +1,57 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef INTROMENU_H
#define INTROMENU_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Frame.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/Label.h>
#include <game/client/iviewport.h>
namespace vgui
{
class TextEntry;
}
class CIntroMenu : public vgui::Frame, public IViewPortPanel
{
private:
DECLARE_CLASS_SIMPLE( CIntroMenu, vgui::Frame );
public:
CIntroMenu( IViewPort *pViewPort );
virtual ~CIntroMenu();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual const char *GetName( void ){ return PANEL_INTRO; }
virtual void SetData( KeyValues *data ){ return; }
virtual void Reset();
virtual void Update();
virtual bool NeedsUpdate( void ) { return false; }
virtual bool HasInputElements( void ) { return true; }
virtual void ShowPanel( bool bShow );
// 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 ); }
protected:
// vgui overrides
virtual void OnCommand( const char *command );
IViewPort *m_pViewPort;
vgui::Label *m_pTitleLabel;
};
#endif // INTROMENU_H

View File

@ -0,0 +1,275 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: MiniMap.h: interface for the CMiniMap class.
//
// $NoKeywords: $
//=============================================================================//
#if !defined HLTVPANEL_H
#define HLTVPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Panel.h>
#include <game/client/iviewport.h>
#include "mathlib/vector.h"
#include <igameevents.h>
#include <shareddefs.h>
#include <const.h>
#include "hudelement.h"
class IMapOverviewPanel
{
public:
virtual void SetMode( int mode ) = 0;
virtual int GetMode( void ) = 0;
virtual void FlashEntity( int entityID ) = 0;
virtual void SetPlayerPositions(int index, const Vector &position, const QAngle &angle) = 0;
virtual void SetVisible(bool state) = 0;
virtual float GetZoom( void ) = 0;
virtual vgui::Panel *GetAsPanel() = 0;
virtual bool AllowConCommandsWhileAlive() = 0;
virtual void SetPlayerPreferredMode( int mode ) = 0;
virtual void SetPlayerPreferredViewSize( float viewSize ) = 0;
virtual bool IsVisible() = 0;
virtual void GetBounds(int &x, int &y, int &wide, int &tall) = 0;
virtual float GetFullZoom( void ) = 0;
virtual float GetMapScale( void ) = 0;
};
#define MAX_TRAIL_LENGTH 30
#define OVERVIEW_MAP_SIZE 1024 // an overview map is 1024x1024 pixels
typedef bool ( *FnCustomMapOverviewObjectPaint )( int textureID, Vector pos, float scale, float angle, const char *text, Color *textColor, float status, Color *statusColor );
class CMapOverview : public CHudElement, public vgui::Panel, public IMapOverviewPanel
{
DECLARE_CLASS_SIMPLE( CMapOverview, vgui::Panel );
public:
enum
{
MAP_MODE_OFF = 0, // Totally off
MAP_MODE_INSET, // A little map up in a corner
MAP_MODE_FULL, // Full screen, full map
MAP_MODE_RADAR // In game radar, extra functionality
};
CMapOverview( const char *pElementName );
virtual ~CMapOverview();
virtual bool ShouldDraw( void );
vgui::Panel *GetAsPanel(){ return this; }
virtual bool AllowConCommandsWhileAlive(){return true;}
virtual void SetPlayerPreferredMode( int mode ){}
virtual void SetPlayerPreferredViewSize( float viewSize ){};
protected: // private structures & types
float GetViewAngle( void ); // The angle that determines the viewport twist from map texture to panel drawing.
// list of game events the hLTV takes care of
typedef struct {
int xpos;
int ypos;
} FootStep_t;
typedef struct MapPlayer_s {
int index; // player's index
int userid; // user ID on server
int icon; // players texture icon ID
Color color; // players team color
char name[MAX_PLAYER_NAME_LENGTH];
int team; // N,T,CT
int health; // 0..100, 7 bit
Vector position; // current x,y pos
QAngle angle; // view origin 0..360
Vector2D trail[MAX_TRAIL_LENGTH]; // save 1 footstep each second for 1 minute
} MapPlayer_t;
typedef struct MapObject_s {
int objectID; // unique object ID
int index; // entity index if any
int icon; // players texture icon ID
Color color; // players team color
char name[MAX_PLAYER_NAME_LENGTH]; // show text under icon
Vector position; // current x,y pos
QAngle angle; // view origin 0..360
float endtime; // time stop showing object
float size; // object size
float status; // green status bar [0..1], -1 = disabled
Color statusColor; // color of status bar
int flags; // MAB_OBJECT_*
const char *text; // text to draw underneath the icon
} MapObject_t;
#define MAP_OBJECT_ALIGN_TO_MAP (1<<0)
public: // IViewPortPanel interface:
virtual const char *GetName( void ) { return PANEL_OVERVIEW; }
virtual void SetData(KeyValues *data);
virtual void Reset();
virtual void OnThink();
virtual void Update();
virtual bool NeedsUpdate( void );
virtual bool HasInputElements( void ) { return false; }
virtual void ShowPanel( bool bShow );
virtual void Init( void );
// 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 GetBounds(int &x, int &y, int &wide, int &tall) { BaseClass::GetBounds(x, y, wide, tall); }
virtual void SetParent(vgui::VPANEL parent) { BaseClass::SetParent(parent); }
public: // IGameEventListener
virtual void FireGameEvent( IGameEvent *event);
public: // VGUI overrides
virtual void Paint();
virtual void OnMousePressed( vgui::MouseCode code );
virtual void ApplySchemeSettings(vgui::IScheme *scheme);
virtual void SetVisible(bool state){BaseClass::SetVisible(state);}
public:
virtual float GetZoom( void );
virtual int GetMode( void );
virtual float GetFullZoom( void ){ return m_fFullZoom; }
virtual float GetMapScale( void ){ return m_fMapScale; }
// Player settings:
virtual void ShowPlayerNames(bool state);
virtual void ShowPlayerHealth(bool state);
virtual void ShowPlayerTracks(float seconds);
virtual void SetPlayerPositions(int index, const Vector &position, const QAngle &angle);
// general settings:
virtual void SetMap(const char * map);
virtual void SetTime( float time );
virtual void SetMode( int mode );
virtual bool SetTeamColor(int team, Color color);
virtual void SetFollowAngle(bool state);
virtual void SetFollowEntity(int entindex); // 0 = off
virtual void SetCenter( const Vector2D &mappos);
virtual void SetAngle( float angle);
virtual Vector2D WorldToMap( const Vector &worldpos );
// Object settings
virtual int AddObject( const char *icon, int entity, float timeToLive ); // returns object ID, 0 = no entity, -1 = forever
virtual void SetObjectIcon( int objectID, const char *icon, float size ); // icon world size
virtual void SetObjectText( int objectID, const char *text, Color color ); // text under icon
virtual void SetObjectStatus( int objectID, float value, Color statusColor ); // status bar under icon
virtual void SetObjectPosition( int objectID, const Vector &position, const QAngle &angle ); // world pos/angles
virtual void AddObjectFlags( int objectID, int flags );
virtual void SetObjectFlags( int objectID, int flags );
virtual void RemoveObject( int objectID );
virtual void RemoveObjectByIndex( int index );
virtual void FlashEntity( int entityID ){}
// rules that define if you can see a player on the overview or not
virtual bool CanPlayerBeSeen(MapPlayer_t *player);
/// allows mods to restrict health
virtual bool CanPlayerHealthBeSeen(MapPlayer_t *player);
/// allows mods to restrict names (e.g. CS when mp_playerid is non-zero)
virtual bool CanPlayerNameBeSeen(MapPlayer_t *player);
virtual int GetIconNumberFromTeamNumber( int teamNumber ){return teamNumber;}
protected:
virtual void DrawCamera();
virtual void DrawObjects();
virtual void DrawMapTexture();
virtual void DrawMapPlayers();
virtual void DrawMapPlayerTrails();
virtual void UpdatePlayerTrails();
virtual void ResetRound();
virtual void InitTeamColorsAndIcons();
virtual void UpdateSizeAndPosition();
virtual bool RunHudAnimations(){ return true; }
bool IsInPanel(Vector2D &pos);
MapPlayer_t* GetPlayerByUserID( int userID );
int AddIconTexture(const char *filename);
Vector2D MapToPanel( const Vector2D &mappos );
int GetPixelOffset( float height );
void UpdateFollowEntity();
virtual void UpdatePlayers();
void UpdateObjects(); // objects bound to entities
MapObject_t* FindObjectByID(int objectID);
virtual bool IsRadarLocked() {return false;}
virtual bool DrawIcon( MapObject_t *obj );
/*virtual bool DrawIcon( int textureID,
int offscreenTextureID,
Vector pos,
float scale,
float angle,
int alpha = 255,
const char *text = NULL,
Color *textColor = NULL,
float status = -1,
Color *statusColor = NULL,
int objectType = OBJECT_TYPE_NORMAL );*/
int m_nMode;
Vector2D m_vPosition;
Vector2D m_vSize;
float m_flChangeSpeed;
float m_flIconSize;
IViewPort * m_pViewPort;
MapPlayer_t m_Players[MAX_PLAYERS];
CUtlDict< int, int> m_TextureIDs;
CUtlVector<MapObject_t> m_Objects;
Color m_TeamColors[MAX_TEAMS];
int m_TeamIcons[MAX_TEAMS];
int m_ObjectIcons[64];
int m_ObjectCounterID;
vgui::HFont m_hIconFont;
bool m_bShowNames;
bool m_bShowTrails;
bool m_bShowHealth;
int m_nMapTextureID; // texture id for current overview image
KeyValues * m_MapKeyValues; // keyvalues describing overview parameters
Vector m_MapOrigin; // read from KeyValues files
float m_fMapScale; // origin and scale used when screenshot was made
bool m_bRotateMap; // if true roatate map around 90 degress, so it fits better to 4:3 screen ratio
int m_nFollowEntity;// entity number to follow, 0 = off
CPanelAnimationVar( float, m_fZoom, "zoom", "1.0" ); // current zoom n = overview panel shows 1/n^2 of whole map'
float m_fFullZoom; // best zoom factor for full map view (1.0 is map is a square)
Vector2D m_ViewOrigin; // map coordinates that are in the center of the pverview panel
Vector2D m_MapCenter; // map coordinates that are in the center of the pverview panel
float m_fNextUpdateTime;
float m_fViewAngle; // rotation of overview map
float m_fWorldTime; // current world time
float m_fNextTrailUpdate; // next time to update player trails
float m_fTrailUpdateInterval; // if -1 don't show trails
bool m_bFollowAngle; // if true, map rotates with view angle
};
extern IMapOverviewPanel *g_pMapOverview;
#endif //

View File

@ -0,0 +1,119 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef MOUSEOVERHTMLBUTTON_H
#define MOUSEOVERHTMLBUTTON_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Triggers a new html page when the mouse goes over the button
//-----------------------------------------------------------------------------
class MouseOverHTMLButton : public vgui::Button
{
public:
MouseOverHTMLButton(vgui::Panel *parent, const char *panelName, vgui::HTML *html, const char *page) :
Button( parent, panelName, "MouseOverHTMLButton")
{
m_pHTML = html;
m_iClass = 0;
m_iIndex = -1;
m_bAddShortCut = true;
if ( page )
{
Q_strncpy( m_sPage, page, sizeof( m_sPage ) );
}
else
{
memset(m_sPage, 0x0, sizeof( m_sPage ) );
}
}
void SetClass(int pClass, int index) { m_iClass = pClass; m_iIndex = index;}
int GetClass() { return m_iClass; }
void SetAddHotKey( bool state ) { m_bAddShortCut = state; }
void SetPage( const char *page )
{
if ( page )
{
Q_strncpy( m_sPage, page, sizeof( m_sPage ) );
}
else
{
memset(m_sPage, 0x0, sizeof( m_sPage ) );
}
}
void SetHTML( vgui::HTML *html)
{
m_pHTML = html;
}
private:
virtual void OnCursorEntered()
{
Button::OnCursorEntered();
if ( m_pHTML && strlen(m_sPage) > 0 )
{
m_pHTML->OpenURL(m_sPage);
}
}
virtual void SetText(const char *text)
{
if ( m_iIndex != -1 )
{
wchar_t newText[ 128 ];
wchar_t localizeText[ 128 ];
wchar_t *ansiLocal;
if ( text[0] == '#' && ( ansiLocal = g_pVGuiLocalize->Find( text ) ) )
{
// wcsncpy will crash if ansiLocal is null... *sigh*
wcsncpy(localizeText, ansiLocal, sizeof(localizeText)/sizeof(wchar_t));
}
else
{
g_pVGuiLocalize->ConvertANSIToUnicode( text, localizeText, sizeof( localizeText ) );
}
if ( m_bAddShortCut )
{
#ifdef WIN32
_snwprintf( newText, sizeof( newText )/ sizeof( wchar_t ), L"&%i %s", m_iIndex, localizeText);
#else
_snwprintf( newText, sizeof( newText )/ sizeof( wchar_t ), L"&%i %S", m_iIndex, localizeText);
#endif
}
else
{
memcpy( newText, localizeText, sizeof( newText ) );
}
Button::SetText( newText );
}
else
{
Button::SetText( text );
}
}
vgui::HTML *m_pHTML;
char m_sPage[ 255 ];
int m_iClass;
int m_iIndex;
bool m_bAddShortCut;
};
#endif // MOUSEOVERHTMLBUTTON_H

View File

@ -0,0 +1,186 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef MOUSEOVERPANELBUTTON_H
#define MOUSEOVERPANELBUTTON_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/IScheme.h>
#include <vgui_controls/Button.h>
#include <vgui/KeyCode.h>
#include <filesystem.h>
extern vgui::Panel *g_lastPanel;
extern vgui::Button *g_lastButton;
//-----------------------------------------------------------------------------
// Purpose: Triggers a new panel when the mouse goes over the button
//
// the new panel has the same dimensions as the passed templatePanel and is of
// the same class.
//
// must at least inherit from vgui::EditablePanel to support LoadControlSettings
//-----------------------------------------------------------------------------
template <class T>
class MouseOverButton : public vgui::Button
{
private:
DECLARE_CLASS_SIMPLE( MouseOverButton, vgui::Button );
public:
MouseOverButton(vgui::Panel *parent, const char *panelName, T *templatePanel ) :
Button( parent, panelName, "MouseOverButton")
{
m_pPanel = new T( parent, NULL );
m_pPanel ->SetVisible( false );
// copy size&pos from template panel
int x,y,wide,tall;
templatePanel->GetBounds( x, y, wide, tall );
m_pPanel->SetBounds( x, y, wide, tall );
int px, py;
templatePanel->GetPinOffset( px, py );
int rx, ry;
templatePanel->GetResizeOffset( rx, ry );
// Apply pin settings from template, too
m_pPanel->SetAutoResize( templatePanel->GetPinCorner(), templatePanel->GetAutoResize(), px, py, rx, ry );
m_bPreserveArmedButtons = false;
m_bUpdateDefaultButtons = false;
}
virtual void SetPreserveArmedButtons( bool bPreserve ){ m_bPreserveArmedButtons = bPreserve; }
virtual void SetUpdateDefaultButtons( bool bUpdate ){ m_bUpdateDefaultButtons = bUpdate; }
virtual void ShowPage()
{
if( m_pPanel )
{
m_pPanel->SetVisible( true );
m_pPanel->MoveToFront();
g_lastPanel = m_pPanel;
}
}
virtual void HidePage()
{
if ( m_pPanel )
{
m_pPanel->SetVisible( false );
}
}
const char *GetClassPage( const char *className )
{
static char classPanel[ _MAX_PATH ];
Q_snprintf( classPanel, sizeof( classPanel ), "classes/%s.res", className);
if ( g_pFullFileSystem->FileExists( classPanel, IsX360() ? "MOD" : "GAME" ) )
{
}
else if (g_pFullFileSystem->FileExists( "classes/default.res", IsX360() ? "MOD" : "GAME" ) )
{
Q_snprintf ( classPanel, sizeof( classPanel ), "classes/default.res" );
}
else
{
return NULL;
}
return classPanel;
}
#ifdef REFRESH_CLASSMENU_TOOL
void RefreshClassPage( void )
{
m_pPanel->LoadControlSettings( GetClassPage( GetName() ) );
}
#endif
virtual void ApplySettings( KeyValues *resourceData )
{
BaseClass::ApplySettings( resourceData );
// name, position etc of button is set, now load matching
// resource file for associated info panel:
m_pPanel->LoadControlSettings( GetClassPage( GetName() ) );
}
T *GetClassPanel( void ) { return m_pPanel; }
virtual void OnCursorExited()
{
if ( !m_bPreserveArmedButtons )
{
BaseClass::OnCursorExited();
}
}
virtual void OnCursorEntered()
{
BaseClass::OnCursorEntered();
if ( !IsEnabled() )
return;
// are we updating the default buttons?
if ( m_bUpdateDefaultButtons )
{
SetAsDefaultButton( 1 );
}
// are we preserving the armed state (and need to turn off the old button)?
if ( m_bPreserveArmedButtons )
{
if ( g_lastButton && g_lastButton != this )
{
g_lastButton->SetArmed( false );
}
g_lastButton = this;
}
// turn on our panel (if it isn't already)
if ( m_pPanel && ( !m_pPanel->IsVisible() ) )
{
// turn off the previous panel
if ( g_lastPanel && g_lastPanel->IsVisible() )
{
g_lastPanel->SetVisible( false );
}
ShowPage();
}
}
virtual void OnKeyCodeReleased( vgui::KeyCode code )
{
BaseClass::OnKeyCodeReleased( code );
if ( m_bPreserveArmedButtons )
{
if ( g_lastButton )
{
g_lastButton->SetArmed( true );
}
}
}
private:
T *m_pPanel;
bool m_bPreserveArmedButtons;
bool m_bUpdateDefaultButtons;
};
#define MouseOverPanelButton MouseOverButton<vgui::EditablePanel>
#endif // MOUSEOVERPANELBUTTON_H

View File

@ -0,0 +1,154 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef SPECTATORGUI_H
#define SPECTATORGUI_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/IScheme.h>
#include <vgui/KeyCode.h>
#include <vgui_controls/Frame.h>
#include <vgui_controls/EditablePanel.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/ComboBox.h>
#include <igameevents.h>
#include "GameEventListener.h"
#include <game/client/iviewport.h>
class KeyValues;
namespace vgui
{
class TextEntry;
class Button;
class Panel;
class ImagePanel;
class ComboBox;
}
#define BLACK_BAR_COLOR Color(0, 0, 0, 196)
class IBaseFileSystem;
//-----------------------------------------------------------------------------
// Purpose: Spectator UI
//-----------------------------------------------------------------------------
class CSpectatorGUI : public vgui::EditablePanel, public IViewPortPanel
{
DECLARE_CLASS_SIMPLE( CSpectatorGUI, vgui::EditablePanel );
public:
CSpectatorGUI( IViewPort *pViewPort );
virtual ~CSpectatorGUI();
virtual const char *GetName( void ) { return PANEL_SPECGUI; }
virtual void SetData(KeyValues *data) {};
virtual void Reset() {};
virtual void Update();
virtual bool NeedsUpdate( void ) { return false; }
virtual bool HasInputElements( void ) { return false; }
virtual void ShowPanel( bool bShow );
// 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 void OnThink();
virtual int GetTopBarHeight() { return m_pTopBar->GetTall(); }
virtual int GetBottomBarHeight() { return m_pBottomBarBlank->GetTall(); }
virtual bool ShouldShowPlayerLabel( int specmode );
virtual Color GetBlackBarColor( void ) { return BLACK_BAR_COLOR; }
virtual const char *GetResFile( void ) { return "Resource/UI/Spectator.res"; }
protected:
void SetLabelText(const char *textEntryName, const char *text);
void SetLabelText(const char *textEntryName, wchar_t *text);
void MoveLabelToFront(const char *textEntryName);
void UpdateTimer();
void SetLogoImage(const char *image);
protected:
enum { INSET_OFFSET = 2 } ;
// vgui overrides
virtual void PerformLayout();
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
// virtual void OnCommand( const char *command );
vgui::Panel *m_pTopBar;
vgui::Panel *m_pBottomBarBlank;
vgui::ImagePanel *m_pBannerImage;
vgui::Label *m_pPlayerLabel;
IViewPort *m_pViewPort;
// bool m_bHelpShown;
// bool m_bInsetVisible;
bool m_bSpecScoreboard;
};
//-----------------------------------------------------------------------------
// Purpose: the bottom bar panel, this is a separate panel because it
// wants mouse input and the main window doesn't
//----------------------------------------------------------------------------
class CSpectatorMenu : public vgui::Frame, public IViewPortPanel, public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CSpectatorMenu, vgui::Frame );
public:
CSpectatorMenu( IViewPort *pViewPort );
~CSpectatorMenu() {}
virtual const char *GetName( void ) { return PANEL_SPECMENU; }
virtual void SetData(KeyValues *data) {};
virtual void Reset( void ) { m_pPlayerList->DeleteAllItems(); }
virtual void Update( void );
virtual bool NeedsUpdate( void ) { return false; }
virtual bool HasInputElements( void ) { return true; }
virtual void ShowPanel( bool bShow );
virtual void FireGameEvent( IGameEvent *event );
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
virtual bool IsVisible() { return BaseClass::IsVisible(); }
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
virtual void SetParent(vgui::VPANEL parent) { BaseClass::SetParent(parent); }
private:
// VGUI2 overrides
MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
virtual void OnCommand( const char *command );
virtual void OnKeyCodePressed(vgui::KeyCode code);
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void PerformLayout();
void SetViewModeText( const char *text ) { m_pViewOptions->SetText( text ); }
void SetPlayerFgColor( Color c1 ) { m_pPlayerList->SetFgColor(c1); }
vgui::ComboBox *m_pPlayerList;
vgui::ComboBox *m_pViewOptions;
vgui::ComboBox *m_pConfigSettings;
vgui::Button *m_pLeftButton;
vgui::Button *m_pRightButton;
IViewPort *m_pViewPort;
ButtonCode_t m_iDuckKey;
};
extern CSpectatorGUI * g_pSpectatorGUI;
#endif // SPECTATORGUI_H

View File

@ -0,0 +1,444 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include <cdll_client_int.h>
#include "teammenu.h"
#include <vgui/IScheme.h>
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <KeyValues.h>
#include <vgui_controls/ImageList.h>
#include <filesystem.h>
#include <vgui_controls/RichText.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/HTML.h>
#include "IGameUIFuncs.h" // for key bindings
#include <igameresources.h>
#include <game/client/iviewport.h>
#include <stdlib.h> // MAX_PATH define
#include <stdio.h>
#include "byteswap.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern IGameUIFuncs *gameuifuncs; // for key binding details
using namespace vgui;
void UpdateCursorState();
// void DuckMessage(const char *str);
// helper function
const char *GetStringTeamColor( int i )
{
switch( i )
{
case 0:
return "team0";
case 1:
return "team1";
case 2:
return "team2";
case 3:
return "team3";
case 4:
default:
return "team4";
}
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CTeamMenu::CTeamMenu(IViewPort *pViewPort) : Frame(NULL, PANEL_TEAM )
{
m_pViewPort = pViewPort;
m_iJumpKey = BUTTON_CODE_INVALID; // this is looked up in Activate()
m_iScoreBoardKey = BUTTON_CODE_INVALID; // this is looked up in Activate()
// initialize dialog
SetTitle("", true);
// load the new scheme early!!
SetScheme("ClientScheme");
SetMoveable(false);
SetSizeable(false);
// hide the system buttons
SetTitleBarVisible( false );
SetProportional(true);
// info window about this map
m_pMapInfo = new RichText( this, "MapInfo" );
#if defined( ENABLE_HTML_WINDOW )
m_pMapInfoHTML = new HTML( this, "MapInfoHTML");
#endif
LoadControlSettings("Resource/UI/TeamMenu.res");
InvalidateLayout();
m_szMapName[0] = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CTeamMenu::~CTeamMenu()
{
}
//-----------------------------------------------------------------------------
// Purpose: sets the text color of the map description field
//-----------------------------------------------------------------------------
void CTeamMenu::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
m_pMapInfo->SetFgColor( pScheme->GetColor("MapDescriptionText", Color(255, 255, 255, 0)) );
if ( *m_szMapName )
{
LoadMapPage( m_szMapName ); // reload the map description to pick up the color
}
}
//-----------------------------------------------------------------------------
// Purpose: makes the user choose the auto assign option
//-----------------------------------------------------------------------------
void CTeamMenu::AutoAssign()
{
engine->ClientCmd("jointeam 0");
OnClose();
}
//-----------------------------------------------------------------------------
// Purpose: shows the team menu
//-----------------------------------------------------------------------------
void CTeamMenu::ShowPanel(bool bShow)
{
if ( BaseClass::IsVisible() == bShow )
return;
if ( bShow )
{
Activate();
SetMouseInputEnabled( true );
// get key bindings if shown
if( m_iJumpKey == BUTTON_CODE_INVALID ) // you need to lookup the jump key AFTER the engine has loaded
{
m_iJumpKey = gameuifuncs->GetButtonCodeForBind( "jump" );
}
if ( m_iScoreBoardKey == BUTTON_CODE_INVALID )
{
m_iScoreBoardKey = gameuifuncs->GetButtonCodeForBind( "showscores" );
}
}
else
{
SetVisible( false );
SetMouseInputEnabled( false );
}
m_pViewPort->ShowBackGround( bShow );
}
//-----------------------------------------------------------------------------
// Purpose: updates the UI with a new map name and map html page, and sets up the team buttons
//-----------------------------------------------------------------------------
void CTeamMenu::Update()
{
char mapname[MAX_MAP_NAME];
Q_FileBase( engine->GetLevelName(), mapname, sizeof(mapname) );
SetLabelText( "mapname", mapname );
LoadMapPage( mapname );
}
//-----------------------------------------------------------------------------
// Purpose: chooses and loads the text page to display that describes mapName map
//-----------------------------------------------------------------------------
void CTeamMenu::LoadMapPage( const char *mapName )
{
// Save off the map name so we can re-load the page in ApplySchemeSettings().
Q_strncpy( m_szMapName, mapName, strlen( mapName ) + 1 );
char mapRES[ MAX_PATH ];
char uilanguage[ 64 ];
engine->GetUILanguage( uilanguage, sizeof( uilanguage ) );
Q_snprintf( mapRES, sizeof( mapRES ), "resource/maphtml/%s_%s.html", mapName, uilanguage );
bool bFoundHTML = false;
if ( !g_pFullFileSystem->FileExists( mapRES ) )
{
// try english
Q_snprintf( mapRES, sizeof( mapRES ), "resource/maphtml/%s_english.html", mapName );
}
else
{
bFoundHTML = true;
}
if( bFoundHTML || g_pFullFileSystem->FileExists( mapRES ) )
{
// it's a local HTML file
char localURL[ _MAX_PATH + 7 ];
Q_strncpy( localURL, "file://", sizeof( localURL ) );
char pPathData[ _MAX_PATH ];
g_pFullFileSystem->GetLocalPath( mapRES, pPathData, sizeof(pPathData) );
Q_strncat( localURL, pPathData, sizeof( localURL ), COPY_ALL_CHARACTERS );
// force steam to dump a local copy
g_pFullFileSystem->GetLocalCopy( pPathData );
m_pMapInfo->SetVisible( false );
#if defined( ENABLE_HTML_WINDOW )
m_pMapInfoHTML->SetVisible( true );
m_pMapInfoHTML->OpenURL( localURL, NULL );
#endif
InvalidateLayout();
Repaint();
return;
}
else
{
m_pMapInfo->SetVisible( true );
#if defined( ENABLE_HTML_WINDOW )
m_pMapInfoHTML->SetVisible( false );
#endif
}
Q_snprintf( mapRES, sizeof( mapRES ), "maps/%s.txt", mapName);
// if no map specific description exists, load default text
if( !g_pFullFileSystem->FileExists( mapRES ) )
{
if ( g_pFullFileSystem->FileExists( "maps/default.txt" ) )
{
Q_snprintf ( mapRES, sizeof( mapRES ), "maps/default.txt");
}
else
{
m_pMapInfo->SetText( "" );
return;
}
}
FileHandle_t f = g_pFullFileSystem->Open( mapRES, "r" );
// read into a memory block
int fileSize = g_pFullFileSystem->Size(f);
int dataSize = fileSize + sizeof( wchar_t );
if ( dataSize % 2 )
++dataSize;
wchar_t *memBlock = (wchar_t *)malloc(dataSize);
memset( memBlock, 0x0, dataSize);
int bytesRead = g_pFullFileSystem->Read(memBlock, fileSize, f);
if ( bytesRead < fileSize )
{
// NULL-terminate based on the length read in, since Read() can transform \r\n to \n and
// return fewer bytes than we were expecting.
char *data = reinterpret_cast<char *>( memBlock );
data[ bytesRead ] = 0;
data[ bytesRead+1 ] = 0;
}
#ifndef WIN32
if ( ((ucs2 *)memBlock)[0] == 0xFEFF )
{
// convert the win32 ucs2 data to wchar_t
dataSize*=2;// need to *2 to account for ucs2 to wchar_t (4byte) growth
wchar_t *memBlockConverted = (wchar_t *)malloc(dataSize);
V_UCS2ToUnicode( (ucs2 *)memBlock, memBlockConverted, dataSize );
free(memBlock);
memBlock = memBlockConverted;
}
#else
// null-terminate the stream (redundant, since we memset & then trimmed the transformed buffer already)
memBlock[dataSize / sizeof(wchar_t) - 1] = 0x0000;
#endif
// ensure little-endian unicode reads correctly on all platforms
CByteswap byteSwap;
byteSwap.SetTargetBigEndian( false );
byteSwap.SwapBufferToTargetEndian( memBlock, memBlock, dataSize/sizeof(wchar_t) );
// check the first character, make sure this a little-endian unicode file
if ( memBlock[0] != 0xFEFF )
{
// its a ascii char file
m_pMapInfo->SetText( reinterpret_cast<char *>( memBlock ) );
}
else
{
m_pMapInfo->SetText( memBlock+1 );
}
// go back to the top of the text buffer
m_pMapInfo->GotoTextStart();
g_pFullFileSystem->Close( f );
free(memBlock);
InvalidateLayout();
Repaint();
}
/*
//-----------------------------------------------------------------------------
// Purpose: sets the text on and displays the team buttons
//-----------------------------------------------------------------------------
void CTeamMenu::MakeTeamButtons(void)
{
int i = 0;
for( i = 0; i< m_pTeamButtons.Count(); i++ )
{
m_pTeamButtons[i]->SetVisible(false);
}
i = 0;
while( true )
{
const char *teamname = GameResources()->GetTeamName( i );
if ( !teamname || !teamname[0] )
return; // no more teams
char buttonText[32];
Q_snprintf( buttonText, sizeof(buttonText), "&%i %s", i +1, teamname );
m_pTeamButtons[i]->SetText( buttonText );
m_pTeamButtons[i]->SetCommand( new KeyValues("TeamButton", "team", i ) );
IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
m_pTeamButtons[i]->SetArmedColor(pScheme->GetColor(GetStringTeamColor(i), Color(255, 255, 255, 255)) , pScheme->GetColor("SelectionBG", Color(255, 255, 255, 0)) );
m_pTeamButtons[i]->SetDepressedColor( pScheme->GetColor(GetStringTeamColor(i), Color(255, 255, 255, 255)), pScheme->GetColor("ButtonArmedBgColor", Color(255, 255, 255, 0)) );
m_pTeamButtons[i]->SetDefaultColor( pScheme->GetColor(GetStringTeamColor(i), Color(255, 255, 255, 255)), pScheme->GetColor("ButtonDepressedBgColor", Color(255, 255, 255, 0)) );
m_pTeamButtons[i]->SetVisible(true);
i++;
}
}
//-----------------------------------------------------------------------------
// Purpose: When a team button is pressed it triggers this function to cause the player to join a team
//-----------------------------------------------------------------------------
void CTeamMenu::OnTeamButton( int team )
{
char cmd[64];
if( team >= m_iNumTeams ) // its a special button
{
if( team == m_iNumTeams ) // first extra team is auto assign
{
Q_snprintf( cmd, sizeof( cmd ), "jointeam 5" );
}
else // next is spectate
{
// DuckMessage( "#Spec_Duck" );
gViewPortInterface->ShowBackGround( false );
}
}
else
{
Q_snprintf( cmd, sizeof( cmd ), "jointeam %i", team + 1 );
//g_iTeamNumber = team + 1;
}
engine->ClientCmd(cmd);
SetVisible( false );
OnClose();
} */
//-----------------------------------------------------------------------------
// Purpose: Sets the text of a control by name
//-----------------------------------------------------------------------------
void CTeamMenu::SetLabelText(const char *textEntryName, const char *text)
{
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
if (entry)
{
entry->SetText(text);
}
}
void CTeamMenu::OnKeyCodePressed(KeyCode code)
{
int nDir = 0;
switch ( code )
{
case KEY_XBUTTON_UP:
case KEY_XSTICK1_UP:
case KEY_XSTICK2_UP:
case KEY_UP:
case KEY_XBUTTON_LEFT:
case KEY_XSTICK1_LEFT:
case KEY_XSTICK2_LEFT:
case KEY_LEFT:
nDir = -1;
break;
case KEY_XBUTTON_DOWN:
case KEY_XSTICK1_DOWN:
case KEY_XSTICK2_DOWN:
case KEY_DOWN:
case KEY_XBUTTON_RIGHT:
case KEY_XSTICK1_RIGHT:
case KEY_XSTICK2_RIGHT:
case KEY_RIGHT:
nDir = 1;
break;
}
if ( m_iScoreBoardKey != BUTTON_CODE_INVALID && m_iScoreBoardKey == code )
{
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, true );
gViewPortInterface->PostMessageToPanel( PANEL_SCOREBOARD, new KeyValues( "PollHideCode", "code", code ) );
}
else if ( nDir != 0 )
{
CUtlSortVector< SortedPanel_t, CSortedPanelYLess > vecSortedButtons;
VguiPanelGetSortedChildButtonList( this, (void*)&vecSortedButtons, "&", 0 );
if ( VguiPanelNavigateSortedChildButtonList( (void*)&vecSortedButtons, nDir ) != -1 )
{
// Handled!
return;
}
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}

View File

@ -0,0 +1,86 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TEAMMENU_H
#define TEAMMENU_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Frame.h>
#include <vgui_controls/Button.h>
#include <game/client/iviewport.h>
#include <vgui/KeyCode.h>
#include <utlvector.h>
namespace vgui
{
class RichText;
class HTML;
}
class TeamFortressViewport;
//-----------------------------------------------------------------------------
// Purpose: Displays the team menu
//-----------------------------------------------------------------------------
class CTeamMenu : public vgui::Frame, public IViewPortPanel
{
private:
DECLARE_CLASS_SIMPLE( CTeamMenu, vgui::Frame );
public:
CTeamMenu(IViewPort *pViewPort);
virtual ~CTeamMenu();
virtual const char *GetName( void ) { return PANEL_TEAM; }
virtual void SetData(KeyValues *data) {};
virtual void Reset() {};
virtual void Update();
virtual bool NeedsUpdate( void ) { return false; }
virtual bool HasInputElements( void ) { return true; }
virtual void ShowPanel( bool bShow );
// 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 ); }
public:
void AutoAssign();
protected:
// int GetNumTeams() { return m_iNumTeams; }
// VGUI2 overrides
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void OnKeyCodePressed(vgui::KeyCode code);
// helper functions
virtual void SetLabelText(const char *textEntryName, const char *text);
virtual void LoadMapPage( const char *mapName );
// virtual void MakeTeamButtons( void );
// command callbacks
// MESSAGE_FUNC_INT( OnTeamButton, "TeamButton", team );
IViewPort *m_pViewPort;
vgui::RichText *m_pMapInfo;
vgui::HTML *m_pMapInfoHTML;
// int m_iNumTeams;
ButtonCode_t m_iJumpKey;
ButtonCode_t m_iScoreBoardKey;
char m_szMapName[ MAX_PATH ];
};
#endif // TEAMMENU_H

View File

@ -0,0 +1,430 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "vguitextwindow.h"
#include <networkstringtabledefs.h>
#include <cdll_client_int.h>
#include <vgui/IScheme.h>
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <filesystem.h>
#include <KeyValues.h>
#include <convar.h>
#include <vgui_controls/ImageList.h>
#include <vgui_controls/TextEntry.h>
#include <vgui_controls/Button.h>
#include <game/client/iviewport.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
extern INetworkStringTable *g_pStringTableInfoPanel;
#define TEMP_HTML_FILE "textwindow_temp.html"
ConVar cl_disablehtmlmotd( "cl_disablehtmlmotd", "0", FCVAR_ARCHIVE, "Disable HTML motds." );
//=============================================================================
// HPE_BEGIN:
// [Forrest] Replaced text window command string with TEXTWINDOW_CMD enumeration
// of options. Passing a command string is dangerous and allowed a server network
// message to run arbitrary commands on the client.
//=============================================================================
CON_COMMAND( showinfo, "Shows a info panel: <type> <title> <message> [<command number>]" )
{
if ( !gViewPortInterface )
return;
if ( args.ArgC() < 4 )
return;
IViewPortPanel * panel = gViewPortInterface->FindPanelByName( PANEL_INFO );
if ( panel )
{
KeyValues *kv = new KeyValues("data");
kv->SetInt( "type", Q_atoi(args[ 1 ]) );
kv->SetString( "title", args[ 2 ] );
kv->SetString( "message", args[ 3 ] );
if ( args.ArgC() == 5 )
kv->SetString( "command", args[ 4 ] );
panel->SetData( kv );
gViewPortInterface->ShowPanel( panel, true );
kv->deleteThis();
}
else
{
Msg("Couldn't find info panel.\n" );
}
}
//=============================================================================
// HPE_END
//=============================================================================
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CTextWindow::CTextWindow(IViewPort *pViewPort) : Frame(NULL, PANEL_INFO )
{
// initialize dialog
m_pViewPort = pViewPort;
// SetTitle("", true);
m_szTitle[0] = '\0';
m_szMessage[0] = '\0';
m_szMessageFallback[0] = '\0';
m_nExitCommand = TEXTWINDOW_CMD_NONE;
m_bShownURL = false;
m_bUnloadOnDismissal = false;
// load the new scheme early!!
SetScheme("ClientScheme");
SetMoveable(false);
SetSizeable(false);
SetProportional(true);
// hide the system buttons
SetTitleBarVisible( false );
m_pTextMessage = new TextEntry( this, "TextMessage" );
#if defined( ENABLE_CHROMEHTMLWINDOW )
m_pHTMLMessage = new CMOTDHTML( this,"HTMLMessage" );
#else
m_pHTMLMessage = NULL;
#endif
m_pTitleLabel = new Label( this, "MessageTitle", "Message Title" );
m_pOK = new Button(this, "ok", "#PropertyDialog_OK");
m_pOK->SetCommand("okay");
m_pTextMessage->SetMultiline( true );
m_nContentType = TYPE_TEXT;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextWindow::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings("Resource/UI/TextWindow.res");
Reset();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CTextWindow::~CTextWindow()
{
// remove temp file again
g_pFullFileSystem->RemoveFile( TEMP_HTML_FILE, "DEFAULT_WRITE_PATH" );
}
void CTextWindow::Reset( void )
{
//=============================================================================
// HPE_BEGIN:
// [Forrest] Replace strange hard-coded default message with hard-coded error message.
//=============================================================================
Q_strcpy( m_szTitle, "Error loading info message." );
Q_strcpy( m_szMessage, "" );
Q_strcpy( m_szMessageFallback, "" );
//=============================================================================
// HPE_END
//=============================================================================
m_nExitCommand = TEXTWINDOW_CMD_NONE;
m_nContentType = TYPE_TEXT;
m_bShownURL = false;
m_bUnloadOnDismissal = false;
Update();
}
void CTextWindow::ShowText( const char *text )
{
m_pTextMessage->SetVisible( true );
m_pTextMessage->SetText( text );
m_pTextMessage->GotoTextStart();
}
void CTextWindow::ShowURL( const char *URL, bool bAllowUserToDisable )
{
#if defined( ENABLE_CHROMEHTMLWINDOW )
if ( bAllowUserToDisable && cl_disablehtmlmotd.GetBool() )
{
// User has disabled HTML TextWindows. Show the fallback as text only.
if ( g_pStringTableInfoPanel )
{
int index = g_pStringTableInfoPanel->FindStringIndex( "motd_text" );
if ( index != ::INVALID_STRING_INDEX )
{
int length = 0;
const char *data = (const char *)g_pStringTableInfoPanel->GetStringUserData( index, &length );
if ( data && data[0] )
{
m_pHTMLMessage->SetVisible( false );
ShowText( data );
}
}
}
return;
}
m_pHTMLMessage->SetVisible( true );
m_pHTMLMessage->OpenURL( URL, NULL );
m_bShownURL = true;
#endif
}
void CTextWindow::ShowIndex( const char *entry )
{
const char *data = NULL;
int length = 0;
if ( NULL == g_pStringTableInfoPanel )
return;
int index = g_pStringTableInfoPanel->FindStringIndex( m_szMessage );
if ( index != ::INVALID_STRING_INDEX )
data = (const char *)g_pStringTableInfoPanel->GetStringUserData( index, &length );
if ( !data || !data[0] )
return; // nothing to show
// is this a web URL ?
if ( !Q_strncmp( data, "http://", 7 ) || !Q_strncmp( data, "https://", 8 ) )
{
ShowURL( data );
return;
}
// try to figure out if this is HTML or not
if ( data[0] != '<' )
{
ShowText( data );
return;
}
// data is a HTML, we have to write to a file and then load the file
FileHandle_t hFile = g_pFullFileSystem->Open( TEMP_HTML_FILE, "wb", "DEFAULT_WRITE_PATH" );
if ( hFile == FILESYSTEM_INVALID_HANDLE )
return;
g_pFullFileSystem->Write( data, length, hFile );
g_pFullFileSystem->Close( hFile );
if ( g_pFullFileSystem->Size( TEMP_HTML_FILE ) != (unsigned int)length )
return; // something went wrong while writing
ShowFile( TEMP_HTML_FILE );
}
void CTextWindow::ShowFile( const char *filename )
{
if ( Q_stristr( filename, ".htm" ) || Q_stristr( filename, ".html" ) )
{
// it's a local HTML file
char localURL[ _MAX_PATH + 7 ];
Q_strncpy( localURL, "file://", sizeof( localURL ) );
char pPathData[ _MAX_PATH ];
g_pFullFileSystem->GetLocalPath( filename, pPathData, sizeof(pPathData) );
Q_strncat( localURL, pPathData, sizeof( localURL ), COPY_ALL_CHARACTERS );
ShowURL( localURL );
}
else
{
// read from local text from file
FileHandle_t f = g_pFullFileSystem->Open( m_szMessage, "rb", "GAME" );
if ( !f )
return;
char buffer[2048];
int size = MIN( g_pFullFileSystem->Size( f ), sizeof(buffer)-1 ); // just allow 2KB
g_pFullFileSystem->Read( buffer, size, f );
g_pFullFileSystem->Close( f );
buffer[size]=0; //terminate string
ShowText( buffer );
}
}
void CTextWindow::Update( void )
{
SetTitle( m_szTitle, false );
m_pTitleLabel->SetText( m_szTitle );
#if defined( ENABLE_CHROMEHTMLWINDOW )
m_pHTMLMessage->SetVisible( false );
#endif
m_pTextMessage->SetVisible( false );
if ( m_nContentType == TYPE_INDEX )
{
ShowIndex( m_szMessage );
}
else if ( m_nContentType == TYPE_URL )
{
ShowURL( m_szMessage );
}
else if ( m_nContentType == TYPE_FILE )
{
ShowFile( m_szMessage );
}
else if ( m_nContentType == TYPE_TEXT )
{
ShowText( m_szMessage );
}
else
{
DevMsg("CTextWindow::Update: unknown content type %i\n", m_nContentType );
}
}
void CTextWindow::OnCommand( const char *command )
{
if (!Q_strcmp(command, "okay"))
{
//=============================================================================
// HPE_BEGIN:
// [Forrest] Replaced text window command string with TEXTWINDOW_CMD enumeration
// of options. Passing a command string is dangerous and allowed a server network
// message to run arbitrary commands on the client.
//=============================================================================
const char *pszCommand = NULL;
switch ( m_nExitCommand )
{
case TEXTWINDOW_CMD_NONE:
break;
case TEXTWINDOW_CMD_JOINGAME:
pszCommand = "joingame";
break;
case TEXTWINDOW_CMD_CHANGETEAM:
pszCommand = "changeteam";
break;
case TEXTWINDOW_CMD_IMPULSE101:
pszCommand = "impulse 101";
break;
case TEXTWINDOW_CMD_MAPINFO:
pszCommand = "mapinfo";
break;
case TEXTWINDOW_CMD_CLOSED_HTMLPAGE:
pszCommand = "closed_htmlpage";
break;
case TEXTWINDOW_CMD_CHOOSETEAM:
pszCommand = "chooseteam";
break;
default:
DevMsg("CTextWindow::OnCommand: unknown exit command value %i\n", m_nExitCommand );
break;
}
if ( pszCommand != NULL )
{
engine->ClientCmd_Unrestricted( pszCommand );
}
//=============================================================================
// HPE_END
//=============================================================================
m_pViewPort->ShowPanel( this, false );
}
BaseClass::OnCommand(command);
}
void CTextWindow::OnKeyCodePressed( vgui::KeyCode code )
{
if ( code == KEY_XBUTTON_A || code == KEY_XBUTTON_B )
{
OnCommand( "okay" );
return;
}
BaseClass::OnKeyCodePressed(code);
}
void CTextWindow::SetData(KeyValues *data)
{
SetData( data->GetInt( "type" ), data->GetString( "title" ), data->GetString( "msg" ), data->GetString( "msg_fallback" ), data->GetInt( "cmd" ), data->GetBool( "unload" ) );
}
void CTextWindow::SetData( int type, const char *title, const char *message, const char *message_fallback, int command, bool bUnload )
{
Q_strncpy( m_szTitle, title, sizeof( m_szTitle ) );
Q_strncpy( m_szMessage, message, sizeof( m_szMessage ) );
Q_strncpy( m_szMessageFallback, message_fallback, sizeof( m_szMessageFallback ) );
m_nExitCommand = command;
m_nContentType = type;
m_bUnloadOnDismissal = bUnload;
Update();
}
void CTextWindow::ShowPanel( bool bShow )
{
if ( BaseClass::IsVisible() == bShow )
return;
m_pViewPort->ShowBackGround( bShow );
if ( bShow )
{
Activate();
SetMouseInputEnabled( true );
}
else
{
SetVisible( false );
SetMouseInputEnabled( false );
#if defined( ENABLE_CHROMEHTMLWINDOW )
if ( m_bUnloadOnDismissal && m_bShownURL )
{
m_pHTMLMessage->OpenURL( "about:blank", NULL );
m_bShownURL = false;
}
#endif
}
}
bool CTextWindow::CMOTDHTML::OnStartRequest( const char *url, const char *target, const char *pchPostData, bool bIsRedirect )
{
if ( Q_strstr( url, "steam://" ) )
return false;
return BaseClass::OnStartRequest( url, target, pchPostData, bIsRedirect );
}

View File

@ -0,0 +1,104 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef VGUITEXTWINDOW_H
#define VGUITEXTWINDOW_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Frame.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/HTML.h>
#include <game/client/iviewport.h>
#include "shareddefs.h"
namespace vgui
{
class TextEntry;
}
//-----------------------------------------------------------------------------
// Purpose: displays the MOTD
//-----------------------------------------------------------------------------
class CTextWindow : public vgui::Frame, public IViewPortPanel
{
private:
DECLARE_CLASS_SIMPLE( CTextWindow, vgui::Frame );
public:
CTextWindow(IViewPort *pViewPort);
virtual ~CTextWindow();
virtual const char *GetName( void ) { return PANEL_INFO; }
virtual void SetData(KeyValues *data);
virtual void Reset();
virtual void Update();
virtual bool NeedsUpdate( void ) { return false; }
virtual bool HasInputElements( void ) { return true; }
virtual void ShowPanel( bool bShow );
// 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 ); }
public:
virtual void SetData( int type, const char *title, const char *message, const char *message_fallback, int command, bool bUnload );
virtual void ShowFile( const char *filename );
virtual void ShowText( const char *text );
virtual void ShowURL( const char *URL, bool bAllowUserToDisable = true );
virtual void ShowIndex( const char *entry );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
protected:
// vgui overrides
virtual void OnCommand( const char *command );
void OnKeyCodePressed( vgui::KeyCode code );
IViewPort *m_pViewPort;
char m_szTitle[255];
char m_szMessage[2048];
char m_szMessageFallback[2048];
//=============================================================================
// HPE_BEGIN:
// [Forrest] Replaced text window command string with TEXTWINDOW_CMD enumeration
// of options. Passing a command string is dangerous and allowed a server network
// message to run arbitrary commands on the client.
//=============================================================================
int m_nExitCommand;
//=============================================================================
// HPE_END
//=============================================================================
int m_nContentType;
bool m_bShownURL;
bool m_bUnloadOnDismissal;
vgui::TextEntry *m_pTextMessage;
class CMOTDHTML : public vgui::HTML
{
private:
DECLARE_CLASS_SIMPLE( CMOTDHTML, vgui::HTML );
public:
CMOTDHTML( Panel *parent, const char *pchName ) : vgui::HTML( parent, pchName ) {}
virtual bool OnStartRequest( const char *url, const char *target, const char *pchPostData, bool bIsRedirect ) OVERRIDE;
};
CMOTDHTML *m_pHTMLMessage;
vgui::Button *m_pOK;
vgui::Label *m_pTitleLabel;
};
#endif // VGUITEXTWINDOW_H