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:
580
game/client/game_controls/ClientScoreBoardDialog.cpp
Normal file
580
game/client/game_controls/ClientScoreBoardDialog.cpp
Normal 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);
|
||||
}
|
68
game/client/game_controls/IconPanel.cpp
Normal file
68
game/client/game_controls/IconPanel.cpp
Normal 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 ) ) );
|
||||
}
|
42
game/client/game_controls/IconPanel.h
Normal file
42
game/client/game_controls/IconPanel.h
Normal 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
|
1340
game/client/game_controls/MapOverview.cpp
Normal file
1340
game/client/game_controls/MapOverview.cpp
Normal file
File diff suppressed because it is too large
Load Diff
137
game/client/game_controls/NavProgress.cpp
Normal file
137
game/client/game_controls/NavProgress.cpp
Normal 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 )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
59
game/client/game_controls/NavProgress.h
Normal file
59
game/client/game_controls/NavProgress.h
Normal 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
|
850
game/client/game_controls/SpectatorGUI.cpp
Normal file
850
game/client/game_controls/SpectatorGUI.cpp
Normal 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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
653
game/client/game_controls/basemodel_panel.cpp
Normal file
653
game/client/game_controls/basemodel_panel.cpp
Normal 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();
|
||||
}
|
||||
|
225
game/client/game_controls/basemodel_panel.h
Normal file
225
game/client/game_controls/basemodel_panel.h
Normal 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
|
898
game/client/game_controls/basemodelpanel.cpp
Normal file
898
game/client/game_controls/basemodelpanel.cpp
Normal 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;
|
||||
}
|
||||
|
233
game/client/game_controls/basemodelpanel.h
Normal file
233
game/client/game_controls/basemodelpanel.h
Normal 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
|
721
game/client/game_controls/baseviewport.cpp
Normal file
721
game/client/game_controls/baseviewport.cpp
Normal 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 );
|
||||
}
|
||||
}
|
148
game/client/game_controls/baseviewport.h
Normal file
148
game/client/game_controls/baseviewport.h
Normal 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
|
150
game/client/game_controls/buymenu.cpp
Normal file
150
game/client/game_controls/buymenu.cpp
Normal 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 );
|
||||
}
|
||||
}
|
||||
|
66
game/client/game_controls/buymenu.h
Normal file
66
game/client/game_controls/buymenu.h
Normal 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
|
171
game/client/game_controls/buysubmenu.cpp
Normal file
171
game/client/game_controls/buysubmenu.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
59
game/client/game_controls/buysubmenu.h
Normal file
59
game/client/game_controls/buysubmenu.h
Normal 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
|
316
game/client/game_controls/classmenu.cpp
Normal file
316
game/client/game_controls/classmenu.cpp
Normal 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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
79
game/client/game_controls/classmenu.h
Normal file
79
game/client/game_controls/classmenu.h
Normal 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
|
127
game/client/game_controls/clientscoreboarddialog.h
Normal file
127
game/client/game_controls/clientscoreboarddialog.h
Normal 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
|
361
game/client/game_controls/commandmenu.cpp
Normal file
361
game/client/game_controls/commandmenu.cpp
Normal 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;
|
||||
}
|
77
game/client/game_controls/commandmenu.h
Normal file
77
game/client/game_controls/commandmenu.h
Normal 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
|
256
game/client/game_controls/imagemouseoverbutton.h
Normal file
256
game/client/game_controls/imagemouseoverbutton.h
Normal 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
|
122
game/client/game_controls/intromenu.cpp
Normal file
122
game/client/game_controls/intromenu.cpp
Normal 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 );
|
||||
}
|
||||
}
|
57
game/client/game_controls/intromenu.h
Normal file
57
game/client/game_controls/intromenu.h
Normal 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
|
275
game/client/game_controls/mapoverview.h
Normal file
275
game/client/game_controls/mapoverview.h
Normal 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 //
|
119
game/client/game_controls/mouseoverhtmlbutton.h
Normal file
119
game/client/game_controls/mouseoverhtmlbutton.h
Normal 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
|
186
game/client/game_controls/mouseoverpanelbutton.h
Normal file
186
game/client/game_controls/mouseoverpanelbutton.h
Normal 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
|
154
game/client/game_controls/spectatorgui.h
Normal file
154
game/client/game_controls/spectatorgui.h
Normal 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
|
444
game/client/game_controls/teammenu.cpp
Normal file
444
game/client/game_controls/teammenu.cpp
Normal 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 );
|
||||
}
|
||||
}
|
86
game/client/game_controls/teammenu.h
Normal file
86
game/client/game_controls/teammenu.h
Normal 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
|
430
game/client/game_controls/vguitextwindow.cpp
Normal file
430
game/client/game_controls/vguitextwindow.cpp
Normal 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 );
|
||||
}
|
104
game/client/game_controls/vguitextwindow.h
Normal file
104
game/client/game_controls/vguitextwindow.h
Normal 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
|
Reference in New Issue
Block a user