This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,72 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "BackgroundMenuButton.h"
#include <KeyValues.h>
#include <vgui/IImage.h>
#include <vgui/IScheme.h>
#include <vgui_controls/Menu.h>
#include <vgui_controls/MenuItem.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CBackgroundMenuButton::CBackgroundMenuButton(vgui::Panel *parent, const char *name) : BaseClass(parent, name, "")
{
m_pImage = NULL;
m_pMouseOverImage = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CBackgroundMenuButton::~CBackgroundMenuButton()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBackgroundMenuButton::OnCommand(const char *command)
{
BaseClass::OnCommand(command);
}
//-----------------------------------------------------------------------------
// Purpose: Makes the button transparent
//-----------------------------------------------------------------------------
void CBackgroundMenuButton::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
// hack some colors in
SetFgColor(Color(255, 255, 255, 255));
SetBgColor(Color(0, 0, 0, 0));
SetDefaultColor(Color(255, 255, 255, 255), Color(0, 0, 0, 0));
SetArmedColor(Color(255, 255, 0, 255), Color(0, 0, 0, 0));
SetDepressedColor(Color(255, 255, 0, 255), Color(0, 0, 0, 0));
SetContentAlignment(Label::a_west);
SetBorder(NULL);
SetDefaultBorder(NULL);
SetDepressedBorder(NULL);
SetKeyFocusBorder(NULL);
SetTextInset(0, 0);
SetAlpha(0);
/*
// sounds disabled for this button (since it's so big now)
SetArmedSound("UI/buttonrollover.wav");
SetDepressedSound("UI/buttonclick.wav");
SetReleasedSound("UI/buttonclickrelease.wav");
*/
}

View File

@@ -0,0 +1,39 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BACKGROUNDMENUBUTTON_H
#define BACKGROUNDMENUBUTTON_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Button.h>
//-----------------------------------------------------------------------------
// Purpose: Baseclass for the left and right ingame menus that lay on the background
//-----------------------------------------------------------------------------
class CBackgroundMenuButton : public vgui::Button
{
public:
CBackgroundMenuButton(vgui::Panel *parent, const char *name);
~CBackgroundMenuButton();
virtual void OnCommand(const char *command);
protected:
vgui::Menu *RecursiveLoadGameMenu(KeyValues *datafile);
vgui::Menu *m_pMenu;
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
private:
vgui::IImage *m_pImage, *m_pMouseOverImage;
typedef vgui::Button BaseClass;
};
#endif // BACKGROUNDMENUBUTTON_H

View File

@@ -0,0 +1,22 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BASEPANEL_H
#define BASEPANEL_H
#ifdef _WIN32
#pragma once
#endif
#if defined( PORTAL2 )
#include "portal2/basemodpanel.h"
#elif defined( SWARM_DLL )
#include "swarm/basemodpanel.h"
#endif
inline BaseModUI::CBaseModPanel * BasePanel() { return &BaseModUI::CBaseModPanel::GetSingleton(); }
#endif // BASEPANEL_H

View File

@@ -0,0 +1,552 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "BaseSaveGameDialog.h"
#include "FileSystem.h"
#include "savegame_version.h"
#include "vgui_controls/PanelListPanel.h"
#include "vgui_controls/Label.h"
#include "vgui_controls/ImagePanel.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/tgaimagepanel.h"
#include "tier1/utlbuffer.h"
#include "tier2/resourceprecacher.h"
#include <stdio.h>
#include <stdlib.h>
#include "FileSystem.h"
#include "MouseMessageForwardingPanel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
#define TGA_IMAGE_PANEL_WIDTH 180
#define TGA_IMAGE_PANEL_HEIGHT 100
#define MAX_LISTED_SAVE_GAMES 128
// Dead, basemod ui trumps...
#if 0
PRECACHE_REGISTER_BEGIN( GLOBAL, BaseSaveGameDialog )
PRECACHE( MATERIAL, "vgui/resource/autosave.vmt" )
PRECACHE_REGISTER_END()
#endif
//-----------------------------------------------------------------------------
// Purpose: Describes the layout of a same game pic
//-----------------------------------------------------------------------------
class CSaveGamePanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CSaveGamePanel, vgui::EditablePanel );
public:
CSaveGamePanel( PanelListPanel *parent, const char *name, int saveGameListItemID ) : BaseClass( parent, name )
{
m_iSaveGameListItemID = saveGameListItemID;
m_pParent = parent;
m_pSaveGameImage = new CTGAImagePanel( this, "SaveGameImage" );
m_pAutoSaveImage = new ImagePanel( this, "AutoSaveImage" );
m_pSaveGameScreenshotBackground = new ImagePanel( this, "SaveGameScreenshotBackground" );
m_pChapterLabel = new Label( this, "ChapterLabel", "" );
m_pTypeLabel = new Label( this, "TypeLabel", "" );
m_pElapsedTimeLabel = new Label( this, "ElapsedTimeLabel", "" );
m_pFileTimeLabel = new Label( this, "FileTimeLabel", "" );
CMouseMessageForwardingPanel *panel = new CMouseMessageForwardingPanel(this, NULL);
panel->SetZPos(2);
SetSize( 200, 140 );
LoadControlSettings( "resource/SaveGamePanel.res" );
m_FillColor = m_pSaveGameScreenshotBackground->GetFillColor();
}
void SetSaveGameInfo( SaveGameDescription_t &save )
{
// set the bitmap to display
char tga[_MAX_PATH];
Q_strncpy( tga, save.szFileName, sizeof(tga) );
char *ext = strstr( tga, ".sav" );
if ( ext )
{
strcpy( ext, ".tga" );
}
// If a TGA file exists then it is a user created savegame
if ( g_pFullFileSystem->FileExists( tga ) )
{
m_pSaveGameImage->SetTGAFilename( tga );
}
// If there is no TGA then it is either an autosave or the user TGA file has been deleted
else
{
m_pSaveGameImage->SetVisible( false );
m_pAutoSaveImage->SetVisible( true );
m_pAutoSaveImage->SetImage( "resource\\autosave" );
}
// set the title text
m_pChapterLabel->SetText( save.szComment );
// type
SetControlString( "TypeLabel", save.szType );
SetControlString( "ElapsedTimeLabel", save.szElapsedTime );
SetControlString( "FileTimeLabel", save.szFileTime );
}
MESSAGE_FUNC_INT( OnPanelSelected, "PanelSelected", state )
{
if ( state )
{
// set the text color to be orange, and the pic border to be orange
m_pSaveGameScreenshotBackground->SetFillColor( m_SelectedColor );
m_pChapterLabel->SetFgColor( m_SelectedColor );
m_pTypeLabel->SetFgColor( m_SelectedColor );
m_pElapsedTimeLabel->SetFgColor( m_SelectedColor );
m_pFileTimeLabel->SetFgColor( m_SelectedColor );
}
else
{
m_pSaveGameScreenshotBackground->SetFillColor( m_FillColor );
m_pChapterLabel->SetFgColor( m_TextColor );
m_pTypeLabel->SetFgColor( m_TextColor );
m_pElapsedTimeLabel->SetFgColor( m_TextColor );
m_pFileTimeLabel->SetFgColor( m_TextColor );
}
PostMessage( m_pParent->GetVParent(), new KeyValues("PanelSelected") );
}
virtual void OnMousePressed( vgui::MouseCode code )
{
m_pParent->SetSelectedPanel( this );
}
virtual void ApplySchemeSettings( IScheme *pScheme )
{
m_TextColor = pScheme->GetColor( "NewGame.TextColor", Color(255, 255, 255, 255) );
m_SelectedColor = pScheme->GetColor( "NewGame.SelectionColor", Color(255, 255, 255, 255) );
BaseClass::ApplySchemeSettings( pScheme );
}
virtual void OnMouseDoublePressed( vgui::MouseCode code )
{
// call the panel
OnMousePressed( code );
PostMessage( m_pParent->GetParent(), new KeyValues("Command", "command", "loadsave") );
}
int GetSaveGameListItemID()
{
return m_iSaveGameListItemID;
}
private:
vgui::PanelListPanel *m_pParent;
vgui::Label *m_pChapterLabel;
CTGAImagePanel *m_pSaveGameImage;
ImagePanel *m_pAutoSaveImage;
// things to change color when the selection changes
ImagePanel *m_pSaveGameScreenshotBackground;
Label *m_pTypeLabel;
Label *m_pElapsedTimeLabel;
Label *m_pFileTimeLabel;
Color m_TextColor, m_FillColor, m_SelectedColor;
int m_iSaveGameListItemID;
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CBaseSaveGameDialog::CBaseSaveGameDialog( vgui::Panel *parent, const char *name ) : BaseClass( parent, name )
{
CreateSavedGamesList();
ScanSavedGames();
new vgui::Button( this, "loadsave", "" );
SetControlEnabled( "loadsave", false );
}
//-----------------------------------------------------------------------------
// Purpose: Creates the load game display list
//-----------------------------------------------------------------------------
void CBaseSaveGameDialog::CreateSavedGamesList()
{
m_pGameList = new vgui::PanelListPanel( this, "listpanel_loadgame" );
m_pGameList->SetFirstColumnWidth( 0 );
}
//-----------------------------------------------------------------------------
// Purpose: returns the save file name of the selected item
//-----------------------------------------------------------------------------
int CBaseSaveGameDialog::GetSelectedItemSaveIndex()
{
CSaveGamePanel *panel = dynamic_cast<CSaveGamePanel *>(m_pGameList->GetSelectedPanel());
if ( panel )
{
// find the panel in the list
for ( int i = 0; i < m_SaveGames.Count(); i++ )
{
if ( i == panel->GetSaveGameListItemID() )
{
return i;
}
}
}
return m_SaveGames.InvalidIndex();
}
//-----------------------------------------------------------------------------
// Purpose: builds save game list from directory
//-----------------------------------------------------------------------------
void CBaseSaveGameDialog::ScanSavedGames()
{
// populate list box with all saved games on record:
char szDirectory[_MAX_PATH];
Q_snprintf( szDirectory, sizeof( szDirectory ), "save/*.sav" );
// clear the current list
m_pGameList->DeleteAllItems();
m_SaveGames.RemoveAll();
// iterate the saved files
FileFindHandle_t handle;
const char *pFileName = g_pFullFileSystem->FindFirst( szDirectory, &handle );
while (pFileName)
{
if ( !Q_strnicmp(pFileName, "HLSave", strlen( "HLSave" ) ) )
{
pFileName = g_pFullFileSystem->FindNext( handle );
continue;
}
char szFileName[_MAX_PATH];
Q_snprintf(szFileName, sizeof( szFileName ), "save/%s", pFileName);
// Only load save games from the current mod's save dir
if( !g_pFullFileSystem->FileExists( szFileName, "MOD" ) )
{
pFileName = g_pFullFileSystem->FindNext( handle );
continue;
}
SaveGameDescription_t save;
if ( ParseSaveData( szFileName, pFileName, save ) )
{
m_SaveGames.AddToTail( save );
}
pFileName = g_pFullFileSystem->FindNext( handle );
}
g_pFullFileSystem->FindClose( handle );
// notify derived classes that save games are being scanned (so they can insert their own)
OnScanningSaveGames();
// sort the save list
qsort( m_SaveGames.Base(), m_SaveGames.Count(), sizeof(SaveGameDescription_t), &SaveGameSortFunc );
// add to the list
for ( int saveIndex = 0; saveIndex < m_SaveGames.Count() && saveIndex < MAX_LISTED_SAVE_GAMES; saveIndex++ )
{
// add the item to the panel
AddSaveGameItemToList( saveIndex );
}
// display a message if there are no save games
if ( !m_SaveGames.Count() )
{
vgui::Label *pNoSavesLabel = SETUP_PANEL(new Label(m_pGameList, "NoSavesLabel", "#GameUI_NoSaveGamesToDisplay"));
pNoSavesLabel->SetTextColorState(vgui::Label::CS_DULL);
m_pGameList->AddItem( NULL, pNoSavesLabel );
}
SetControlEnabled( "loadsave", false );
SetControlEnabled( "delete", false );
}
//-----------------------------------------------------------------------------
// Purpose: Adds an item to the list
//-----------------------------------------------------------------------------
void CBaseSaveGameDialog::AddSaveGameItemToList( int saveIndex )
{
// create the new panel and add to the list
CSaveGamePanel *saveGamePanel = new CSaveGamePanel( m_pGameList, "SaveGamePanel", saveIndex );
saveGamePanel->SetSaveGameInfo( m_SaveGames[saveIndex] );
m_pGameList->AddItem( NULL, saveGamePanel );
}
//-----------------------------------------------------------------------------
// Purpose: Parses the save game info out of the .sav file header
//-----------------------------------------------------------------------------
bool CBaseSaveGameDialog::ParseSaveData( char const *pszFileName, char const *pszShortName, SaveGameDescription_t &save )
{
char szMapName[SAVEGAME_MAPNAME_LEN];
char szComment[SAVEGAME_COMMENT_LEN];
char szElapsedTime[SAVEGAME_ELAPSED_LEN];
if ( !pszFileName || !pszShortName )
return false;
Q_strncpy( save.szShortName, pszShortName, sizeof(save.szShortName) );
Q_strncpy( save.szFileName, pszFileName, sizeof(save.szFileName) );
FileHandle_t fh = g_pFullFileSystem->Open( pszFileName, "rb", "MOD" );
if (fh == FILESYSTEM_INVALID_HANDLE)
return false;
int readok = SaveReadNameAndComment( fh, szMapName, szComment );
g_pFullFileSystem->Close(fh);
if ( !readok )
{
return false;
}
Q_strncpy( save.szMapName, szMapName, sizeof(save.szMapName) );
// Elapsed time is the last 6 characters in comment. (mmm:ss)
int i;
i = strlen( szComment );
Q_strncpy( szElapsedTime, "??", sizeof( szElapsedTime ) );
if (i >= 6)
{
Q_strncpy( szElapsedTime, (char *)&szComment[i - 6], 7 );
szElapsedTime[6] = '\0';
// parse out
int minutes = atoi( szElapsedTime );
int seconds = atoi( szElapsedTime + 4);
// reformat
if ( minutes )
{
Q_snprintf( szElapsedTime, sizeof(szElapsedTime), "%d %s %d seconds", minutes, minutes > 1 ? "minutes" : "minute", seconds );
}
else
{
Q_snprintf( szElapsedTime, sizeof(szElapsedTime), "%d seconds", seconds );
}
// Chop elapsed out of comment.
int n;
n = i - 6;
szComment[n] = '\0';
n--;
// Strip back the spaces at the end.
while ((n >= 1) &&
szComment[n] &&
szComment[n] == ' ')
{
szComment[n--] = '\0';
}
}
// calculate the file name to print
const char *pszType = "";
if (strstr(pszFileName, "quick"))
{
pszType = "#GameUI_QuickSave";
}
else if (strstr(pszFileName, "autosave"))
{
pszType = "#GameUI_AutoSave";
}
Q_strncpy( save.szType, pszType, sizeof(save.szType) );
Q_strncpy( save.szComment, szComment, sizeof(save.szComment) );
Q_strncpy( save.szElapsedTime, szElapsedTime, sizeof(save.szElapsedTime) );
// Now get file time stamp.
long fileTime = g_pFullFileSystem->GetFileTime(pszFileName);
char szFileTime[32];
g_pFullFileSystem->FileTimeToString(szFileTime, sizeof(szFileTime), fileTime);
char *newline = strstr(szFileTime, "\n");
if (newline)
{
*newline = 0;
}
Q_strncpy( save.szFileTime, szFileTime, sizeof(save.szFileTime) );
save.iTimestamp = fileTime;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: timestamp sort function for savegames
//-----------------------------------------------------------------------------
int CBaseSaveGameDialog::SaveGameSortFunc( const void *lhs, const void *rhs )
{
const SaveGameDescription_t *s1 = (const SaveGameDescription_t *)lhs;
const SaveGameDescription_t *s2 = (const SaveGameDescription_t *)rhs;
if (s1->iTimestamp < s2->iTimestamp)
return 1;
else if (s1->iTimestamp > s2->iTimestamp)
return -1;
// timestamps are equal, so just sort by filename
return strcmp(s1->szFileName, s2->szFileName);
}
#define MAKEID(d,c,b,a) ( ((int)(a) << 24) | ((int)(b) << 16) | ((int)(c) << 8) | ((int)(d)) )
int SaveReadNameAndComment( FileHandle_t f, char *name, char *comment )
{
int i, tag, size, tokenSize, tokenCount;
char *pSaveData, *pFieldName, **pTokenList;
g_pFullFileSystem->Read( &tag, sizeof(int), f );
if ( tag != MAKEID('J','S','A','V') )
{
return 0;
}
g_pFullFileSystem->Read( &tag, sizeof(int), f );
if ( tag != SAVEGAME_VERSION ) // Enforce version for now
{
return 0;
}
name[0] = '\0';
comment[0] = '\0';
g_pFullFileSystem->Read( &size, sizeof(int), f );
g_pFullFileSystem->Read( &tokenCount, sizeof(int), f ); // These two ints are the token list
g_pFullFileSystem->Read( &tokenSize, sizeof(int), f );
size += tokenSize;
// Sanity Check.
if ( tokenCount < 0 || tokenCount > 1024*1024*32 )
{
return 0;
}
if ( tokenSize < 0 || tokenSize > 1024*1024*32 )
{
return 0;
}
pSaveData = (char *)new char[size];
g_pFullFileSystem->Read(pSaveData, size, f);
int nNumberOfFields;
char *pData;
int nFieldSize;
pData = pSaveData;
// Allocate a table for the strings, and parse the table
if ( tokenSize > 0 )
{
pTokenList = new char *[tokenCount];
// Make sure the token strings pointed to by the pToken hashtable.
for( i=0; i<tokenCount; i++ )
{
pTokenList[i] = *pData ? pData : NULL; // Point to each string in the pToken table
while( *pData++ ); // Find next token (after next null)
}
}
else
pTokenList = NULL;
// short, short (size, index of field name)
nFieldSize = *(short *)pData;
pData += sizeof(short);
pFieldName = pTokenList[ *(short *)pData ];
if (stricmp(pFieldName, "GameHeader"))
{
delete[] pSaveData;
return 0;
};
// int (fieldcount)
pData += sizeof(short);
nNumberOfFields = *(int*)pData;
pData += nFieldSize;
// Each field is a short (size), short (index of name), binary string of "size" bytes (data)
for (i = 0; i < nNumberOfFields; i++)
{
// Data order is:
// Size
// szName
// Actual Data
nFieldSize = *(short *)pData;
pData += sizeof(short);
pFieldName = pTokenList[ *(short *)pData ];
pData += sizeof(short);
if (!stricmp(pFieldName, "comment"))
{
Q_strncpy(comment, pData, nFieldSize);
}
else if (!stricmp(pFieldName, "mapName"))
{
Q_strncpy(name, pData, nFieldSize);
};
// Move to Start of next field.
pData += nFieldSize;
};
// Delete the string table we allocated
delete[] pTokenList;
delete[] pSaveData;
if (strlen(name) > 0 && strlen(comment) > 0)
return 1;
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: deletes an existing save game
//-----------------------------------------------------------------------------
void CBaseSaveGameDialog::DeleteSaveGame( const char *fileName )
{
if ( !fileName || !fileName[0] )
return;
// delete the save game file
g_pFullFileSystem->RemoveFile( fileName, "MOD" );
// delete the associated tga
char tga[_MAX_PATH];
Q_strncpy( tga, fileName, sizeof(tga) );
char *ext = strstr( tga, ".sav" );
if ( ext )
{
strcpy( ext, ".tga" );
}
g_pFullFileSystem->RemoveFile( tga, "MOD" );
}
//-----------------------------------------------------------------------------
// Purpose: One item has been selected
//-----------------------------------------------------------------------------
void CBaseSaveGameDialog::OnPanelSelected()
{
SetControlEnabled( "loadsave", true );
SetControlEnabled( "delete", true );
}

View File

@@ -0,0 +1,71 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef BASESAVEGAMEDIALOG_H
#define BASESAVEGAMEDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/Frame.h"
#include "vgui/MouseCode.h"
#include "KeyValues.h"
#include "UtlVector.h"
#define SAVEGAME_MAPNAME_LEN 32
#define SAVEGAME_COMMENT_LEN 80
#define SAVEGAME_ELAPSED_LEN 32
struct SaveGameDescription_t
{
char szShortName[64];
char szFileName[128];
char szMapName[SAVEGAME_MAPNAME_LEN];
char szComment[SAVEGAME_COMMENT_LEN];
char szType[64];
char szElapsedTime[SAVEGAME_ELAPSED_LEN];
char szFileTime[32];
unsigned int iTimestamp;
unsigned int iSize;
};
int SaveReadNameAndComment( FileHandle_t f, char *name, char *comment );
//-----------------------------------------------------------------------------
// Purpose: Base class for save & load game dialogs
//-----------------------------------------------------------------------------
class CBaseSaveGameDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CBaseSaveGameDialog, vgui::Frame );
public:
CBaseSaveGameDialog( vgui::Panel *parent, const char *name );
static int __cdecl SaveGameSortFunc( const void *lhs, const void *rhs );
protected:
CUtlVector<SaveGameDescription_t> m_SaveGames;
vgui::PanelListPanel *m_pGameList;
virtual void OnScanningSaveGames() {}
void DeleteSaveGame( const char *fileName );
void ScanSavedGames();
void CreateSavedGamesList();
int GetSelectedItemSaveIndex();
void AddSaveGameItemToList( int saveIndex );
bool ParseSaveData( char const *pszFileName, char const *pszShortName, SaveGameDescription_t &save );
private:
MESSAGE_FUNC( OnPanelSelected, "PanelSelected" );
};
#endif // BASESAVEGAMEDIALOG_H

View File

@@ -0,0 +1,87 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "BitmapImagePanel.h"
#include <vgui/ISurface.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
CBitmapImagePanel::CBitmapImagePanel( Panel *parent, char const *panelName,
char const *filename /*= NULL*/ ) : Panel( parent, panelName )
{
m_szTexture[ 0 ] = 0;
m_bUploaded = false;
m_nTextureId = -1;
SetBounds( 0, 0, 100, 100 );
if ( filename && filename[ 0 ] )
{
Q_strncpy( m_szTexture, filename, sizeof( m_szTexture ) );
}
}
CBitmapImagePanel::~CBitmapImagePanel()
{
if ( vgui::surface() && m_nTextureId != -1 )
{
vgui::surface()->DestroyTextureID( m_nTextureId );
m_nTextureId = -1;
}
}
void CBitmapImagePanel::PaintBackground()
{
if (!m_szTexture[0])
return;
if ( !m_bUploaded )
forceUpload();
int w, h;
GetSize( w, h );
surface()->DrawSetColor( Color( 255, 255, 255, 255 ) );
surface()->DrawSetTexture( m_nTextureId );
surface()->DrawTexturedRect( 0, 0, w, h );
}
void CBitmapImagePanel::setTexture( char const *filename )
{
Q_strncpy( m_szTexture, filename, sizeof( m_szTexture ) );
if ( m_bUploaded )
{
forceReload();
}
else
{
forceUpload();
}
}
void CBitmapImagePanel::forceUpload()
{
if ( !m_szTexture[ 0 ] )
return;
m_bUploaded = true;
m_nTextureId = surface()->CreateNewTextureID();
surface()->DrawSetTextureFile( m_nTextureId, m_szTexture, false, true);
}
void CBitmapImagePanel::forceReload( void )
{
if ( !m_bUploaded )
return;
// Force texture to re-upload to video card
surface()->DrawSetTextureFile( m_nTextureId, m_szTexture, false, true);
}

View File

@@ -0,0 +1,38 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BITMAPIMAGEPANEL_H
#define BITMAPIMAGEPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Panel.h>
class CBitmapImagePanel : public vgui::Panel
{
public:
CBitmapImagePanel( vgui::Panel *parent, char const *panelName, char const *filename = NULL );
virtual ~CBitmapImagePanel();
virtual void PaintBackground();
virtual void setTexture( char const *filename );
virtual void forceReload( void );
private:
typedef vgui::Panel BaseClass;
void forceUpload();
bool m_bUploaded;
int m_nTextureId;
char m_szTexture[ 128 ];
};
#endif // BITMAPIMAGEPANEL_H

View File

@@ -0,0 +1,58 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CDKEYENTRYDIALOG_H
#define CDKEYENTRYDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/Frame.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CCDKeyEntryDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CCDKeyEntryDialog, vgui::Frame );
public:
CCDKeyEntryDialog(vgui::Panel *parent, bool inConnect = false);
~CCDKeyEntryDialog();
virtual void Activate();
static bool IsValidWeakCDKeyInRegistry();
private:
enum { MAX_CDKEY_ERRORS = 5 };
virtual void OnCommand(const char *command);
virtual void OnClose();
virtual void OnThink();
MESSAGE_FUNC_PTR( OnTextChanged, "TextChanged", panel );
bool IsEnteredKeyValid();
vgui::Button *m_pOK;
vgui::Button *m_pQuitGame;
vgui::TextEntry *m_pEntry1;
vgui::TextEntry *m_pEntry2;
vgui::TextEntry *m_pEntry3;
vgui::TextEntry *m_pEntry4;
vgui::TextEntry *m_pEntry5;
vgui::DHANDLE<vgui::MessageBox> m_hErrorBox;
bool m_bEnteredValidCDKey;
bool m_bInConnect;
int m_iErrCount;
};
#endif // CDKEYENTRYDIALOG_H

View File

@@ -0,0 +1,47 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "CommandCheckButton.h"
#include "EngineInterface.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
CCommandCheckButton::CCommandCheckButton( Panel *parent, const char *panelName, const char *text, const char *downcmd, const char *upcmd )
: CheckButton( parent, panelName, text )
{
m_pszDown = downcmd ? strdup( downcmd ) : NULL;
m_pszUp = upcmd ? strdup( upcmd ) : NULL;
}
CCommandCheckButton::~CCommandCheckButton()
{
free( m_pszDown );
free( m_pszUp );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *panel -
//-----------------------------------------------------------------------------
void CCommandCheckButton::SetSelected( bool state )
{
BaseClass::SetSelected( state );
if ( IsSelected() && m_pszDown )
{
engine->ClientCmd_Unrestricted( m_pszDown );
engine->ClientCmd_Unrestricted( "\n" );
}
else if ( !IsSelected() && m_pszUp )
{
engine->ClientCmd_Unrestricted( m_pszUp );
engine->ClientCmd_Unrestricted( "\n" );
}
}

View File

@@ -0,0 +1,30 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef COMMANDCHECKBUTTON_H
#define COMMANDCHECKBUTTON_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/CheckButton.h>
class CCommandCheckButton : public vgui::CheckButton
{
public:
CCommandCheckButton( vgui::Panel *parent, const char *panelName, const char *text, const char *downcmd, const char *upcmd );
~CCommandCheckButton();
// virtual void OnCheckButtonChecked(vgui::Panel *panel);
virtual void SetSelected( bool state );
private:
typedef vgui::CheckButton BaseClass;
char *m_pszDown;
char *m_pszUp;
};
#endif // COMMANDCHECKBUTTON_H

View File

@@ -0,0 +1,402 @@
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#ifdef IS_WINDOWS_PC
#include <memory.h>
#include <windows.h>
#endif
#include "ContentControlDialog.h"
#include "checksum_md5.h"
#include "EngineInterface.h"
#include <vgui/IInput.h>
#include <vgui/ISystem.h>
#include <vgui/ISurface.h>
#include "tier1/KeyValues.h"
#include "tier1/convar.h"
#include <vgui_controls/Button.h>
#include <vgui_controls/CheckButton.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/RadioButton.h>
#include <vgui_controls/TextEntry.h>
#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif
#if defined( _PS3 )
#include "ps3/ps3_core.h"
#include "ps3/ps3_win32stubs.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Basic help dialog
//-----------------------------------------------------------------------------
CContentControlDialog::CContentControlDialog(vgui::Panel *parent) : vgui::Frame(parent, "ContentControlDialog")
{
SetBounds(0, 0, 372, 160);
SetSizeable( false );
SetTitle( "#GameUI_ContentLock", true );
m_pStatus = new vgui::Label( this, "ContentStatus", "" );
m_pPasswordLabel = new vgui::Label( this, "PasswordPrompt", "#GameUI_PasswordPrompt" );
m_pPassword2Label = new vgui::Label( this, "PasswordReentryPrompt", "#GameUI_PasswordReentryPrompt" );
m_pExplain = new vgui::Label( this, "ContentControlExplain", "" );
m_pPassword = new vgui::TextEntry( this, "Password" );
m_pPassword2 = new vgui::TextEntry( this, "Password2" );
m_pOK = new vgui::Button( this, "Ok", "#GameUI_OK" );
m_pOK->SetCommand( "Ok" );
vgui::Button *cancel = new vgui::Button( this, "Cancel", "#GameUI_Cancel" );
cancel->SetCommand( "Cancel" );
m_szGorePW[ 0 ] = 0;
ResetPassword();
LoadControlSettings("Resource\\ContentControlDialog.res");
// Explain("");
// UpdateContentControlStatus();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CContentControlDialog::~CContentControlDialog()
{
}
void CContentControlDialog::Activate()
{
BaseClass::Activate();
m_pPassword->SetText("");
m_pPassword->RequestFocus();
m_pPassword2->SetText("");
Explain("");
UpdateContentControlStatus();
input()->SetAppModalSurface(GetVPanel());
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CContentControlDialog::ResetPassword()
{
// Set initial value
#if defined(_WIN32)
HKEY key;
if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Valve\\Half-Life\\Settings", 0, KEY_READ, &key))
{
DWORD type;
DWORD bufSize = sizeof(m_szGorePW);
RegQueryValueEx(key, "User Token 2", NULL, &type, (unsigned char *)m_szGorePW, &bufSize );
RegCloseKey( key );
}
else
#endif
{
m_szGorePW[ 0 ] = 0;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CContentControlDialog::ApplyPassword()
{
WriteToken( m_szGorePW );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CContentControlDialog::Explain( char const *fmt, ... )
{
if ( !m_pExplain )
return;
va_list argptr;
char text[1024];
va_start (argptr,fmt);
Q_vsnprintf (text, sizeof(text), fmt, argptr);
va_end (argptr);
m_pExplain->SetText( text );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *command -
//-----------------------------------------------------------------------------
void CContentControlDialog::OnCommand( const char *command )
{
if ( !stricmp( command, "Ok" ) )
{
bool canclose = false;
char pw1[ 256 ];
char pw2[ 256 ];
m_pPassword->GetText( pw1, 256 );
m_pPassword2->GetText( pw2, 256 );
// Get text and check
// bool enabled = PasswordEnabled(); //( m_szGorePW[0]!=0 ) ? true : false;
// bool pwMatch = stricmp( pw1, pw2 ) == 0 ? true : false;
if (IsPasswordEnabledInDialog())
{
canclose = DisablePassword(pw1);
// canclose = CheckPassword( m_szGorePW, pw1, false );
}
else if (!strcmp(pw1, pw2))
{
canclose = EnablePassword(pw1);
// canclose = CheckPassword( NULL, pw1, true );
}
else
{
Explain( "#GameUI_PasswordsDontMatch" );
}
if ( canclose )
{
OnClose();
}
}
else if ( !stricmp( command, "Cancel" ) )
{
OnClose();
}
else
{
BaseClass::OnCommand( command );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CContentControlDialog::OnClose()
{
BaseClass::OnClose();
PostActionSignal(new KeyValues("ContentControlClose"));
// MarkForDeletion();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CContentControlDialog::WriteToken( const char *str )
{
// Set initial value
#ifdef IS_WINDOWS_PC
HKEY key;
if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Valve\\Half-Life\\Settings", 0, KEY_WRITE, &key))
{
DWORD type = REG_SZ;
DWORD bufSize = strlen( str ) + 1;
RegSetValueEx(key, "User Token 2", 0, type, (const unsigned char *)str, bufSize );
RegCloseKey( key );
}
#endif
Q_strncpy( m_szGorePW, str, sizeof( m_szGorePW ) );
UpdateContentControlStatus();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CContentControlDialog::HashPassword(const char *newPW, char *hashBuffer, int maxlen )
{
// Compute the md5 hash and save it.
unsigned char md5_hash[16];
MD5Context_t ctx;
MD5Init( &ctx );
MD5Update( &ctx, (unsigned char const *)newPW, strlen( newPW ) );
MD5Final( md5_hash, &ctx );
char hex[ 128 ];
Q_binarytohex( md5_hash, sizeof( md5_hash ), hex, sizeof( hex ) );
// char digestedPW[ 128 ];
Q_strncpy( hashBuffer, hex, maxlen );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
/*
bool CContentControlDialog::CheckPassword( char const *oldPW, char const *newPW, bool enableContentControl )
{
char digestedPW[ 128 ];
HashPassword(newPW, digestedPW, sizeof( digestedPW ) );
// Compute the md5 hash and save it.
unsigned char md5_hash[16];
MD5Context_t ctx;
MD5Init( &ctx );
MD5Update( &ctx, (unsigned char const *)(LPCSTR)newPW, strlen( newPW ) );
MD5Final( md5_hash, &ctx );
char hex[ 128 ];
Q_binarytohex( md5_hash, sizeof( md5_hash ), hex, sizeof( hex ) );
Q_strncpy( digestedPW, hex, sizeof( digestedPW ) );
*/
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CContentControlDialog::EnablePassword(const char *newPW)
{
if ( !newPW[ 0 ] )
{
Explain( "#GameUI_MustEnterPassword" );
return false;
}
char digestedPW[ 128 ];
HashPassword(newPW, digestedPW, sizeof( digestedPW ) );
// disable violence
/* engine->Cvar_SetValue("violence_hblood", 0.0 );
engine->Cvar_SetValue("violence_hgibs" , 0.0 );
engine->Cvar_SetValue("violence_ablood", 0.0 );
engine->Cvar_SetValue("violence_agibs" , 0.0 );
*/
ConVarRef violence_hblood( "violence_hblood" );
violence_hblood.SetValue(false);
ConVarRef violence_hgibs( "violence_hgibs" );
violence_hgibs.SetValue(false);
ConVarRef violence_ablood( "violence_ablood" );
violence_ablood.SetValue(false);
ConVarRef violence_agibs( "violence_agibs" );
violence_agibs.SetValue(false);
// Store digest to registry
// WriteToken( digestedPW );
Q_strncpy(m_szGorePW, digestedPW, sizeof( m_szGorePW ) );
/*
}
else
{
if ( stricmp( oldPW, digestedPW ) )
{
// Warn that password is invalid
Explain( "#GameUI_IncorrectPassword" );
return false;
}
}
}*/
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CContentControlDialog::DisablePassword(const char *oldPW)
{
if ( !oldPW[ 0 ] )
{
Explain( "#GameUI_MustEnterPassword" );
return false;
}
char digestedPW[ 128 ];
HashPassword(oldPW, digestedPW, sizeof( digestedPW ) );
if( stricmp( m_szGorePW, digestedPW ) )
{
Explain( "#GameUI_IncorrectPassword" );
return false;
}
m_szGorePW[0] = 0;
// set the violence cvars
/* engine->Cvar_SetValue("violence_hblood", 1.0 );
engine->Cvar_SetValue("violence_hgibs" , 1.0 );
engine->Cvar_SetValue("violence_ablood", 1.0 );
engine->Cvar_SetValue("violence_agibs" , 1.0 );
*/
ConVarRef violence_hblood( "violence_hblood" );
violence_hblood.SetValue(true);
ConVarRef violence_hgibs( "violence_hgibs" );
violence_hgibs.SetValue(true);
ConVarRef violence_ablood( "violence_ablood" );
violence_ablood.SetValue(true);
ConVarRef violence_agibs( "violence_agibs" );
violence_agibs.SetValue(true);
// // Remove digest value
// WriteToken( "" );
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CContentControlDialog::IsPasswordEnabledInDialog()
{
return m_szGorePW[0] != 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CContentControlDialog::UpdateContentControlStatus( void )
{
bool enabled = IsPasswordEnabledInDialog(); //( m_szGorePW[0]!=0 ) ? true : false;
m_pStatus->SetText( enabled ? "#GameUI_ContentStatusEnabled" : "#GameUI_ContentStatusDisabled" );
if (enabled)
{
m_pPasswordLabel->SetText("#GameUI_PasswordDisablePrompt");
}
else
{
m_pPasswordLabel->SetText("#GameUI_PasswordPrompt");
}
// hide the re-entry
m_pPassword2Label->SetVisible(!enabled);
m_pPassword2->SetVisible(!enabled);
// m_pOK->SetText( enabled ? "#GameUI_Disable" : "#GameUI_Enable" );
}

View File

@@ -0,0 +1,66 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CONTENTCONTROLDIALOG_H
#define CONTENTCONTROLDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/Frame.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CContentControlDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CContentControlDialog, vgui::Frame );
public:
CContentControlDialog(vgui::Panel *parent);
~CContentControlDialog();
virtual void OnCommand( const char *command );
virtual void OnClose();
virtual void Activate();
void ResetPassword();
void ApplyPassword();
bool IsPasswordEnabledInDialog();
bool IsPasswordEnabled() { return ( m_szGorePW[0] != 0 ); }
protected:
void WriteToken( const char *str );
bool CheckPassword( char const *oldPW, char const *newPW, bool enableContentControl );
void UpdateContentControlStatus( void );
void Explain( char const *fmt, ... );
void HashPassword(const char *newPW, char *hashBuffer, int maxlen );
bool EnablePassword(const char *newPW);
bool DisablePassword(const char *oldPW);
enum
{
MAX_GORE_PW = 64,
};
char m_szGorePW[ MAX_GORE_PW ];
bool m_bDefaultPassword;
vgui::Label *m_pStatus;
vgui::Button *m_pOK;
vgui::TextEntry *m_pPassword;
vgui::Label *m_pPasswordLabel;
vgui::Label *m_pPassword2Label;
vgui::TextEntry *m_pPassword2;
vgui::Label *m_pExplain;
};
#endif // CONTENTCONTROLDIALOG_H

View File

@@ -0,0 +1,227 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "CreateMultiplayerGameBotPage.h"
using namespace vgui;
#include <KeyValues.h>
#include <vgui_controls/ComboBox.h>
#include <vgui_controls/CheckButton.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/TextEntry.h>
#include "FileSystem.h"
#include "PanelListPanel.h"
#include "ScriptObject.h"
#include "tier1/convar.h"
#include "EngineInterface.h"
#include "CvarToggleCheckButton.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
// for join team combo box
enum BotGUITeamType
{
BOT_GUI_TEAM_RANDOM = 0,
BOT_GUI_TEAM_CT = 1,
BOT_GUI_TEAM_T = 2
};
// these must correlate with above enum
static const char *joinTeamArg[] = { "any", "ct", "t", NULL };
// for bot chatter combo box
enum BotGUIChatterType
{
BOT_GUI_CHATTER_NORMAL = 0,
BOT_GUI_CHATTER_MINIMAL = 1,
BOT_GUI_CHATTER_RADIO = 2,
BOT_GUI_CHATTER_OFF = 3
};
// these must correlate with above enum
static const char *chatterArg[] = { "normal", "minimal", "radio", "off", NULL };
extern void UTIL_StripInvalidCharacters( char *pszInput );
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameBotPage::SetJoinTeamCombo( const char *team )
{
if (team)
{
for( int i=0; joinTeamArg[i]; ++i )
if (!stricmp( team, joinTeamArg[i] ))
{
m_joinTeamCombo->ActivateItemByRow( i );
return;
}
}
else
{
m_joinTeamCombo->ActivateItemByRow( BOT_GUI_TEAM_RANDOM );
}
}
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameBotPage::SetChatterCombo( const char *chatter )
{
if (chatter)
{
for( int i=0; chatterArg[i]; ++i )
if (!stricmp( chatter, chatterArg[i] ))
{
m_chatterCombo->ActivateItemByRow( i );
return;
}
}
else
{
m_joinTeamCombo->ActivateItemByRow( BOT_GUI_CHATTER_NORMAL );
}
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CCreateMultiplayerGameBotPage::CCreateMultiplayerGameBotPage( vgui::Panel *parent, const char *name, KeyValues *botKeys ) : PropertyPage( parent, name )
{
m_pSavedData = botKeys;
m_allowRogues = new CCvarToggleCheckButton( this, "BotAllowRogueCheck", "", "bot_allow_rogues" );
m_allowPistols = new CCvarToggleCheckButton( this, "BotAllowPistolsCheck", "", "bot_allow_pistols" );
m_allowShotguns = new CCvarToggleCheckButton( this, "BotAllowShotgunsCheck", "", "bot_allow_shotguns" );
m_allowSubmachineGuns = new CCvarToggleCheckButton( this, "BotAllowSubmachineGunsCheck", "", "bot_allow_sub_machine_guns" );
m_allowRifles = new CCvarToggleCheckButton( this, "BotAllowRiflesCheck", "", "bot_allow_rifles" );
m_allowMachineGuns = new CCvarToggleCheckButton( this, "BotAllowMachineGunsCheck", "", "bot_allow_machine_guns" );
m_allowGrenades = new CCvarToggleCheckButton( this, "BotAllowGrenadesCheck", "", "bot_allow_grenades" );
m_allowSnipers = new CCvarToggleCheckButton( this, "BotAllowSnipersCheck", "", "bot_allow_snipers" );
#ifdef CS_SHIELD_ENABLED
m_allowShields = new CCvarToggleCheckButton( this, "BotAllowShieldCheck", "", "bot_allow_shield" );
#endif // CS_SHIELD_ENABLED
m_joinAfterPlayer = new CCvarToggleCheckButton( this, "BotJoinAfterPlayerCheck", "", "bot_join_after_player" );
m_deferToHuman = new CCvarToggleCheckButton( this, "BotDeferToHumanCheck", "", "bot_defer_to_human" );
// set up team join combo box
// NOTE: If order of AddItem is changed, update the associated enum
m_joinTeamCombo = new ComboBox( this, "BotJoinTeamCombo", 3, false );
m_joinTeamCombo->AddItem( "#Cstrike_Random", NULL );
m_joinTeamCombo->AddItem( "#Cstrike_ScoreBoard_CT", NULL );
m_joinTeamCombo->AddItem( "#Cstrike_ScoreBoard_Ter", NULL );
// set up chatter combo box
// NOTE: If order of AddItem is changed, update the associated enum
m_chatterCombo = new ComboBox( this, "BotChatterCombo", 4, false );
m_chatterCombo->AddItem( "#Cstrike_Bot_Chatter_Normal", NULL );
m_chatterCombo->AddItem( "#Cstrike_Bot_Chatter_Minimal", NULL );
m_chatterCombo->AddItem( "#Cstrike_Bot_Chatter_Radio", NULL );
m_chatterCombo->AddItem( "#Cstrike_Bot_Chatter_Off", NULL );
// create text entry fields for quota and prefix
m_prefixEntry = new TextEntry( this, "BotPrefixEntry" );
// set positions and sizes from resources file
LoadControlSettings( "Resource/CreateMultiplayerGameBotPage.res" );
// get initial values from bot keys
m_joinAfterPlayer->SetSelected( botKeys->GetBool( "bot_join_after_player", true ) );
m_allowRogues->SetSelected( botKeys->GetBool( "bot_allow_rogues", true ) );
m_allowPistols->SetSelected( botKeys->GetBool( "bot_allow_pistols", true ) );
m_allowShotguns->SetSelected( botKeys->GetBool( "bot_allow_shotguns", true ) );
m_allowSubmachineGuns->SetSelected( botKeys->GetBool( "bot_allow_sub_machine_guns", true ) );
m_allowMachineGuns->SetSelected( botKeys->GetBool( "bot_allow_machine_guns", true ) );
m_allowRifles->SetSelected( botKeys->GetBool( "bot_allow_rifles", true ) );
m_allowSnipers->SetSelected( botKeys->GetBool( "bot_allow_snipers", true ) );
m_allowGrenades->SetSelected( botKeys->GetBool( "bot_allow_grenades", true ) );
#ifdef CS_SHIELD_ENABLED
m_allowShields->SetSelected( botKeys->GetBool( "bot_allow_shield", true ) );
#endif // CS_SHIELD_ENABLED
m_deferToHuman->SetSelected( botKeys->GetBool( "bot_defer_to_human", true ) );
SetJoinTeamCombo( botKeys->GetString( "bot_join_team", "any" ) );
SetChatterCombo( botKeys->GetString( "bot_chatter", "normal" ) );
// set bot_prefix
const char *prefix = botKeys->GetString( "bot_prefix" );
if (prefix)
SetControlString( "BotPrefixEntry", prefix );
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
CCreateMultiplayerGameBotPage::~CCreateMultiplayerGameBotPage()
{
// vgui handles deletion of children automatically through the hierarchy
}
//-----------------------------------------------------------------------------
// Reset values
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameBotPage::OnResetChanges()
{
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void UpdateValue( KeyValues *data, const char *cvarName, int value )
{
data->SetInt( cvarName, value );
ConVarRef var( cvarName );
var.SetValue( value );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void UpdateValue( KeyValues *data, const char *cvarName, const char *value )
{
data->SetString( cvarName, value );
ConVarRef var( cvarName );
var.SetValue( value );
}
//-----------------------------------------------------------------------------
// Called to get data from the page
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameBotPage::OnApplyChanges()
{
UpdateValue( m_pSavedData, "bot_join_after_player", m_joinAfterPlayer->IsSelected() );
UpdateValue( m_pSavedData, "bot_allow_rogues", m_allowRogues->IsSelected() );
UpdateValue( m_pSavedData, "bot_allow_pistols", m_allowPistols->IsSelected() );
UpdateValue( m_pSavedData, "bot_allow_shotguns", m_allowShotguns->IsSelected() );
UpdateValue( m_pSavedData, "bot_allow_sub_machine_guns", m_allowSubmachineGuns->IsSelected() );
UpdateValue( m_pSavedData, "bot_allow_machine_guns", m_allowMachineGuns->IsSelected() );
UpdateValue( m_pSavedData, "bot_allow_rifles", m_allowRifles->IsSelected() );
UpdateValue( m_pSavedData, "bot_allow_snipers", m_allowSnipers->IsSelected() );
UpdateValue( m_pSavedData, "bot_allow_grenades", m_allowGrenades->IsSelected() );
#ifdef CS_SHIELD_ENABLED
UpdateValue( m_pSavedData, "bot_allow_shield", m_allowShields->IsSelected() );
#endif // CS_SHIELD_ENABLED
UpdateValue( m_pSavedData, "bot_defer_to_human", m_deferToHuman->IsSelected() );
// set bot_join_team
UpdateValue( m_pSavedData, "bot_join_team", joinTeamArg[ m_joinTeamCombo->GetActiveItem() ] );
// set bot_chatter
UpdateValue( m_pSavedData, "bot_chatter", chatterArg[ m_chatterCombo->GetActiveItem() ] );
// set bot_prefix
#define BUF_LENGTH 256
char entryBuffer[ BUF_LENGTH ];
m_prefixEntry->GetText( entryBuffer, BUF_LENGTH );
UpdateValue( m_pSavedData, "bot_prefix", entryBuffer );
}

View File

@@ -0,0 +1,66 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CREATEMULTIPLAYERGAMEBOTPAGE_H
#define CREATEMULTIPLAYERGAMEBOTPAGE_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/PropertyPage.h>
class CPanelListPanel;
class CDescription;
class mpcontrol_t;
class CCvarToggleCheckButton;
//-----------------------------------------------------------------------------
// Purpose: advanced bot properties page of the create game server dialog
//-----------------------------------------------------------------------------
class CCreateMultiplayerGameBotPage : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( CCreateMultiplayerGameBotPage, vgui::PropertyPage );
public:
CCreateMultiplayerGameBotPage( vgui::Panel *parent, const char *name, KeyValues *botKeys );
~CCreateMultiplayerGameBotPage();
protected:
virtual void OnResetChanges();
virtual void OnApplyChanges();
private:
CCvarToggleCheckButton *m_joinAfterPlayer;
CCvarToggleCheckButton *m_allowRogues;
CCvarToggleCheckButton *m_allowPistols;
CCvarToggleCheckButton *m_allowShotguns;
CCvarToggleCheckButton *m_allowSubmachineGuns;
CCvarToggleCheckButton *m_allowMachineGuns;
CCvarToggleCheckButton *m_allowRifles;
CCvarToggleCheckButton *m_allowGrenades;
#ifdef CS_SHIELD_ENABLED
CCvarToggleCheckButton *m_allowShields;
#endif // CS_SHIELD_ENABLED
CCvarToggleCheckButton *m_allowSnipers;
CCvarToggleCheckButton *m_deferToHuman;
vgui::ComboBox *m_joinTeamCombo;
void SetJoinTeamCombo( const char *team );
vgui::ComboBox *m_chatterCombo;
void SetChatterCombo( const char *team );
vgui::TextEntry *m_prefixEntry;
KeyValues *m_pSavedData;
};
#endif // CREATEMULTIPLAYERGAMEBOTPAGE_H

View File

@@ -0,0 +1,144 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "CreateMultiplayerGameDialog.h"
#include "CreateMultiplayerGameServerPage.h"
#include "CreateMultiplayerGameGameplayPage.h"
#include "CreateMultiplayerGameBotPage.h"
#include "EngineInterface.h"
#include "ModInfo.h"
#include "GameUI_Interface.h"
#include <stdio.h>
using namespace vgui;
#include <vgui/ILocalize.h>
#include "FileSystem.h"
#include <KeyValues.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CCreateMultiplayerGameDialog::CCreateMultiplayerGameDialog(vgui::Panel *parent) : PropertyDialog(parent, "CreateMultiplayerGameDialog")
{
m_bBotsEnabled = false;
SetDeleteSelfOnClose(true);
SetSize(348, 460);
SetTitle("#GameUI_CreateServer", true);
SetOKButtonText("#GameUI_Start");
if (!stricmp( ModInfo().GetGameName(), "Counter-Strike Source" ))
{
m_bBotsEnabled = true;
}
m_pServerPage = new CCreateMultiplayerGameServerPage(this, "ServerPage");
m_pGameplayPage = new CCreateMultiplayerGameGameplayPage(this, "GameplayPage");
m_pBotPage = NULL;
AddPage(m_pServerPage, "#GameUI_Server");
AddPage(m_pGameplayPage, "#GameUI_Game");
// create KeyValues object to load/save config options
m_pSavedData = new KeyValues( "ServerConfig" );
// load the config data
if (m_pSavedData)
{
m_pSavedData->LoadFromFile( g_pFullFileSystem, "ServerConfig.vdf", "GAME" ); // this is game-specific data, so it should live in GAME, not CONFIG
const char *startMap = m_pSavedData->GetString("map", "");
if (startMap[0])
{
m_pServerPage->SetMap(startMap);
}
}
if ( m_bBotsEnabled )
{
// add a page of advanced bot controls
// NOTE: These controls will use the bot keys to initialize their values
m_pBotPage = new CCreateMultiplayerGameBotPage( this, "BotPage", m_pSavedData );
AddPage( m_pBotPage, "#GameUI_CPUPlayerOptions" );
m_pServerPage->EnableBots( m_pSavedData );
}
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CCreateMultiplayerGameDialog::~CCreateMultiplayerGameDialog()
{
if (m_pSavedData)
{
m_pSavedData->deleteThis();
m_pSavedData = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: runs the server when the OK button is pressed
//-----------------------------------------------------------------------------
bool CCreateMultiplayerGameDialog::OnOK(bool applyOnly)
{
// reset server enforced cvars
g_pCVar->RevertFlaggedConVars( FCVAR_REPLICATED );
// Cheats were disabled; revert all cheat cvars to their default values.
// This must be done heading into multiplayer games because people can play
// demos etc and set cheat cvars with sv_cheats 0.
g_pCVar->RevertFlaggedConVars( FCVAR_CHEAT );
DevMsg( "FCVAR_CHEAT cvars reverted to defaults.\n" );
BaseClass::OnOK(applyOnly);
// get these values from m_pServerPage and store them temporarily
char szMapName[64], szHostName[64], szPassword[64];
Q_strncpy(szMapName, m_pServerPage->GetMapName(), sizeof( szMapName ));
Q_strncpy(szHostName, m_pGameplayPage->GetHostName(), sizeof( szHostName ));
Q_strncpy(szPassword, m_pGameplayPage->GetPassword(), sizeof( szPassword ));
// save the config data
if (m_pSavedData)
{
if (m_pServerPage->IsRandomMapSelected())
{
// it's set to random map, just save an
m_pSavedData->SetString("map", "");
}
else
{
m_pSavedData->SetString("map", szMapName);
}
// save config to a file
m_pSavedData->SaveToFile( g_pFullFileSystem, "ServerConfig.vdf", "GAME" );
}
char szMapCommand[1024];
// create the command to execute
Q_snprintf(szMapCommand, sizeof( szMapCommand ), "disconnect\nwait\nwait\nsv_lan 1\nsetmaster enable\nmaxplayers %i\nsv_password \"%s\"\nhostname \"%s\"\nprogress_enable\nmap %s\n",
m_pGameplayPage->GetMaxPlayers(),
szPassword,
szHostName,
szMapName
);
// exec
engine->ClientCmd_Unrestricted(szMapCommand);
return true;
}

View File

@@ -0,0 +1,46 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CREATEMULTIPLAYERGAMEDIALOG_H
#define CREATEMULTIPLAYERGAMEDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/PropertyDialog.h>
class CCreateMultiplayerGameServerPage;
class CCreateMultiplayerGameGameplayPage;
class CCreateMultiplayerGameBotPage;
//-----------------------------------------------------------------------------
// Purpose: dialog for launching a listenserver
//-----------------------------------------------------------------------------
class CCreateMultiplayerGameDialog : public vgui::PropertyDialog
{
DECLARE_CLASS_SIMPLE( CCreateMultiplayerGameDialog, vgui::PropertyDialog );
public:
CCreateMultiplayerGameDialog(vgui::Panel *parent);
~CCreateMultiplayerGameDialog();
protected:
virtual bool OnOK(bool applyOnly);
private:
CCreateMultiplayerGameServerPage *m_pServerPage;
CCreateMultiplayerGameGameplayPage *m_pGameplayPage;
CCreateMultiplayerGameBotPage *m_pBotPage;
bool m_bBotsEnabled;
// for loading/saving game config
KeyValues *m_pSavedData;
};
#endif // CREATEMULTIPLAYERGAMEDIALOG_H

View File

@@ -0,0 +1,487 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#include <time.h>
#include "CreateMultiplayerGameGameplayPage.h"
using namespace vgui;
#include <KeyValues.h>
#include <vgui/ILocalize.h>
#include <vgui_controls/ComboBox.h>
#include <vgui_controls/CheckButton.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/TextEntry.h>
#include "FileSystem.h"
#include "PanelListPanel.h"
#include "ScriptObject.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#ifdef _PS3
//!!BUG!! "PS3 doesn't support wcsicmp!"
#ifdef _wcsicmp
#undef _wcsicmp
#endif
#define _wcsicmp wcscmp
#endif
#define OPTIONS_DIR "cfg"
#define DEFAULT_OPTIONS_FILE OPTIONS_DIR "/settings_default.scr"
#define OPTIONS_FILE OPTIONS_DIR "/settings.scr"
//-----------------------------------------------------------------------------
// Purpose: class for loading/saving server config file
//-----------------------------------------------------------------------------
class CServerDescription : public CDescription
{
public:
CServerDescription( CPanelListPanel *panel );
void WriteScriptHeader( FileHandle_t fp );
void WriteFileHeader( FileHandle_t fp );
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CCreateMultiplayerGameGameplayPage::CCreateMultiplayerGameGameplayPage(vgui::Panel *parent, const char *name) : PropertyPage(parent, name)
{
m_pOptionsList = new CPanelListPanel(this, "GameOptions");
m_pDescription = new CServerDescription(m_pOptionsList);
m_pDescription->InitFromFile( DEFAULT_OPTIONS_FILE );
m_pDescription->InitFromFile( OPTIONS_FILE );
m_pList = NULL;
LoadControlSettings("Resource/CreateMultiplayerGameGameplayPage.res");
LoadGameOptionsList();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CCreateMultiplayerGameGameplayPage::~CCreateMultiplayerGameGameplayPage()
{
delete m_pDescription;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CCreateMultiplayerGameGameplayPage::GetMaxPlayers()
{
return atoi(GetValue("maxplayers", "32"));
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CCreateMultiplayerGameGameplayPage::GetPassword()
{
return GetValue("sv_password", "");
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CCreateMultiplayerGameGameplayPage::GetHostName()
{
return GetValue("hostname", "Half-Life");
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CCreateMultiplayerGameGameplayPage::GetValue(const char *cvarName, const char *defaultValue)
{
for (mpcontrol_t *mp = m_pList; mp != NULL; mp = mp->next)
{
Panel *control = mp->pControl;
if (control && !stricmp(mp->GetName(), cvarName))
{
KeyValues *data = new KeyValues("GetText");
static char buf[128];
if (control && control->RequestInfo(data))
{
Q_strncpy(buf, data->GetString("text", defaultValue), sizeof(buf) - 1);
}
else
{
// no value found, copy in default text
Q_strncpy(buf, defaultValue, sizeof(buf) - 1);
}
// ensure null termination of string
buf[sizeof(buf) - 1] = 0;
// free
data->deleteThis();
return buf;
}
}
return defaultValue;
}
//-----------------------------------------------------------------------------
// Purpose: called to get data from the page
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameGameplayPage::OnApplyChanges()
{
// Get the values from the controls
GatherCurrentValues();
// Create the game.cfg file
if ( m_pDescription )
{
FileHandle_t fp;
// Add settings to config.cfg
m_pDescription->WriteToConfig();
// save out in the settings file
g_pFullFileSystem->CreateDirHierarchy( OPTIONS_DIR, "GAME" );
fp = g_pFullFileSystem->Open( OPTIONS_FILE, "wb", "GAME" );
if ( fp )
{
m_pDescription->WriteToScriptFile( fp );
g_pFullFileSystem->Close( fp );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Creates all the controls in the game options list
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameGameplayPage::LoadGameOptionsList()
{
// destroy any existing controls
mpcontrol_t *p, *n;
p = m_pList;
while ( p )
{
n = p->next;
//
delete p->pControl;
delete p->pPrompt;
delete p;
p = n;
}
m_pList = NULL;
// Go through desciption creating controls
CScriptObject *pObj;
pObj = m_pDescription->pObjList;
mpcontrol_t *pCtrl;
CheckButton *pBox;
TextEntry *pEdit;
ComboBox *pCombo;
CScriptListItem *pListItem;
Panel *objParent = m_pOptionsList;
while ( pObj )
{
if ( pObj->type == O_OBSOLETE )
{
pObj = pObj->pNext;
continue;
}
pCtrl = new mpcontrol_t( objParent, pObj->cvarname );
pCtrl->type = pObj->type;
switch ( pCtrl->type )
{
case O_BOOL:
pBox = new CheckButton( pCtrl, "DescCheckButton", pObj->prompt );
pBox->SetSelected( pObj->fdefValue != 0.0f ? true : false );
pCtrl->pControl = (Panel *)pBox;
break;
case O_STRING:
case O_NUMBER:
pEdit = new TextEntry( pCtrl, "DescEdit");
pEdit->InsertString(pObj->defValue);
pCtrl->pControl = (Panel *)pEdit;
break;
case O_LIST:
pCombo = new ComboBox( pCtrl, "DescEdit", 5, false );
pListItem = pObj->pListItems;
while ( pListItem )
{
pCombo->AddItem(pListItem->szItemText, NULL);
pListItem = pListItem->pNext;
}
pCombo->ActivateItemByRow((int)pObj->fdefValue);
pCtrl->pControl = (Panel *)pCombo;
break;
default:
break;
}
if ( pCtrl->type != O_BOOL )
{
pCtrl->pPrompt = new vgui::Label( pCtrl, "DescLabel", "" );
pCtrl->pPrompt->SetContentAlignment( vgui::Label::a_west );
pCtrl->pPrompt->SetTextInset( 5, 0 );
pCtrl->pPrompt->SetText( pObj->prompt );
}
pCtrl->pScrObj = pObj;
pCtrl->SetSize( 100, 28 );
//pCtrl->SetBorder( scheme()->GetBorder(1, "DepressedButtonBorder") );
m_pOptionsList->AddItem( pCtrl );
// Link it in
if ( !m_pList )
{
m_pList = pCtrl;
pCtrl->next = NULL;
}
else
{
mpcontrol_t *p;
p = m_pList;
while ( p )
{
if ( !p->next )
{
p->next = pCtrl;
pCtrl->next = NULL;
break;
}
p = p->next;
}
}
pObj = pObj->pNext;
}
}
//-----------------------------------------------------------------------------
// Purpose: applies all the values in the page
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameGameplayPage::GatherCurrentValues()
{
if ( !m_pDescription )
return;
// OK
CheckButton *pBox;
TextEntry *pEdit;
ComboBox *pCombo;
mpcontrol_t *pList;
CScriptObject *pObj;
CScriptListItem *pItem;
char szValue[256];
char strValue[256];
wchar_t w_szStrValue[256];
pList = m_pList;
while ( pList )
{
pObj = pList->pScrObj;
if ( !pList->pControl )
{
pObj->SetCurValue( pObj->defValue );
pList = pList->next;
continue;
}
switch ( pObj->type )
{
case O_BOOL:
pBox = (CheckButton *)pList->pControl;
Q_snprintf( szValue, sizeof( szValue ), "%s", pBox->IsSelected() ? "1" : "0" );
break;
case O_NUMBER:
pEdit = ( TextEntry * )pList->pControl;
pEdit->GetText( strValue, sizeof( strValue ) );
Q_snprintf( szValue, sizeof( szValue ), "%s", strValue );
break;
case O_STRING:
pEdit = ( TextEntry * )pList->pControl;
pEdit->GetText( strValue, sizeof( strValue ) );
Q_snprintf( szValue, sizeof( szValue ), "%s", strValue );
break;
case O_LIST:
pCombo = ( ComboBox *)pList->pControl;
pCombo->GetText( w_szStrValue, sizeof( w_szStrValue ) / sizeof( wchar_t ) );
pItem = pObj->pListItems;
while ( pItem )
{
wchar_t *wLocalizedString = NULL;
wchar_t w_szStrTemp[256];
// Localized string?
if ( pItem->szItemText[0] == '#' )
{
wLocalizedString = g_pVGuiLocalize->Find( pItem->szItemText );
}
if ( wLocalizedString )
{
// Copy the string we found into our temp array
wcsncpy( w_szStrTemp, wLocalizedString, sizeof( w_szStrTemp ) / sizeof( wchar_t ) );
}
else
{
// Just convert what we have to Unicode
g_pVGuiLocalize->ConvertANSIToUnicode( pItem->szItemText, w_szStrTemp, sizeof( w_szStrTemp ) );
}
if ( _wcsicmp( w_szStrTemp, w_szStrValue ) == 0 )
{
// Found a match!
break;
}
pItem = pItem->pNext;
}
if ( pItem )
{
Q_snprintf( szValue, sizeof( szValue ), "%s", pItem->szValue );
}
else //Couldn't find index
{
Q_snprintf( szValue, sizeof( szValue ), "%s", pObj->defValue );
}
break;
}
// Remove double quotes and % characters
UTIL_StripInvalidCharacters( szValue, sizeof( szValue ) );
Q_strncpy( strValue, szValue, sizeof( strValue ) );
pObj->SetCurValue( strValue );
pList = pList->next;
}
}
//-----------------------------------------------------------------------------
// Purpose: Constructor, load/save server settings object
//-----------------------------------------------------------------------------
CServerDescription::CServerDescription(CPanelListPanel *panel) : CDescription(panel)
{
setHint( "// NOTE: THIS FILE IS AUTOMATICALLY REGENERATED, \r\n"
"//DO NOT EDIT THIS HEADER, YOUR COMMENTS WILL BE LOST IF YOU DO\r\n"
"// Multiplayer options script\r\n"
"//\r\n"
"// Format:\r\n"
"// Version [float]\r\n"
"// Options description followed by \r\n"
"// Options defaults\r\n"
"//\r\n"
"// Option description syntax:\r\n"
"//\r\n"
"// \"cvar\" { \"Prompt\" { type [ type info ] } { default } }\r\n"
"//\r\n"
"// type = \r\n"
"// BOOL (a yes/no toggle)\r\n"
"// STRING\r\n"
"// NUMBER\r\n"
"// LIST\r\n"
"//\r\n"
"// type info:\r\n"
"// BOOL no type info\r\n"
"// NUMBER min max range, use -1 -1 for no limits\r\n"
"// STRING no type info\r\n"
"// LIST "" delimited list of options value pairs\r\n"
"//\r\n"
"//\r\n"
"// default depends on type\r\n"
"// BOOL is \"0\" or \"1\"\r\n"
"// NUMBER is \"value\"\r\n"
"// STRING is \"value\"\r\n"
"// LIST is \"index\", where index \"0\" is the first element of the list\r\n\r\n\r\n" );
setDescription ( "SERVER_OPTIONS" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CServerDescription::WriteScriptHeader( FileHandle_t fp )
{
char am_pm[] = "AM";
tm newtime;
Plat_GetLocalTime( &newtime );
if( newtime.tm_hour > 12 ) /* Set up extension. */
Q_strncpy( am_pm, "PM", sizeof( am_pm ) );
if( newtime.tm_hour > 12 ) /* Convert from 24-hour */
newtime.tm_hour -= 12; /* to 12-hour clock. */
if( newtime.tm_hour == 0 ) /*Set hour to 12 if midnight. */
newtime.tm_hour = 12;
g_pFullFileSystem->FPrintf( fp, (char *)getHint() );
char timeString[64];
Plat_GetTimeString( &newtime, timeString, sizeof( timeString ) );
// Write out the comment and Cvar Info:
g_pFullFileSystem->FPrintf( fp, "// Half-Life Server Configuration Layout Script (stores last settings chosen, too)\r\n" );
g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", timeString, am_pm );
g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" );
g_pFullFileSystem->FPrintf( fp, "VERSION %.1f\r\n\r\n", SCRIPT_VERSION );
g_pFullFileSystem->FPrintf( fp, "DESCRIPTION SERVER_OPTIONS\r\n{\r\n" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CServerDescription::WriteFileHeader( FileHandle_t fp )
{
char am_pm[] = "AM";
tm newtime;
Plat_GetLocalTime( &newtime );
if( newtime.tm_hour > 12 ) /* Set up extension. */
Q_strncpy( am_pm, "PM", sizeof( am_pm ) );
if( newtime.tm_hour > 12 ) /* Convert from 24-hour */
newtime.tm_hour -= 12; /* to 12-hour clock. */
if( newtime.tm_hour == 0 ) /*Set hour to 12 if midnight. */
newtime.tm_hour = 12;
char timeString[64];
Plat_GetTimeString( &newtime, timeString, sizeof( timeString ) );
g_pFullFileSystem->FPrintf( fp, "// Half-Life Server Configuration Settings\r\n" );
g_pFullFileSystem->FPrintf( fp, "// DO NOT EDIT, GENERATED BY HALF-LIFE\r\n" );
g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", timeString, am_pm );
g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" );
}

View File

@@ -0,0 +1,48 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CREATEMULTIPLAYERGAMEGAMEPLAYPAGE_H
#define CREATEMULTIPLAYERGAMEGAMEPLAYPAGE_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/PropertyPage.h>
class CPanelListPanel;
class CDescription;
class mpcontrol_t;
//-----------------------------------------------------------------------------
// Purpose: server options page of the create game server dialog
//-----------------------------------------------------------------------------
class CCreateMultiplayerGameGameplayPage : public vgui::PropertyPage
{
public:
CCreateMultiplayerGameGameplayPage(vgui::Panel *parent, const char *name);
~CCreateMultiplayerGameGameplayPage();
// returns currently entered information about the server
int GetMaxPlayers();
const char *GetPassword();
const char *GetHostName();
protected:
virtual void OnApplyChanges();
private:
const char *GetValue(const char *cvarName, const char *defaultValue);
void LoadGameOptionsList();
void GatherCurrentValues();
CDescription *m_pDescription;
mpcontrol_t *m_pList;
CPanelListPanel *m_pOptionsList;
};
#endif // CREATEMULTIPLAYERGAMEGAMEPLAYPAGE_H

View File

@@ -0,0 +1,300 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "CreateMultiplayerGameServerPage.h"
using namespace vgui;
#include <KeyValues.h>
#include <vgui_controls/ComboBox.h>
#include <vgui_controls/RadioButton.h>
#include <vgui_controls/CheckButton.h>
#include "FileSystem.h"
#include "tier1/convar.h"
#include "EngineInterface.h"
#include "CvarToggleCheckButton.h"
#include "ModInfo.h"
// for SRC
#include <vstdlib/random.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#define RANDOM_MAP "#GameUI_RandomMap"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CCreateMultiplayerGameServerPage::CCreateMultiplayerGameServerPage(vgui::Panel *parent, const char *name) : PropertyPage(parent, name)
{
m_pSavedData = NULL;
// we can use this if we decide we want to put "listen server" at the end of the game name
m_pMapList = new ComboBox(this, "MapList", 12, false);
m_pEnableBotsCheck = new CheckButton( this, "EnableBotsCheck", "" );
m_pEnableBotsCheck->SetVisible( false );
m_pEnableBotsCheck->SetEnabled( false );
LoadControlSettings("Resource/CreateMultiplayerGameServerPage.res");
LoadMapList();
m_szMapName[0] = 0;
// initialize hostname
SetControlString("ServerNameEdit", ModInfo().GetGameName());//szHostName);
// initialize password
// SetControlString("PasswordEdit", engine->pfnGetCvarString("sv_password"));
ConVarRef var( "sv_password" );
if ( var.IsValid() )
{
SetControlString("PasswordEdit", var.GetString() );
}
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CCreateMultiplayerGameServerPage::~CCreateMultiplayerGameServerPage()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameServerPage::EnableBots( KeyValues *data )
{
m_pSavedData = data;
int quota = data->GetInt( "bot_quota", 0 );
SetControlInt( "BotQuotaCombo", quota );
m_pEnableBotsCheck->SetSelected( (quota > 0) );
int difficulty = data->GetInt( "bot_difficulty", 0 );
difficulty = MAX( difficulty, 0 );
difficulty = MIN( 3, difficulty );
char buttonName[64];
Q_snprintf( buttonName, sizeof( buttonName ), "SkillLevel%d", difficulty );
vgui::RadioButton *button = dynamic_cast< vgui::RadioButton * >(FindChildByName( buttonName ));
if ( button )
{
button->SetSelected( true );
}
}
//-----------------------------------------------------------------------------
// Purpose: called to get the info from the dialog
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameServerPage::OnApplyChanges()
{
KeyValues *kv = m_pMapList->GetActiveItemUserData();
Q_strncpy(m_szMapName, kv->GetString("mapname", ""), DATA_STR_LENGTH);
if ( m_pSavedData )
{
int quota = GetControlInt( "BotQuotaCombo", 0 );
if ( !m_pEnableBotsCheck->IsSelected() )
{
quota = 0;
}
m_pSavedData->SetInt( "bot_quota", quota );
ConVarRef bot_quota( "bot_quota" );
bot_quota.SetValue( quota );
int difficulty = 0;
for ( int i=0; i<4; ++i )
{
char buttonName[64];
Q_snprintf( buttonName, sizeof( buttonName ), "SkillLevel%d", i );
vgui::RadioButton *button = dynamic_cast< vgui::RadioButton * >(FindChildByName( buttonName ));
if ( button )
{
if ( button->IsSelected() )
{
difficulty = i;
break;
}
}
}
m_pSavedData->SetInt( "bot_difficulty", difficulty );
ConVarRef bot_difficulty( "bot_difficulty" );
bot_difficulty.SetValue( difficulty );
}
}
//-----------------------------------------------------------------------------
// Purpose: loads the list of available maps into the map list
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameServerPage::LoadMaps( const char *pszPathID )
{
FileFindHandle_t findHandle = NULL;
KeyValues *hiddenMaps = ModInfo().GetHiddenMaps();
const char *pszFilename = g_pFullFileSystem->FindFirst( "maps/*.bsp", &findHandle );
while ( pszFilename )
{
const char *str = NULL;
char *ext = NULL;
char mapname[256];
// FindFirst ignores the pszPathID, so check it here
// TODO: this doesn't find maps in fallback dirs
Q_snprintf( mapname, sizeof(mapname), "maps/%s", pszFilename );
if ( !g_pFullFileSystem->FileExists( mapname, pszPathID ) )
{
goto nextFile;
}
// remove the text 'maps/' and '.bsp' from the file name to get the map name
str = Q_strstr( pszFilename, "maps" );
if ( str )
{
Q_strncpy( mapname, str + 5, sizeof(mapname) - 1 ); // maps + \\ = 5
}
else
{
Q_strncpy( mapname, pszFilename, sizeof(mapname) - 1 );
}
ext = Q_strstr( mapname, ".bsp" );
if ( ext )
{
*ext = 0;
}
//!! hack: strip out single player HL maps
// this needs to be specified in a seperate file
if ( !stricmp( ModInfo().GetGameName(), "Half-Life" ) && ( mapname[0] == 'c' || mapname[0] == 't') && mapname[2] == 'a' && mapname[1] >= '0' && mapname[1] <= '5' )
{
goto nextFile;
}
// strip out maps that shouldn't be displayed
if ( hiddenMaps )
{
if ( hiddenMaps->GetInt( mapname, 0 ) )
{
goto nextFile;
}
}
// add to the map list
m_pMapList->AddItem( mapname, new KeyValues( "data", "mapname", mapname ) );
// get the next file
nextFile:
pszFilename = g_pFullFileSystem->FindNext( findHandle );
}
g_pFullFileSystem->FindClose( findHandle );
}
//-----------------------------------------------------------------------------
// Purpose: loads the list of available maps into the map list
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameServerPage::LoadMapList()
{
// clear the current list (if any)
m_pMapList->DeleteAllItems();
// add special "name" to represent loading a randomly selected map
m_pMapList->AddItem( RANDOM_MAP, new KeyValues( "data", "mapname", RANDOM_MAP ) );
// iterate the filesystem getting the list of all the files
// UNDONE: steam wants this done in a special way, need to support that
const char *pathID = "MOD";
if ( !stricmp(ModInfo().GetGameName(), "Half-Life" ) )
{
pathID = NULL; // hl is the base dir
}
// Load the GameDir maps
LoadMaps( pathID );
// If we're not the Valve directory and we're using a "fallback_dir" in gameinfo.txt then include those maps...
// (pathID is NULL if we're "Half-Life")
const char *pszFallback = ModInfo().GetFallbackDir();
if ( pathID && pszFallback[0] )
{
LoadMaps( "GAME_FALLBACK" );
}
// set the first item to be selected
m_pMapList->ActivateItem( 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CCreateMultiplayerGameServerPage::IsRandomMapSelected()
{
const char *mapname = m_pMapList->GetActiveItemUserData()->GetString("mapname");
if (!stricmp( mapname, RANDOM_MAP ))
{
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CCreateMultiplayerGameServerPage::GetMapName()
{
int count = m_pMapList->GetItemCount();
// if there is only one entry it's the special "select random map" entry
if( count <= 1 )
return NULL;
const char *mapname = m_pMapList->GetActiveItemUserData()->GetString("mapname");
if (!strcmp( mapname, RANDOM_MAP ))
{
int which = RandomInt( 1, count - 1 );
mapname = m_pMapList->GetItemUserData( which )->GetString("mapname");
}
return mapname;
}
//-----------------------------------------------------------------------------
// Purpose: Sets currently selected map in the map combobox
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameServerPage::SetMap(const char *mapName)
{
for (int i = 0; i < m_pMapList->GetItemCount(); i++)
{
if (!m_pMapList->IsItemIDValid(i))
continue;
if (!stricmp(m_pMapList->GetItemUserData(i)->GetString("mapname"), mapName))
{
m_pMapList->ActivateItem(i);
break;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCreateMultiplayerGameServerPage::OnCheckButtonChecked()
{
SetControlEnabled("SkillLevel0", m_pEnableBotsCheck->IsSelected());
SetControlEnabled("SkillLevel1", m_pEnableBotsCheck->IsSelected());
SetControlEnabled("SkillLevel2", m_pEnableBotsCheck->IsSelected());
SetControlEnabled("SkillLevel3", m_pEnableBotsCheck->IsSelected());
SetControlEnabled("BotQuotaCombo", m_pEnableBotsCheck->IsSelected());
SetControlEnabled("BotQuotaLabel", m_pEnableBotsCheck->IsSelected());
SetControlEnabled("BotDifficultyLabel", m_pEnableBotsCheck->IsSelected());
}

View File

@@ -0,0 +1,56 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CREATEMULTIPLAYERGAMESERVERPAGE_H
#define CREATEMULTIPLAYERGAMESERVERPAGE_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/PropertyPage.h>
#include "cvartogglecheckbutton.h"
//-----------------------------------------------------------------------------
// Purpose: server options page of the create game server dialog
//-----------------------------------------------------------------------------
class CCreateMultiplayerGameServerPage : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( CCreateMultiplayerGameServerPage, vgui::PropertyPage );
public:
CCreateMultiplayerGameServerPage(vgui::Panel *parent, const char *name);
~CCreateMultiplayerGameServerPage();
// returns currently entered information about the server
void SetMap(const char *name);
bool IsRandomMapSelected();
const char *GetMapName();
// CS Bots
void EnableBots( KeyValues *data );
int GetBotQuota( void );
bool GetBotsEnabled( void );
protected:
virtual void OnApplyChanges();
MESSAGE_FUNC( OnCheckButtonChecked, "CheckButtonChecked" );
private:
void LoadMapList();
void LoadMaps( const char *pszPathID );
vgui::ComboBox *m_pMapList;
vgui::CheckButton *m_pEnableBotsCheck;
CCvarToggleCheckButton *m_pEnableTutorCheck;
KeyValues *m_pSavedData;
enum { DATA_STR_LENGTH = 64 };
char m_szMapName[DATA_STR_LENGTH];
};
#endif // CREATEMULTIPLAYERGAMESERVERPAGE_H

View File

@@ -0,0 +1,92 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "CustomTabExplanationDialog.h"
#include "BasePanel.h"
#include "convar.h"
#include "EngineInterface.h"
#include "GameUI_Interface.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
#include "ModInfo.h"
#include <stdio.h>
using namespace vgui;
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCustomTabExplanationDialog::CCustomTabExplanationDialog(vgui::Panel *parent) : BaseClass(parent, "CustomTabExplanationDialog")
{
SetDeleteSelfOnClose(true);
SetSizeable( false );
input()->SetAppModalSurface(GetVPanel());
LoadControlSettings("Resource/CustomTabExplanationDialog.res");
MoveToCenterOfScreen();
GameUI().PreventEngineHideGameUI();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCustomTabExplanationDialog::~CCustomTabExplanationDialog()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomTabExplanationDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
SetDialogVariable( "game", ModInfo().GetGameName() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomTabExplanationDialog::OnKeyCodePressed(KeyCode code)
{
if (code == KEY_ESCAPE)
{
Close();
}
else
{
BaseClass::OnKeyCodePressed(code);
}
}
//-----------------------------------------------------------------------------
// Purpose: handles button commands
//-----------------------------------------------------------------------------
void CCustomTabExplanationDialog::OnCommand( const char *command )
{
if ( !stricmp( command, "ok" ) || !stricmp( command, "cancel" ) || !stricmp( command, "close" ) )
{
Close();
}
else
{
BaseClass::OnCommand( command );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCustomTabExplanationDialog::OnClose( void )
{
BaseClass::OnClose();
}

View File

@@ -0,0 +1,35 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef CUSTOMTABEXPLANATIONDIALOG_H
#define CUSTOMTABEXPLANATIONDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/Frame.h"
#include "UtlVector.h"
#include <vgui/KeyCode.h>
#include "vgui_controls/URLLabel.h"
//-----------------------------------------------------------------------------
// Purpose: Dialog that explains the custom tab
//-----------------------------------------------------------------------------
class CCustomTabExplanationDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CCustomTabExplanationDialog, vgui::Frame );
public:
CCustomTabExplanationDialog(vgui::Panel *parent);
~CCustomTabExplanationDialog();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnKeyCodePressed(vgui::KeyCode code);
virtual void OnCommand( const char *command );
virtual void OnClose( void );
};
#endif // CUSTOMTABEXPLANATIONDIALOG_H

View File

@@ -0,0 +1,136 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "CvarNegateCheckButton.h"
#include "EngineInterface.h"
#include <vgui/IVGui.h>
#include "IGameUIFuncs.h"
#include "tier1/KeyValues.h"
#include "tier1/convar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
CCvarNegateCheckButton::CCvarNegateCheckButton( Panel *parent, const char *panelName, const char *text,
const char *cvarname )
: CheckButton( parent, panelName, text )
{
m_pszCvarName = cvarname ? strdup( cvarname ) : NULL;
Reset();
AddActionSignalTarget( this );
}
CCvarNegateCheckButton::~CCvarNegateCheckButton()
{
free( m_pszCvarName );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarNegateCheckButton::Paint()
{
if ( !m_pszCvarName )
{
BaseClass::Paint();
return;
}
// Look up current value
// float value = engine->pfnGetCvarFloat( m_pszCvarName );
ConVarRef var( m_pszCvarName );
if ( !var.IsValid() )
return;
float value = var.GetFloat();
if ( value < 0 )
{
if ( !m_bStartState )
{
SetSelected( true );
m_bStartState = true;
}
}
else
{
if ( m_bStartState )
{
SetSelected( false );
m_bStartState = false;
}
}
BaseClass::Paint();
}
void CCvarNegateCheckButton::Reset()
{
// Look up current value
// float value = engine->pfnGetCvarFloat( m_pszCvarName );
ConVarRef var( m_pszCvarName );
if ( !var.IsValid() )
return;
float value = var.GetFloat();
if ( value < 0 )
{
m_bStartState = true;
}
else
{
m_bStartState = false;
}
SetSelected(m_bStartState);
}
bool CCvarNegateCheckButton::HasBeenModified()
{
return IsSelected() != m_bStartState;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *panel -
//-----------------------------------------------------------------------------
void CCvarNegateCheckButton::SetSelected( bool state )
{
BaseClass::SetSelected( state );
}
void CCvarNegateCheckButton::ApplyChanges()
{
if ( !m_pszCvarName || !m_pszCvarName[ 0 ] )
return;
ConVarRef var( m_pszCvarName );
float value = var.GetFloat();
value = (float)fabs( value );
if (value < 0.00001)
{
// correct the value if it's not set
value = 0.022f;
}
m_bStartState = IsSelected();
value = -value;
float ans = m_bStartState ? value : -value;
var.SetValue( ans );
}
void CCvarNegateCheckButton::OnButtonChecked()
{
if (HasBeenModified())
{
PostActionSignal(new KeyValues("ControlModified"));
}
}

View File

@@ -0,0 +1,39 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CVARNEGATECHECKBUTTON_H
#define CVARNEGATECHECKBUTTON_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/CheckButton.h>
class CCvarNegateCheckButton : public vgui::CheckButton
{
DECLARE_CLASS_SIMPLE( CCvarNegateCheckButton, vgui::CheckButton );
public:
CCvarNegateCheckButton( vgui::Panel *parent, const char *panelName, const char *text,
char const *cvarname );
~CCvarNegateCheckButton();
virtual void SetSelected( bool state );
virtual void Paint();
void Reset();
void ApplyChanges();
bool HasBeenModified();
private:
MESSAGE_FUNC( OnButtonChecked, "CheckButtonChecked" );
char *m_pszCvarName;
bool m_bStartState;
};
#endif // CVARNEGATECHECKBUTTON_H

View File

@@ -0,0 +1,317 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "CvarSlider.h"
#include <stdio.h>
#include "EngineInterface.h"
#include "tier1/KeyValues.h"
#include "tier1/convar.h"
#include <vgui/IVGui.h>
#include <vgui_controls/propertypage.h>
#define CVARSLIDER_SCALE_FACTOR 100.0f
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( CCvarSlider );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCvarSlider::CCvarSlider( Panel *parent, const char *name ) : Slider( parent, name )
{
SetupSlider( 0, 1, "", false );
m_bCreatedInCode = false;
AddActionSignalTarget( this );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCvarSlider::CCvarSlider( Panel *parent, const char *panelName, char const *caption,
float minValue, float maxValue, char const *cvarname, bool bAllowOutOfRange )
: Slider( parent, panelName )
{
AddActionSignalTarget( this );
SetupSlider( minValue, maxValue, cvarname, bAllowOutOfRange );
// For backwards compatability. Ignore .res file settings for forced setup sliders.
m_bCreatedInCode = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarSlider::SetupSlider( float minValue, float maxValue, const char *cvarname, bool bAllowOutOfRange )
{
m_flMinValue = minValue;
m_flMaxValue = maxValue;
// scale by CVARSLIDER_SCALE_FACTOR
SetRange( (int)( CVARSLIDER_SCALE_FACTOR * minValue ), (int)( CVARSLIDER_SCALE_FACTOR * maxValue ) );
char szMin[ 32 ];
char szMax[ 32 ];
Q_snprintf( szMin, sizeof( szMin ), "%.2f", minValue );
Q_snprintf( szMax, sizeof( szMax ), "%.2f", maxValue );
SetTickCaptions( szMin, szMax );
Q_strncpy( m_szCvarName, cvarname, sizeof( m_szCvarName ) );
m_bModifiedOnce = false;
m_bAllowOutOfRange = bAllowOutOfRange;
// Set slider to current value
Reset();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CCvarSlider::~CCvarSlider()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarSlider::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
if ( !m_bCreatedInCode )
{
float minValue = inResourceData->GetFloat( "minvalue", 0 );
float maxValue = inResourceData->GetFloat( "maxvalue", 1 );
const char *cvarname = inResourceData->GetString( "cvar_name", "" );
bool bAllowOutOfRange = inResourceData->GetBool( "allowoutofrange", false );
SetupSlider( minValue, maxValue, cvarname, bAllowOutOfRange );
if ( GetParent() )
{
// HACK: If our parent is a property page, we want the dialog containing it
if ( dynamic_cast<vgui::PropertyPage*>(GetParent()) && GetParent()->GetParent() )
{
GetParent()->GetParent()->AddActionSignalTarget( this );
}
else
{
GetParent()->AddActionSignalTarget( this );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Get control settings for editing
//-----------------------------------------------------------------------------
void CCvarSlider::GetSettings( KeyValues *outResourceData )
{
BaseClass::GetSettings(outResourceData);
if ( !m_bCreatedInCode )
{
outResourceData->SetFloat( "minvalue", m_flMinValue );
outResourceData->SetFloat( "maxvalue", m_flMaxValue );
outResourceData->SetString( "cvar_name", m_szCvarName );
outResourceData->SetBool( "allowoutofrange", m_bAllowOutOfRange );
}
}
void CCvarSlider::SetCVarName( char const *cvarname )
{
Q_strncpy( m_szCvarName, cvarname, sizeof( m_szCvarName ) );
m_bModifiedOnce = false;
// Set slider to current value
Reset();
}
void CCvarSlider::SetMinMaxValues( float minValue, float maxValue, bool bSetTickDisplay )
{
SetRange( (int)( CVARSLIDER_SCALE_FACTOR * minValue ), (int)( CVARSLIDER_SCALE_FACTOR * maxValue ) );
if ( bSetTickDisplay )
{
char szMin[ 32 ];
char szMax[ 32 ];
Q_snprintf( szMin, sizeof( szMin ), "%.2f", minValue );
Q_snprintf( szMax, sizeof( szMax ), "%.2f", maxValue );
SetTickCaptions( szMin, szMax );
}
// Set slider to current value
Reset();
}
void CCvarSlider::SetTickColor( Color color )
{
m_TickColor = color;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarSlider::Paint()
{
// Get engine's current value
// float curvalue = engine->pfnGetCvarFloat( m_szCvarName );
ConVarRef var( m_szCvarName );
if ( !var.IsValid() )
return;
float curvalue = var.GetFloat();
// did it get changed from under us?
if (curvalue != m_fStartValue)
{
int val = (int)( CVARSLIDER_SCALE_FACTOR * curvalue );
m_fStartValue = curvalue;
m_fCurrentValue = curvalue;
SetValue( val );
m_iStartValue = GetValue();
}
BaseClass::Paint();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarSlider::ApplyChanges()
{
if (m_bModifiedOnce)
{
m_iStartValue = GetValue();
if (m_bAllowOutOfRange)
{
m_fStartValue = m_fCurrentValue;
}
else
{
m_fStartValue = (float) m_iStartValue / CVARSLIDER_SCALE_FACTOR;
}
//engine->Cvar_SetValue( m_szCvarName, m_fStartValue );
ConVarRef var( m_szCvarName );
var.SetValue( (float)m_fStartValue );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CCvarSlider::GetSliderValue()
{
if (m_bAllowOutOfRange)
{
return m_fCurrentValue;
}
else
{
return ((float)GetValue())/ CVARSLIDER_SCALE_FACTOR;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarSlider::SetSliderValue(float fValue)
{
int nVal = (int)( CVARSLIDER_SCALE_FACTOR * fValue );
SetValue( nVal, false);
// remember this slider value
m_iLastSliderValue = GetValue();
if (m_fCurrentValue != fValue)
{
m_fCurrentValue = fValue;
m_bModifiedOnce = true;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarSlider::Reset()
{
// Set slider to current value
// m_fStartValue = engine->pfnGetCvarFloat( m_szCvarName );
ConVarRef var( m_szCvarName );
if ( !var.IsValid() )
{
m_fCurrentValue = m_fStartValue = 0.0f;
SetValue( 0 );
m_iStartValue = GetValue();
m_iLastSliderValue = m_iStartValue;
return;
}
float m_fStartValue = var.GetFloat();
m_fCurrentValue = m_fStartValue;
int value = (int)( CVARSLIDER_SCALE_FACTOR * m_fStartValue );
SetValue( value );
m_iStartValue = GetValue();
m_iLastSliderValue = m_iStartValue;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CCvarSlider::HasBeenModified()
{
if (GetValue() != m_iStartValue)
{
m_bModifiedOnce = true;
}
return m_bModifiedOnce;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : position -
//-----------------------------------------------------------------------------
void CCvarSlider::OnSliderMoved()
{
if (HasBeenModified())
{
if (m_iLastSliderValue != GetValue())
{
m_iLastSliderValue = GetValue();
m_fCurrentValue = ((float) m_iLastSliderValue)/CVARSLIDER_SCALE_FACTOR;
}
// tell parent that we've been modified
PostActionSignal(new KeyValues("ControlModified"));
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarSlider::OnApplyChanges( void )
{
if ( !m_bCreatedInCode )
{
ApplyChanges();
}
}

View File

@@ -0,0 +1,61 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CVARSLIDER_H
#define CVARSLIDER_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Slider.h>
class CCvarSlider : public vgui::Slider
{
DECLARE_CLASS_SIMPLE( CCvarSlider, vgui::Slider );
public:
CCvarSlider( vgui::Panel *parent, const char *panelName );
CCvarSlider( vgui::Panel *parent, const char *panelName, char const *caption,
float minValue, float maxValue, char const *cvarname, bool bAllowOutOfRange=false );
~CCvarSlider();
void SetupSlider( float minValue, float maxValue, const char *cvarname, bool bAllowOutOfRange );
void SetCVarName( char const *cvarname );
void SetMinMaxValues( float minValue, float maxValue, bool bSetTickdisplay = true );
void SetTickColor( Color color );
virtual void Paint();
virtual void ApplySettings( KeyValues *inResourceData );
virtual void GetSettings( KeyValues *outResourceData );
void ApplyChanges();
float GetSliderValue();
void SetSliderValue(float fValue);
void Reset();
bool HasBeenModified();
private:
MESSAGE_FUNC( OnSliderMoved, "SliderMoved" );
MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" );
bool m_bAllowOutOfRange;
bool m_bModifiedOnce;
float m_fStartValue;
int m_iStartValue;
int m_iLastSliderValue;
float m_fCurrentValue;
char m_szCvarName[ 64 ];
bool m_bCreatedInCode;
float m_flMinValue;
float m_flMaxValue;
};
#endif // CVARSLIDER_H

View File

@@ -0,0 +1,112 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "CvarTextEntry.h"
#include "EngineInterface.h"
#include <vgui/IVGui.h>
#include "IGameUIFuncs.h"
#include "tier1/KeyValues.h"
#include "tier1/convar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
static const int MAX_CVAR_TEXT = 64;
CCvarTextEntry::CCvarTextEntry( Panel *parent, const char *panelName, char const *cvarname )
: TextEntry( parent, panelName)
{
m_pszCvarName = cvarname ? strdup( cvarname ) : NULL;
m_pszStartValue[0] = 0;
if ( m_pszCvarName )
{
Reset();
}
AddActionSignalTarget( this );
}
CCvarTextEntry::~CCvarTextEntry()
{
if ( m_pszCvarName )
{
free( m_pszCvarName );
}
}
void CCvarTextEntry::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
if (GetMaximumCharCount() < 0 || GetMaximumCharCount() > MAX_CVAR_TEXT)
{
SetMaximumCharCount(MAX_CVAR_TEXT - 1);
}
}
void CCvarTextEntry::ApplyChanges( bool immediate )
{
if ( !m_pszCvarName )
return;
char szText[ MAX_CVAR_TEXT ];
GetText( szText, MAX_CVAR_TEXT );
if ( !szText[ 0 ] )
return;
if ( immediate )
{
// set immediately - don't wait for the next frame
ConVarRef newCvar( m_pszCvarName );
newCvar.SetValue( szText );
}
else
{
char szCommand[ 256 ];
Q_snprintf( szCommand, ARRAYSIZE( szCommand ), "%s \"%s\"\n", m_pszCvarName, szText );
engine->ClientCmd_Unrestricted( szCommand );
}
Q_strncpy( m_pszStartValue, szText, sizeof( m_pszStartValue ) );
}
void CCvarTextEntry::Reset()
{
// char *value = engine->pfnGetCvarString( m_pszCvarName );
ConVarRef var( m_pszCvarName );
if ( !var.IsValid() )
return;
const char *value = var.GetString();
if ( value && value[ 0 ] )
{
SetText( value );
Q_strncpy( m_pszStartValue, value, sizeof( m_pszStartValue ) );
}
}
bool CCvarTextEntry::HasBeenModified()
{
char szText[ MAX_CVAR_TEXT ];
GetText( szText, MAX_CVAR_TEXT );
return stricmp( szText, m_pszStartValue ) != 0 ? true : false;
}
void CCvarTextEntry::OnTextChanged()
{
if ( !m_pszCvarName )
return;
if (HasBeenModified())
{
PostActionSignal(new KeyValues("ControlModified"));
}
}

View File

@@ -0,0 +1,35 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CVARTEXTENTRY_H
#define CVARTEXTENTRY_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/TextEntry.h>
class CCvarTextEntry : public vgui::TextEntry
{
DECLARE_CLASS_SIMPLE( CCvarTextEntry, vgui::TextEntry );
public:
CCvarTextEntry( vgui::Panel *parent, const char *panelName, char const *cvarname );
~CCvarTextEntry();
MESSAGE_FUNC( OnTextChanged, "TextChanged" );
void ApplyChanges( bool immediate = false );
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
void Reset();
bool HasBeenModified();
private:
char *m_pszCvarName;
char m_pszStartValue[64];
};
#endif // CVARTEXTENTRY_H

View File

@@ -0,0 +1,157 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "CvarToggleCheckButton.h"
#include "EngineInterface.h"
#include <vgui/IVGui.h>
#include "tier1/KeyValues.h"
#include "tier1/convar.h"
#include "IGameUIFuncs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
vgui::Panel *CvarToggleCheckButton_Factory()
{
return new CCvarToggleCheckButton( NULL, NULL, "CvarToggleCheckButton", NULL );
}
DECLARE_BUILD_FACTORY_CUSTOM( CCvarToggleCheckButton, CvarToggleCheckButton_Factory );
CCvarToggleCheckButton::CCvarToggleCheckButton( Panel *parent, const char *panelName, const char *text,
char const *cvarname )
: CheckButton( parent, panelName, text )
{
m_pszCvarName = cvarname ? strdup( cvarname ) : NULL;
if (m_pszCvarName)
{
Reset();
}
AddActionSignalTarget( this );
}
CCvarToggleCheckButton::~CCvarToggleCheckButton()
{
if ( m_pszCvarName )
{
free( m_pszCvarName );
}
}
void CCvarToggleCheckButton::Paint()
{
if ( !m_pszCvarName || !m_pszCvarName[ 0 ] )
{
BaseClass::Paint();
return;
}
// Look up current value
// bool value = engine->pfnGetCvarFloat( m_pszCvarName ) > 0.0f ? true : false;
ConVarRef var( m_pszCvarName );
if ( !var.IsValid() )
return;
bool value = var.GetBool();
if ( value != m_bStartValue )
//if ( value != IsSelected() )
{
SetSelected( value );
m_bStartValue = value;
}
BaseClass::Paint();
}
void CCvarToggleCheckButton::ApplyChanges()
{
if ( !m_pszCvarName || !m_pszCvarName[ 0 ] )
return;
m_bStartValue = IsSelected();
// engine->Cvar_SetValue( m_pszCvarName, m_bStartValue ? 1.0f : 0.0f );
ConVarRef var( m_pszCvarName );
var.SetValue( m_bStartValue );
}
void CCvarToggleCheckButton::Reset()
{
// m_bStartValue = engine->pfnGetCvarFloat( m_pszCvarName ) > 0.0f ? true : false;
if ( !m_pszCvarName || !m_pszCvarName[ 0 ] )
return;
ConVarRef var( m_pszCvarName );
if ( !var.IsValid() )
return;
m_bStartValue = var.GetBool();
SetSelected(m_bStartValue);
}
bool CCvarToggleCheckButton::HasBeenModified()
{
return IsSelected() != m_bStartValue;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *panel -
//-----------------------------------------------------------------------------
void CCvarToggleCheckButton::SetSelected( bool state )
{
BaseClass::SetSelected( state );
if ( !m_pszCvarName || !m_pszCvarName[ 0 ] )
return;
/*
// Look up current value
bool value = state;
engine->Cvar_SetValue( m_pszCvarName, value ? 1.0f : 0.0f );*/
}
//-----------------------------------------------------------------------------
void CCvarToggleCheckButton::OnButtonChecked()
{
if (HasBeenModified())
{
PostActionSignal(new KeyValues("ControlModified"));
}
}
//-----------------------------------------------------------------------------
void CCvarToggleCheckButton::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
const char *cvarName = inResourceData->GetString("cvar_name", "");
const char *cvarValue = inResourceData->GetString("cvar_value", "");
if( Q_stricmp( cvarName, "") == 0 )
return;// Doesn't have cvar set up in res file, must have been constructed with it.
if( m_pszCvarName )
free( m_pszCvarName );// got a "", not a NULL from the create-control call
m_pszCvarName = cvarName ? strdup( cvarName ) : NULL;
if( Q_stricmp( cvarValue, "1") == 0 )
m_bStartValue = true;
else
m_bStartValue = false;
const ConVar *var = cvar->FindVar( m_pszCvarName );
if ( var )
{
if( var->GetBool() )
SetSelected( true );
else
SetSelected( false );
}
}

View File

@@ -0,0 +1,41 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CVARTOGGLECHECKBUTTON_H
#define CVARTOGGLECHECKBUTTON_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/CheckButton.h>
class CCvarToggleCheckButton : public vgui::CheckButton
{
DECLARE_CLASS_SIMPLE( CCvarToggleCheckButton, vgui::CheckButton );
public:
CCvarToggleCheckButton( vgui::Panel *parent, const char *panelName, const char *text,
char const *cvarname );
~CCvarToggleCheckButton();
virtual void SetSelected( bool state );
virtual void Paint();
void Reset();
void ApplyChanges();
bool HasBeenModified();
virtual void ApplySettings( KeyValues *inResourceData );
private:
MESSAGE_FUNC( OnButtonChecked, "CheckButtonChecked" );
char *m_pszCvarName;
bool m_bStartValue;
};
#endif // CVARTOGGLECHECKBUTTON_H

View File

@@ -0,0 +1,60 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Includes all the headers/declarations necessary to access the
// engine interface
//
// $NoKeywords: $
//=============================================================================//
#ifndef ENGINEINTERFACE_H
#define ENGINEINTERFACE_H
#ifdef _WIN32
#pragma once
#endif
// these stupid set of includes are required to use the cdll_int interface
#include "mathlib/vector.h"
//#include "wrect.h"
#define IN_BUTTONS_H
// engine interface
#include "cdll_int.h"
#include "eiface.h"
#include "icvar.h"
#include "tier2/tier2.h"
#include "matchmaking/imatchframework.h"
#ifdef SWARM_DLL
#include "matchmaking/swarm/imatchext_swarm.h"
extern class IMatchExtSwarm *g_pMatchExt;
#endif
#ifdef PORTAL2
class IMatchExtPortal2
{
public:
inline KeyValues * GetAllMissions() { return NULL; }
inline KeyValues * GetMapInfoByBspName( KeyValues *, char const *, KeyValues ** = NULL ) { return NULL; }
inline KeyValues * GetMapInfo( KeyValues *, KeyValues ** = NULL ) { return NULL; }
};
extern class IMatchExtPortal2 *g_pMatchExt;
#endif
// engine interface singleton accessors
extern IVEngineClient *engine;
extern class IBik *bik;
extern class IEngineVGui *enginevguifuncs;
extern class IGameUIFuncs *gameuifuncs;
extern class IEngineSound *enginesound;
extern class IXboxSystem *xboxsystem;
#ifdef _GAMECONSOLE
extern class IXOnline *xonline;
#endif
extern class CSteamAPIContext *steamapicontext;
#ifdef _PS3
#include "ps3/saverestore_ps3_api_ui.h"
extern class IPS3SaveRestoreToUI *ps3saveuiapi;
#endif
#endif // ENGINEINTERFACE_H

View File

@@ -0,0 +1,148 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#include "GameConsole.h"
#include "GameConsoleDialog.h"
#include "LoadingDialog.h"
#include "vgui/ISurface.h"
#include "KeyValues.h"
#include "vgui/VGUI.h"
#include "vgui/IVGUI.h"
#include "vgui_controls/Panel.h"
#include "convar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static CGameConsole g_GameConsole;
//-----------------------------------------------------------------------------
// Purpose: singleton accessor
//-----------------------------------------------------------------------------
CGameConsole &GameConsole()
{
return g_GameConsole;
}
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CGameConsole, IGameConsole, GAMECONSOLE_INTERFACE_VERSION, g_GameConsole);
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CGameConsole::CGameConsole()
{
m_bInitialized = false;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CGameConsole::~CGameConsole()
{
m_bInitialized = false;
}
//-----------------------------------------------------------------------------
// Purpose: sets up the console for use
//-----------------------------------------------------------------------------
void CGameConsole::Initialize()
{
m_pConsole = vgui::SETUP_PANEL( new CGameConsoleDialog() ); // we add text before displaying this so set it up now!
// set the console to taking up most of the right-half of the screen
int swide, stall;
vgui::surface()->GetScreenSize(swide, stall);
int offset = vgui::scheme()->GetProportionalScaledValue(16);
m_pConsole->SetBounds(
swide / 2 - (offset * 4),
offset,
(swide / 2) + (offset * 3),
stall - (offset * 8));
m_bInitialized = true;
}
//-----------------------------------------------------------------------------
// Purpose: activates the console, makes it visible and brings it to the foreground
//-----------------------------------------------------------------------------
void CGameConsole::Activate()
{
if (!m_bInitialized)
return;
vgui::surface()->RestrictPaintToSinglePanel(NULL);
m_pConsole->Activate();
}
//-----------------------------------------------------------------------------
// Purpose: hides the console
//-----------------------------------------------------------------------------
void CGameConsole::Hide()
{
if (!m_bInitialized)
return;
m_pConsole->Hide();
}
//-----------------------------------------------------------------------------
// Purpose: clears the console
//-----------------------------------------------------------------------------
void CGameConsole::Clear()
{
if (!m_bInitialized)
return;
m_pConsole->Clear();
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the console is currently in focus
//-----------------------------------------------------------------------------
bool CGameConsole::IsConsoleVisible()
{
if (!m_bInitialized)
return false;
return m_pConsole->IsVisible();
}
//-----------------------------------------------------------------------------
// Purpose: activates the console after a delay
//-----------------------------------------------------------------------------
void CGameConsole::ActivateDelayed(float time)
{
if (!m_bInitialized)
return;
m_pConsole->PostMessage(m_pConsole, new KeyValues("Activate"), time);
}
void CGameConsole::SetParent( int parent )
{
if (!m_bInitialized)
return;
m_pConsole->SetParent( static_cast<vgui::VPANEL>( parent ));
}
//-----------------------------------------------------------------------------
// Purpose: static command handler
//-----------------------------------------------------------------------------
void CGameConsole::OnCmdCondump()
{
g_GameConsole.m_pConsole->DumpConsoleTextToFile();
}
CON_COMMAND( condump, "dump the text currently in the console to condumpXX.log" )
{
g_GameConsole.OnCmdCondump();
}

View File

@@ -0,0 +1,54 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMECONSOLE_H
#define GAMECONSOLE_H
#ifdef _WIN32
#pragma once
#endif
#include "GameUI/IGameConsole.h"
class CGameConsoleDialog;
//-----------------------------------------------------------------------------
// Purpose: VGui implementation of the game/dev console
//-----------------------------------------------------------------------------
class CGameConsole : public IGameConsole
{
public:
CGameConsole();
~CGameConsole();
// sets up the console for use
void Initialize();
// activates the console, makes it visible and brings it to the foreground
virtual void Activate();
// hides the console
virtual void Hide();
// clears the console
virtual void Clear();
// returns true if the console is currently in focus
virtual bool IsConsoleVisible();
// activates the console after a delay
void ActivateDelayed(float time);
void SetParent( int parent );
static void OnCmdCondump();
private:
bool m_bInitialized;
CGameConsoleDialog *m_pConsole;
};
extern CGameConsole &GameConsole();
#endif // GAMECONSOLE_H

View File

@@ -0,0 +1,99 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "GameConsoleDialog.h"
#include "GameUI_Interface.h"
#include "vgui/iinput.h"
#include "vgui/isurface.h"
#include "vgui/keycode.h"
#include "LoadingDialog.h"
#include "igameuifuncs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CGameConsoleDialog::CGameConsoleDialog() : BaseClass( NULL, "GameConsole", false )
{
AddActionSignalTarget( this );
}
//-----------------------------------------------------------------------------
// Purpose: generic vgui command handler
//-----------------------------------------------------------------------------
void CGameConsoleDialog::OnCommand(const char *command)
{
if ( !Q_stricmp( command, "Close" ) )
{
if ( GameUI().IsInBackgroundLevel() )
{
// Tell the engine we've hid the console, so that it unpauses the game
// even though we're still sitting at the menu.
engine->ClientCmd_Unrestricted( "unpause" );
}
}
BaseClass::OnCommand(command);
}
//-----------------------------------------------------------------------------
// HACK: Allow F key bindings to operate even when typing in the text entry field
//-----------------------------------------------------------------------------
void CGameConsoleDialog::OnKeyCodeTyped(KeyCode code)
{
BaseClass::OnKeyCodeTyped(code);
// check for processing
if ( m_pConsolePanel->TextEntryHasFocus() )
{
// HACK: Allow F key bindings to operate even here
if ( code >= KEY_F1 && code <= KEY_F12 )
{
// See if there is a binding for the FKey
const char *binding = gameuifuncs->GetBindingForButtonCode( code );
if ( binding && binding[0] )
{
// submit the entry as a console commmand
char szCommand[256];
Q_strncpy( szCommand, binding, sizeof( szCommand ) );
engine->ClientCmd_Unrestricted( szCommand );
}
}
}
}
//-----------------------------------------------------------------------------
// Submits a command
//-----------------------------------------------------------------------------
void CGameConsoleDialog::OnCommandSubmitted( const char *pCommand )
{
engine->ClientCmd_Unrestricted( pCommand );
}
//-----------------------------------------------------------------------------
// Submits a command
//-----------------------------------------------------------------------------
void CGameConsoleDialog::OnClosedByHittingTilde()
{
if ( !LoadingDialog() )
{
GameUI().HideGameUI();
}
else
{
vgui::surface()->RestrictPaintToSinglePanel( LoadingDialog()->GetVPanel() );
}
}

View File

@@ -0,0 +1,40 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef GAMECONSOLEDIALOG_H
#define GAMECONSOLEDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/consoledialog.h"
#include <Color.h>
#include "UtlVector.h"
#include "EngineInterface.h"
#include "vgui_controls/Frame.h"
//-----------------------------------------------------------------------------
// Purpose: Game/dev console dialog
//-----------------------------------------------------------------------------
class CGameConsoleDialog : public vgui::CConsoleDialog
{
DECLARE_CLASS_SIMPLE( CGameConsoleDialog, vgui::CConsoleDialog );
public:
CGameConsoleDialog();
private:
MESSAGE_FUNC( OnClosedByHittingTilde, "ClosedByHittingTilde" );
MESSAGE_FUNC_CHARPTR( OnCommandSubmitted, "CommandSubmitted", command );
virtual void OnKeyCodeTyped( vgui::KeyCode code );
virtual void OnCommand( const char *command );
};
#endif // GAMECONSOLEDIALOG_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines the interface that the GameUI dll exports
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMEUI_INTERFACE_H
#define GAMEUI_INTERFACE_H
#pragma once
#include "GameUI/IGameUI.h"
#include "vgui_controls/Panel.h"
#include "vgui_controls/PHandle.h"
#include "convar.h"
class IGameClientExports;
class CCommand;
//-----------------------------------------------------------------------------
// Purpose: Implementation of GameUI's exposed interface
//-----------------------------------------------------------------------------
class CGameUI : public IGameUI
{
public:
CGameUI();
~CGameUI();
virtual void Initialize( CreateInterfaceFn appFactory );
virtual void Connect( CreateInterfaceFn gameFactory );
virtual void Start();
virtual void Shutdown();
virtual void RunFrame();
virtual void PostInit();
// plays the startup mp3 when GameUI starts
void PlayGameStartupSound();
// Engine wrappers for activating / hiding the gameUI
void ActivateGameUI();
void HideGameUI();
// Toggle allowing the engine to hide the game UI with the escape key
void PreventEngineHideGameUI();
void AllowEngineHideGameUI();
virtual void SetLoadingBackgroundDialog( vgui::VPANEL panel );
// notifications
virtual void OnGameUIActivated();
virtual void OnGameUIHidden();
virtual void OLD_OnConnectToServer( const char *game, int IP, int port ); // OLD: use OnConnectToServer2
virtual void OnConnectToServer2( const char *game, int IP, int connectionPort, int queryPort );
virtual void OnDisconnectFromServer( uint8 eSteamLoginFailure );
virtual void OnLevelLoadingStarted( const char *levelName, bool bShowProgressDialog );
virtual void OnLevelLoadingFinished( bool bError, const char *failureReason, const char *extendedReason );
virtual void OnDisconnectFromServer_OLD( uint8 eSteamLoginFailure, const char *username ) { OnDisconnectFromServer( eSteamLoginFailure ); }
// progress
virtual bool UpdateProgressBar(float progress, const char *statusText);
// Shows progress desc, returns previous setting... (used with custom progress bars )
virtual bool SetShowProgressText( bool show );
// Allows the level loading progress to show map-specific info
virtual void SetProgressLevelName( const char *levelName );
virtual void NeedConnectionProblemWaitScreen();
virtual void ShowPasswordUI( char const *pchCurrentPW );
virtual void SetProgressOnStart();
#if defined( _GAMECONSOLE ) && defined( _DEMO )
virtual void OnDemoTimeout();
#endif
// state
bool IsInLevel();
bool IsInBackgroundLevel();
bool IsInMultiplayer();
bool IsConsoleUI();
bool HasSavedThisMenuSession();
void SetSavedThisMenuSession( bool bState );
void ShowLoadingBackgroundDialog();
void HideLoadingBackgroundDialog();
bool HasLoadingBackgroundDialog();
virtual bool LoadingProgressWantsIsolatedRender( bool bContextValid );
virtual bool IsPlayingFullScreenVideo();
virtual bool IsTransitionEffectEnabled();
private:
void SendConnectedToGameMessage();
virtual void StartProgressBar();
virtual bool ContinueProgressBar(float progressFraction);
virtual void StopProgressBar(bool bError, const char *failureReason, const char *extendedReason = NULL);
virtual bool SetProgressBarStatusText(const char *statusText);
//!! these functions currently not implemented
virtual void SetSecondaryProgressBar(float progress /* range [0..1] */);
virtual void SetSecondaryProgressBarText(const char *statusText);
bool FindPlatformDirectory(char *platformDir, int bufferSize);
void GetUpdateVersion( char *pszProd, char *pszVer);
void ValidateCDKey();
CreateInterfaceFn m_GameFactory;
bool m_bTryingToLoadFriends : 1;
bool m_bActivatedUI : 1;
bool m_bIsConsoleUI : 1;
bool m_bHasSavedThisMenuSession : 1;
bool m_bOpenProgressOnStart : 1;
int m_iGameIP;
int m_iGameConnectionPort;
int m_iGameQueryPort;
int m_iFriendsLoadPauseFrames;
int m_iPlayGameStartupSound;
char m_szPreviousStatusText[128];
char m_szPlatformDir[MAX_PATH];
vgui::DHANDLE<class CCDKeyEntryDialog> m_hCDKeyEntryDialog;
};
// Purpose: singleton accessor
extern CGameUI &GameUI();
// expose client interface
extern IGameClientExports *GameClientExports();
#endif // GAMEUI_INTERFACE_H

View File

@@ -0,0 +1,203 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
#include <stdarg.h>
#include "gameui_util.h"
#include "strtools.h"
#include "EngineInterface.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
static int g_nGameUIActiveSplitscreenPlayerSlot = 0;
int GetGameUIActiveSplitScreenPlayerSlot()
{
return g_nGameUIActiveSplitscreenPlayerSlot;
}
void SetGameUIActiveSplitScreenPlayerSlot( int nSlot )
{
if ( g_nGameUIActiveSplitscreenPlayerSlot != nSlot )
{
g_nGameUIActiveSplitscreenPlayerSlot = nSlot;
}
}
//-----------------------------------------------------------------------------
// Purpose: Scans player names
//Passes the player name to be checked in a KeyValues pointer
//with the keyname "name"
// - replaces '&' with '&&' so they will draw in the scoreboard
// - replaces '#' at the start of the name with '*'
//-----------------------------------------------------------------------------
void GameUI_MakeSafeName( const char *oldName, char *newName, int newNameBufSize )
{
if ( !oldName )
{
newName[0] = 0;
return;
}
int newpos = 0;
for( const char *p=oldName; *p != 0 && newpos < newNameBufSize-1; p++ )
{
//check for a '#' char at the beginning
/*
if( p == oldName && *p == '#' )
{
newName[newpos] = '*';
newpos++;
}
else */
if( *p == '%' )
{
// remove % chars
newName[newpos] = '*';
newpos++;
}
else if( *p == '&' )
{
//insert another & after this one
if ( newpos+2 < newNameBufSize )
{
newName[newpos] = '&';
newName[newpos+1] = '&';
newpos+=2;
}
}
else
{
newName[newpos] = *p;
newpos++;
}
}
newName[newpos] = 0;
}
//-----------------------------------------------------------------------------
// This version is simply used to make reading convars simpler.
// Writing convars isn't allowed in this mode
//-----------------------------------------------------------------------------
class CEmptyGameUIConVar : public ConVar
{
public:
CEmptyGameUIConVar() : ConVar( "", "0" ) {}
// Used for optimal read access
virtual void SetValue( const char *pValue ) {}
virtual void SetValue( float flValue ) {}
virtual void SetValue( int nValue ) {}
virtual const char *GetName( void ) const { return ""; }
virtual bool IsFlagSet( int nFlags ) const { return false; }
};
static CEmptyGameUIConVar s_EmptyConVar;
// Helper for splitscreen ConVars
CGameUIConVarRef::CGameUIConVarRef( const char *pName )
{
Init( pName, false );
}
CGameUIConVarRef::CGameUIConVarRef( const char *pName, bool bIgnoreMissing )
{
Init( pName, bIgnoreMissing );
}
void CGameUIConVarRef::Init( const char *pName, bool bIgnoreMissing )
{
for ( int i = 0; i < MAX_SPLITSCREEN_CLIENTS; ++i )
{
cv_t &info = m_Info[ i ];
char pchName[ 256 ];
if ( i != 0 )
{
Q_snprintf( pchName, sizeof( pchName ), "%s%d", pName, i + 1 );
}
else
{
Q_strncpy( pchName, pName, sizeof( pchName ) );
}
info.m_pConVar = g_pCVar ? g_pCVar->FindVar( pchName ) : &s_EmptyConVar;
if ( !info.m_pConVar )
{
info.m_pConVar = &s_EmptyConVar;
if ( i > 0 )
{
// Point at slot zero instead, in case we got in here with a non FCVAR_SS var...
info.m_pConVar = m_Info[ 0 ].m_pConVar;
}
}
info.m_pConVarState = static_cast< ConVar * >( info.m_pConVar );
}
if ( !IsValid() )
{
static bool bFirst = true;
if ( g_pCVar || bFirst )
{
if ( !bIgnoreMissing )
{
Warning( "CGameUIConVarRef %s doesn't point to an existing ConVar\n", pName );
}
bFirst = false;
}
}
}
CGameUIConVarRef::CGameUIConVarRef( IConVar *pConVar )
{
cv_t &info = m_Info[ 0 ];
info.m_pConVar = pConVar ? pConVar : &s_EmptyConVar;
info.m_pConVarState = static_cast< ConVar * >( info.m_pConVar );
for ( int i = 1; i < MAX_SPLITSCREEN_CLIENTS; ++i )
{
info = m_Info[ i ];
char pchName[ 256 ];
Q_snprintf( pchName, sizeof( pchName ), "%s%d", pConVar->GetName(), i + 1 );
info.m_pConVar = g_pCVar ? g_pCVar->FindVar( pchName ) : &s_EmptyConVar;
if ( !info.m_pConVar )
{
info.m_pConVar = &s_EmptyConVar;
if ( i > 0 )
{
// Point at slot zero instead, in case we got in here with a non FCVAR_SS var...
info.m_pConVar = m_Info[ 0 ].m_pConVar;
}
}
info.m_pConVarState = static_cast< ConVar * >( info.m_pConVar );
}
}
bool CGameUIConVarRef::IsValid() const
{
return m_Info[ 0 ].m_pConVar != &s_EmptyConVar;
}
//-----------------------------------------------------------------------------
CGameUiSetActiveSplitScreenPlayerGuard::CGameUiSetActiveSplitScreenPlayerGuard( int slot )
{
m_nSaveSlot = engine->GetActiveSplitScreenPlayerSlot();
engine->SetActiveSplitScreenPlayerSlot( slot );
}
CGameUiSetActiveSplitScreenPlayerGuard::~CGameUiSetActiveSplitScreenPlayerGuard()
{
engine->SetActiveSplitScreenPlayerSlot( m_nSaveSlot );
}

View File

@@ -0,0 +1,165 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef GAMEUI_UTIL_H
#define GAMEUI_UTIL_H
#ifdef _WIN32
#pragma once
#endif
char *VarArgs( const char *format, ... );
// Set by the player who "owns" the gameui/settings/etc.
void SetGameUIActiveSplitScreenPlayerSlot( int nSlot );
int GetGameUIActiveSplitScreenPlayerSlot();
#include "tier1/convar.h"
void GameUI_MakeSafeName( const char *oldName, char *newName, int newNameBufSize );
//-----------------------------------------------------------------------------
// Useful for game ui since game ui has a single active "splitscreen" owner and since
// it can gracefully handle non-FCVAR_SS vars without code changes required.
//-----------------------------------------------------------------------------
class CGameUIConVarRef
{
public:
CGameUIConVarRef( const char *pName );
CGameUIConVarRef( const char *pName, bool bIgnoreMissing );
CGameUIConVarRef( IConVar *pConVar );
void Init( const char *pName, bool bIgnoreMissing );
bool IsValid() const;
bool IsFlagSet( int nFlags ) const;
// Get/Set value
float GetFloat() const;
int GetInt() const;
bool GetBool() const { return !!GetInt(); }
const char *GetString() const;
void SetValue( const char *pValue );
void SetValue( float flValue );
void SetValue( int nValue );
void SetValue( bool bValue );
const char *GetName() const;
const char *GetDefault() const;
const char *GetBaseName() const;
protected:
int GetActiveSplitScreenPlayerSlot() const;
private:
struct cv_t
{
IConVar *m_pConVar;
ConVar *m_pConVarState;
};
cv_t m_Info[ MAX_SPLITSCREEN_CLIENTS ];
};
// In GAMUI we should never use the regular ConVarRef
#define ConVarRef CGameUIConVarRef
FORCEINLINE int CGameUIConVarRef::GetActiveSplitScreenPlayerSlot() const
{
return GetGameUIActiveSplitScreenPlayerSlot();
}
//-----------------------------------------------------------------------------
// Did we find an existing convar of that name?
//-----------------------------------------------------------------------------
FORCEINLINE bool CGameUIConVarRef::IsFlagSet( int nFlags ) const
{
return ( m_Info[ 0 ].m_pConVar->IsFlagSet( nFlags ) != 0 );
}
FORCEINLINE const char *CGameUIConVarRef::GetName() const
{
int nSlot = GetActiveSplitScreenPlayerSlot();
return m_Info[ nSlot ].m_pConVar->GetName();
}
FORCEINLINE const char *CGameUIConVarRef::GetBaseName() const
{
return m_Info[ 0 ].m_pConVar->GetBaseName();
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
//-----------------------------------------------------------------------------
FORCEINLINE float CGameUIConVarRef::GetFloat() const
{
int nSlot = GetActiveSplitScreenPlayerSlot();
return m_Info[ nSlot ].m_pConVarState->GetRawValue().m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
//-----------------------------------------------------------------------------
FORCEINLINE int CGameUIConVarRef::GetInt() const
{
int nSlot = GetActiveSplitScreenPlayerSlot();
return m_Info[ nSlot ].m_pConVarState->GetRawValue().m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
//-----------------------------------------------------------------------------
FORCEINLINE const char *CGameUIConVarRef::GetString() const
{
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
int nSlot = GetActiveSplitScreenPlayerSlot();
return m_Info[ nSlot ].m_pConVarState->GetRawValue().m_pszString;
}
FORCEINLINE void CGameUIConVarRef::SetValue( const char *pValue )
{
int nSlot = GetActiveSplitScreenPlayerSlot();
m_Info[ nSlot ].m_pConVar->SetValue( pValue );
}
FORCEINLINE void CGameUIConVarRef::SetValue( float flValue )
{
int nSlot = GetActiveSplitScreenPlayerSlot();
m_Info[ nSlot ].m_pConVar->SetValue( flValue );
}
FORCEINLINE void CGameUIConVarRef::SetValue( int nValue )
{
int nSlot = GetActiveSplitScreenPlayerSlot();
m_Info[ nSlot ].m_pConVar->SetValue( nValue );
}
FORCEINLINE void CGameUIConVarRef::SetValue( bool bValue )
{
int nSlot = GetActiveSplitScreenPlayerSlot();
m_Info[ nSlot ].m_pConVar->SetValue( bValue ? 1 : 0 );
}
FORCEINLINE const char *CGameUIConVarRef::GetDefault() const
{
return m_Info[ 0 ].m_pConVarState->GetDefault();
}
//-----------------------------------------------------------------------------
class CGameUiSetActiveSplitScreenPlayerGuard
{
public:
explicit CGameUiSetActiveSplitScreenPlayerGuard( int slot );
~CGameUiSetActiveSplitScreenPlayerGuard();
private:
int m_nSaveSlot;
};
#define GAMEUI_ACTIVE_SPLITSCREEN_PLAYER_GUARD( slot ) CGameUiSetActiveSplitScreenPlayerGuard g_SSGuard( slot );
#endif // GAMEUI_UTIL_H

View File

@@ -0,0 +1,118 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "KeyToggleCheckButton.h"
#include "EngineInterface.h"
#include <vgui/IVGui.h>
#include "IGameUIFuncs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
CKeyToggleCheckButton::CKeyToggleCheckButton( Panel *parent, const char *panelName, const char *text,
char const *key, char const *cmdname )
: CheckButton( parent, panelName, text )
{
m_pszKeyName = key ? strdup( key ) : NULL;
m_pszCmdName = cmdname ? strdup( cmdname ) : NULL;
if (m_pszKeyName)
{
Reset();
}
//m_bNoCommand = false;
}
CKeyToggleCheckButton::~CKeyToggleCheckButton()
{
free( m_pszKeyName );
free( m_pszCmdName );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CKeyToggleCheckButton::Paint()
{
BaseClass::Paint();
if ( !m_pszKeyName )
return;
// Fixme, look up key state
bool isdown;
if ( gameuifuncs->IsKeyDown( m_pszKeyName, isdown ) )
{
// if someone changed the value using the consoel
if ( m_bStartValue != isdown )
{
SetSelected( isdown );
m_bStartValue = isdown;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *panel -
//-----------------------------------------------------------------------------
/*
void CKeyToggleCheckButton::SetSelected( bool state )
{
BaseClass::SetSelected( state );
if ( !m_pszCmdName || !m_pszCmdName[ 0 ] )
return;
if ( m_bNoCommand )
return;
char szCommand[ 256 ];
Q_snprintf( szCommand, sizeof( szCommand ), "%c%s\n", IsSelected() ? '+' : '-',
m_pszCmdName );
engine->pfnClientCmd( szCommand );
}*/
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CKeyToggleCheckButton::Reset()
{
gameuifuncs->IsKeyDown( m_pszKeyName, m_bStartValue );
if ( IsSelected() != m_bStartValue)
{
SetSelected( m_bStartValue );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CKeyToggleCheckButton::ApplyChanges()
{
if ( !m_pszCmdName || !m_pszCmdName[ 0 ] )
return;
char szCommand[ 256 ];
Q_snprintf( szCommand, sizeof( szCommand ), "%c%s\n", IsSelected() ? '+' : '-',
m_pszCmdName );
engine->ClientCmd_Unrestricted( szCommand );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CKeyToggleCheckButton::HasBeenModified()
{
return IsSelected() != m_bStartValue;
}

View File

@@ -0,0 +1,38 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef KEYTOGGLECHECKBUTTON_H
#define KEYTOGGLECHECKBUTTON_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/CheckButton.h>
class CKeyToggleCheckButton : public vgui::CheckButton
{
public:
CKeyToggleCheckButton( vgui::Panel *parent, const char *panelName, const char *text,
char const *keyname, char const *cmdname );
~CKeyToggleCheckButton();
//virtual void SetSelected( bool state );
virtual void Paint();
void Reset();
void ApplyChanges();
bool HasBeenModified();
private:
typedef vgui::CheckButton BaseClass;
char *m_pszKeyName;
char *m_pszCmdName;
bool m_bStartValue;
};
#endif // KEYTOGGLECHECKBUTTON_H

View File

@@ -0,0 +1,131 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "LabeledCommandComboBox.h"
#include "EngineInterface.h"
#include <KeyValues.h>
#include <vgui/ILocalize.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
CLabeledCommandComboBox::CLabeledCommandComboBox( vgui::Panel *parent, const char *panelName ) : vgui::ComboBox( parent, panelName, 6, false )
{
AddActionSignalTarget(this);
m_iCurrentSelection = -1;
m_iStartSelection = -1;
}
CLabeledCommandComboBox::~CLabeledCommandComboBox( void )
{
}
void CLabeledCommandComboBox::DeleteAllItems()
{
BaseClass::DeleteAllItems();
m_Items.RemoveAll();
}
void CLabeledCommandComboBox::AddItem( char const *text, char const *engineCommand )
{
int idx = m_Items.AddToTail();
COMMANDITEM *item = &m_Items[ idx ];
item->comboBoxID = BaseClass::AddItem( text, NULL );
Q_strncpy( item->name, text, sizeof( item->name ) );
if (text[0] == '#')
{
// need to localize the string
wchar_t *localized = g_pVGuiLocalize->Find(text);
if (localized)
{
g_pVGuiLocalize->ConvertUnicodeToANSI(localized, item->name, sizeof(item->name));
}
}
Q_strncpy( item->command, engineCommand, sizeof( item->command ) );
}
void CLabeledCommandComboBox::ActivateItem(int index)
{
if ( index< m_Items.Count() )
{
int comboBoxID = m_Items[index].comboBoxID;
BaseClass::ActivateItem(comboBoxID);
m_iCurrentSelection = index;
}
}
void CLabeledCommandComboBox::SetInitialItem(int index)
{
if ( index< m_Items.Count() )
{
m_iStartSelection = index;
int comboBoxID = m_Items[index].comboBoxID;
ActivateItem(comboBoxID);
}
}
void CLabeledCommandComboBox::OnTextChanged( char const *text )
{
int i;
for ( i = 0; i < m_Items.Count(); i++ )
{
COMMANDITEM *item = &m_Items[ i ];
if ( !stricmp( item->name, text ) )
{
// engine->pfnClientCmd( item->command );
m_iCurrentSelection = i;
break;
}
}
if (HasBeenModified())
{
PostActionSignal(new KeyValues("ControlModified"));
}
// PostMessage( GetParent()->GetVPanel(), new vgui::KeyValues( "TextChanged", "text", text ) );
}
const char *CLabeledCommandComboBox::GetActiveItemCommand()
{
if (m_iCurrentSelection == -1)
return NULL;
COMMANDITEM *item = &m_Items[ m_iCurrentSelection ];
return item->command;
}
void CLabeledCommandComboBox::ApplyChanges()
{
if (m_iCurrentSelection == -1)
return;
if (m_Items.Count() < 1)
return;
Assert( m_iCurrentSelection < m_Items.Count() );
COMMANDITEM *item = &m_Items[ m_iCurrentSelection ];
engine->ClientCmd_Unrestricted( item->command );
m_iStartSelection = m_iCurrentSelection;
}
bool CLabeledCommandComboBox::HasBeenModified()
{
return m_iStartSelection != m_iCurrentSelection;
}
void CLabeledCommandComboBox::Reset()
{
if (m_iStartSelection != -1)
{
ActivateItem(m_iStartSelection);
}
}

View File

@@ -0,0 +1,59 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef LABELEDCOMMANDCOMBOBOX_H
#define LABELEDCOMMANDCOMBOBOX_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/ComboBox.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/Panel.h>
#include "UtlVector.h"
class CLabeledCommandComboBox : public vgui::ComboBox
{
DECLARE_CLASS_SIMPLE( CLabeledCommandComboBox, vgui::ComboBox );
public:
CLabeledCommandComboBox(vgui::Panel *parent, const char *panelName);
~CLabeledCommandComboBox();
virtual void DeleteAllItems();
virtual void AddItem(char const *text, char const *engineCommand);
virtual void ActivateItem(int itemIndex);
const char *GetActiveItemCommand();
void SetInitialItem(int itemIndex);
void ApplyChanges();
void Reset();
bool HasBeenModified();
enum
{
MAX_NAME_LEN = 256,
MAX_COMMAND_LEN = 256
};
private:
MESSAGE_FUNC_CHARPTR( OnTextChanged, "TextChanged", text );
struct COMMANDITEM
{
char name[ MAX_NAME_LEN ];
char command[ MAX_COMMAND_LEN ];
int comboBoxID;
};
CUtlVector< COMMANDITEM > m_Items;
int m_iCurrentSelection;
int m_iStartSelection;
};
#endif // LABELEDCOMMANDCOMBOBOX_H

View File

@@ -0,0 +1,637 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "LoadingDialog.h"
#include "EngineInterface.h"
#include "igameuifuncs.h"
#include <vgui/IInput.h>
#include <vgui/ISurface.h>
#include <vgui/ILocalize.h>
#include <vgui/IScheme.h>
#include <vgui/ISystem.h>
#include <vgui_controls/ProgressBar.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/HTML.h>
#include <vgui_controls/RichText.h>
#include "tier0/icommandline.h"
#include "GameUI_Interface.h"
#include "ModInfo.h"
#include "basepanel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CLoadingDialog::CLoadingDialog( vgui::Panel *parent ) : Frame(parent, "LoadingDialog")
{
SetDeleteSelfOnClose(true);
// Use console style
m_bConsoleStyle = GameUI().IsConsoleUI();
if ( !m_bConsoleStyle )
{
SetSize( 416, 100 );
SetTitle( "#GameUI_Loading", true );
}
// center the loading dialog, unless we have another dialog to show in the background
m_bCenter = !GameUI().HasLoadingBackgroundDialog();
m_bShowingSecondaryProgress = false;
m_flSecondaryProgress = 0.0f;
m_flLastSecondaryProgressUpdateTime = 0.0f;
m_flSecondaryProgressStartTime = 0.0f;
m_pProgress = new ProgressBar( this, "Progress" );
m_pProgress2 = new ProgressBar( this, "Progress2" );
m_pInfoLabel = new Label( this, "InfoLabel", "" );
m_pCancelButton = new Button( this, "CancelButton", "#GameUI_Cancel" );
m_pTimeRemainingLabel = new Label( this, "TimeRemainingLabel", "" );
m_pCancelButton->SetCommand( "Cancel" );
if ( ModInfo().IsSinglePlayerOnly() == false && m_bConsoleStyle == true )
{
m_pLoadingBackground = new Panel( this, "LoadingDialogBG" );
}
else
{
m_pLoadingBackground = NULL;
}
SetMinimizeButtonVisible( false );
SetMaximizeButtonVisible( false );
SetCloseButtonVisible( false );
SetSizeable( false );
SetMoveable( false );
if ( m_bConsoleStyle )
{
m_bCenter = false;
m_pProgress->SetVisible( false );
m_pProgress2->SetVisible( false );
m_pInfoLabel->SetVisible( false );
m_pCancelButton->SetVisible( false );
m_pTimeRemainingLabel->SetVisible( false );
m_pCancelButton->SetVisible( false );
SetMinimumSize( 0, 0 );
SetTitleBarVisible( false );
m_flProgressFraction = 0;
}
else
{
m_pInfoLabel->SetBounds(20, 32, 392, 24);
m_pProgress->SetBounds(20, 64, 300, 24);
m_pCancelButton->SetBounds(330, 64, 72, 24);
m_pInfoLabel->SetTextColorState(Label::CS_DULL);
m_pProgress2->SetVisible(false);
}
SetupControlSettings( false );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CLoadingDialog::~CLoadingDialog()
{
}
void CLoadingDialog::PaintBackground()
{
if ( !m_bConsoleStyle )
{
BaseClass::PaintBackground();
return;
}
// draw solid progress bar with curved endcaps
int panelWide, panelTall;
GetSize( panelWide, panelTall );
int barWide, barTall;
m_pProgress->GetSize( barWide, barTall );
int x = ( panelWide - barWide )/2;
int y = panelTall - barTall;
if ( m_pLoadingBackground )
{
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
Color color = GetSchemeColor( "TanDarker", Color(255, 255, 255, 255), vgui::scheme()->GetIScheme(scheme) );
m_pLoadingBackground->SetFgColor( color );
m_pLoadingBackground->SetBgColor( color );
m_pLoadingBackground->SetPaintBackgroundEnabled( true );
}
if ( ModInfo().IsSinglePlayerOnly() )
{
DrawBox( x, y, barWide, barTall, Color( 0, 0, 0, 255 ), 1.0f );
}
DrawBox( x+2, y+2, barWide-4, barTall-4, Color( 100, 100, 100, 255 ), 1.0f );
barWide = m_flProgressFraction * ( barWide - 4 );
if ( barWide >= 12 )
{
// cannot draw a curved box smaller than 12 without artifacts
DrawBox( x+2, y+2, barWide, barTall-4, Color( 200, 100, 0, 255 ), 1.0f );
}
}
//-----------------------------------------------------------------------------
// Purpose: sets up dialog layout
//-----------------------------------------------------------------------------
void CLoadingDialog::SetupControlSettings( bool bForceShowProgressText )
{
m_bShowingVACInfo = false;
#if defined( BASEPANEL_LEGACY_SOURCE1 )
if ( GameUI().IsConsoleUI() )
{
KeyValues *pControlSettings = BasePanel()->GetConsoleControlSettings()->FindKey( "LoadingDialogNoBanner.res" );
LoadControlSettings( "null", NULL, pControlSettings );
return;
}
#endif
if ( ModInfo().IsSinglePlayerOnly() && !bForceShowProgressText )
{
LoadControlSettings("Resource/LoadingDialogNoBannerSingle.res");
}
else if ( gameuifuncs->IsConnectedToVACSecureServer() )
{
LoadControlSettings("Resource/LoadingDialogVAC.res");
m_bShowingVACInfo = true;
}
else
{
LoadControlSettings("Resource/LoadingDialogNoBanner.res");
}
}
//-----------------------------------------------------------------------------
// Purpose: Activates the loading screen, initializing and making it visible
//-----------------------------------------------------------------------------
void CLoadingDialog::Open()
{
if ( !m_bConsoleStyle )
{
SetTitle( "#GameUI_Loading", true );
}
HideOtherDialogs( true );
BaseClass::Activate();
if ( !m_bConsoleStyle )
{
m_pProgress->SetVisible( true );
if ( !ModInfo().IsSinglePlayerOnly() )
{
m_pInfoLabel->SetVisible( true );
}
m_pInfoLabel->SetText("");
m_pCancelButton->SetText("#GameUI_Cancel");
m_pCancelButton->SetCommand("Cancel");
}
}
//-----------------------------------------------------------------------------
// Purpose: error display file
//-----------------------------------------------------------------------------
void CLoadingDialog::SetupControlSettingsForErrorDisplay( const char *settingsFile )
{
if ( m_bConsoleStyle )
{
return;
}
m_bCenter = true;
SetTitle("#GameUI_Disconnected", true);
m_pInfoLabel->SetText("");
LoadControlSettings( settingsFile );
HideOtherDialogs( true );
BaseClass::Activate();
m_pProgress->SetVisible(false);
m_pInfoLabel->SetVisible(true);
m_pCancelButton->SetText("#GameUI_Close");
m_pCancelButton->SetCommand("Close");
m_pInfoLabel->InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: shows or hides other top-level dialogs
//-----------------------------------------------------------------------------
void CLoadingDialog::HideOtherDialogs( bool bHide )
{
if ( bHide )
{
if ( GameUI().HasLoadingBackgroundDialog() )
{
// if we have a loading background dialog, hide any other dialogs by moving the full-screen background dialog to the
// front, then moving ourselves in front of it
GameUI().ShowLoadingBackgroundDialog();
vgui::ipanel()->MoveToFront( GetVPanel() );
vgui::input()->SetAppModalSurface( GetVPanel() );
}
else
{
// if there is no loading background dialog, use VGUI paint restrictions to hide other dialogs
vgui::surface()->RestrictPaintToSinglePanel(GetVPanel());
}
}
else
{
if ( GameUI().HasLoadingBackgroundDialog() )
{
GameUI().HideLoadingBackgroundDialog();
vgui::input()->SetAppModalSurface( NULL );
}
else
{
// remove any rendering restrictions
vgui::surface()->RestrictPaintToSinglePanel(NULL);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Turns dialog into error display
//-----------------------------------------------------------------------------
void CLoadingDialog::DisplayGenericError(const char *failureReason, const char *extendedReason)
{
if ( m_bConsoleStyle )
{
return;
}
// In certain race conditions, DisplayGenericError can get called AFTER OnClose() has been called.
// If that happens and we don't call Activate(), then it'll continue closing when we don't want it to.
Activate();
SetupControlSettingsForErrorDisplay("Resource/LoadingDialogError.res");
if ( extendedReason && strlen( extendedReason ) > 0 )
{
wchar_t compositeReason[256], finalMsg[512], formatStr[256];
if ( extendedReason[0] == '#' )
{
wcsncpy(compositeReason, g_pVGuiLocalize->Find(extendedReason), sizeof( compositeReason ) / sizeof( wchar_t ) );
}
else
{
g_pVGuiLocalize->ConvertANSIToUnicode(extendedReason, compositeReason, sizeof( compositeReason ));
}
if ( failureReason[0] == '#' )
{
wcsncpy(formatStr, g_pVGuiLocalize->Find(failureReason), sizeof( formatStr ) / sizeof( wchar_t ) );
}
else
{
g_pVGuiLocalize->ConvertANSIToUnicode(failureReason, formatStr, sizeof( formatStr ));
}
g_pVGuiLocalize->ConstructString(finalMsg, sizeof( finalMsg ), formatStr, 1, compositeReason);
m_pInfoLabel->SetText(finalMsg);
}
else
{
m_pInfoLabel->SetText(failureReason);
}
}
//-----------------------------------------------------------------------------
// Purpose: explain to the user they can't join secure servers due to a VAC ban
//-----------------------------------------------------------------------------
void CLoadingDialog::DisplayVACBannedError()
{
if ( m_bConsoleStyle )
{
return;
}
SetupControlSettingsForErrorDisplay("Resource/LoadingDialogErrorVACBanned.res");
SetTitle("#VAC_ConnectionRefusedTitle", true);
}
//-----------------------------------------------------------------------------
// Purpose: explain to the user they can't connect to public servers due to
// not having a valid connection to Steam
// this should only happen if they are a pirate
//-----------------------------------------------------------------------------
void CLoadingDialog::DisplayNoSteamConnectionError()
{
if ( m_bConsoleStyle )
{
return;
}
SetupControlSettingsForErrorDisplay("Resource/LoadingDialogErrorNoSteamConnection.res");
}
//-----------------------------------------------------------------------------
// Purpose: explain to the user they got kicked from a server due to that same account
// logging in from another location. This also triggers the refresh login dialog on OK
// being pressed.
//-----------------------------------------------------------------------------
void CLoadingDialog::DisplayLoggedInElsewhereError()
{
if ( m_bConsoleStyle )
{
return;
}
SetupControlSettingsForErrorDisplay("Resource/LoadingDialogErrorLoggedInElsewhere.res");
m_pCancelButton->SetText("#GameUI_RefreshLogin_Login");
m_pCancelButton->SetCommand("Login");
}
//-----------------------------------------------------------------------------
// Purpose: sets status info text
//-----------------------------------------------------------------------------
void CLoadingDialog::SetStatusText(const char *statusText)
{
if ( m_bConsoleStyle )
{
return;
}
m_pInfoLabel->SetText(statusText);
}
//-----------------------------------------------------------------------------
// Purpose: returns the previous state
//-----------------------------------------------------------------------------
bool CLoadingDialog::SetShowProgressText( bool show )
{
if ( m_bConsoleStyle )
{
return false;
}
bool bret = m_pInfoLabel->IsVisible();
if ( bret != show )
{
SetupControlSettings( show );
m_pInfoLabel->SetVisible( show );
}
return bret;
}
//-----------------------------------------------------------------------------
// Purpose: updates time remaining
//-----------------------------------------------------------------------------
void CLoadingDialog::OnThink()
{
BaseClass::OnThink();
if ( !m_bConsoleStyle && m_bShowingSecondaryProgress )
{
// calculate the time remaining string
wchar_t unicode[512];
if (m_flSecondaryProgress >= 1.0f)
{
m_pTimeRemainingLabel->SetText("complete");
}
else if (ProgressBar::ConstructTimeRemainingString(unicode, sizeof(unicode), m_flSecondaryProgressStartTime, (float)system()->GetFrameTime(), m_flSecondaryProgress, m_flLastSecondaryProgressUpdateTime, true))
{
m_pTimeRemainingLabel->SetText(unicode);
}
else
{
m_pTimeRemainingLabel->SetText("");
}
}
SetAlpha( 255 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadingDialog::PerformLayout()
{
if ( m_bConsoleStyle )
{
// place in lower center
int screenWide, screenTall;
surface()->GetScreenSize( screenWide, screenTall );
int wide,tall;
GetSize( wide, tall );
int x = 0;
int y = 0;
if ( ModInfo().IsSinglePlayerOnly() )
{
x = ( screenWide - wide ) * 0.50f;
y = ( screenTall - tall ) * 0.86f;
}
else
{
x = ( screenWide - ( wide * 1.30f ) );
y = ( ( screenTall * 0.875f ) );
}
SetPos( x, y );
}
else if ( m_bCenter )
{
MoveToCenterOfScreen();
}
else
{
// if we're not supposed to be centered, move ourselves to the lower right hand corner of the screen
int x, y, screenWide, screenTall;
surface()->GetWorkspaceBounds( x, y, screenWide, screenTall );
int wide,tall;
GetSize( wide, tall );
if ( IsPC() )
{
x = screenWide - ( wide + 10 );
y = screenTall - ( tall + 10 );
}
else
{
// Move farther in so we're title safe
x = screenWide - wide - (screenWide * 0.05);
y = screenTall - tall - (screenTall * 0.05);
}
x -= m_iAdditionalIndentX;
y -= m_iAdditionalIndentY;
SetPos( x, y );
}
BaseClass::PerformLayout();
vgui::ipanel()->MoveToFront( GetVPanel() );
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the number of ticks has changed
//-----------------------------------------------------------------------------
bool CLoadingDialog::SetProgressPoint( float fraction )
{
if ( m_bConsoleStyle )
{
if ( fraction >= 0.99f )
{
// show the progress artifically completed to fill in 100%
fraction = 1.0f;
}
fraction = clamp( fraction, 0.0f, 1.0f );
if ( (int)(fraction * 25) != (int)(m_flProgressFraction * 25) )
{
m_flProgressFraction = fraction;
return true;
}
return IsGameConsole();
}
if ( !m_bShowingVACInfo && gameuifuncs->IsConnectedToVACSecureServer() )
{
SetupControlSettings( false );
}
int nOldDrawnSegments = m_pProgress->GetDrawnSegmentCount();
m_pProgress->SetProgress( fraction );
int nNewDrawSegments = m_pProgress->GetDrawnSegmentCount();
return (nOldDrawnSegments != nNewDrawSegments) || IsGameConsole();
}
//-----------------------------------------------------------------------------
// Purpose: sets and shows the secondary progress bar
//-----------------------------------------------------------------------------
void CLoadingDialog::SetSecondaryProgress( float progress )
{
if ( m_bConsoleStyle )
return;
// don't show the progress if we've jumped right to completion
if (!m_bShowingSecondaryProgress && progress > 0.99f)
return;
// if we haven't yet shown secondary progress then reconfigure the dialog
if (!m_bShowingSecondaryProgress)
{
LoadControlSettings("Resource/LoadingDialogDualProgress.res");
m_bShowingSecondaryProgress = true;
m_pProgress2->SetVisible(true);
m_flSecondaryProgressStartTime = (float)system()->GetFrameTime();
}
// if progress has increased then update the progress counters
if (progress > m_flSecondaryProgress)
{
m_pProgress2->SetProgress(progress);
m_flSecondaryProgress = progress;
m_flLastSecondaryProgressUpdateTime = (float)system()->GetFrameTime();
}
// if progress has decreased then reset progress counters
if (progress < m_flSecondaryProgress)
{
m_pProgress2->SetProgress(progress);
m_flSecondaryProgress = progress;
m_flLastSecondaryProgressUpdateTime = (float)system()->GetFrameTime();
m_flSecondaryProgressStartTime = (float)system()->GetFrameTime();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadingDialog::SetSecondaryProgressText(const char *statusText)
{
if ( m_bConsoleStyle )
{
return;
}
SetControlString( "SecondaryProgressLabel", statusText );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLoadingDialog::OnClose()
{
// remove any rendering restrictions
HideOtherDialogs( false );
BaseClass::OnClose();
}
//-----------------------------------------------------------------------------
// Purpose: command handler
//-----------------------------------------------------------------------------
void CLoadingDialog::OnCommand(const char *command)
{
if ( !stricmp(command, "Cancel") )
{
// disconnect from the server
engine->ClientCmd_Unrestricted("disconnect\n");
// close
Close();
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: Maps ESC to quiting loading
//-----------------------------------------------------------------------------
void CLoadingDialog::OnKeyCodePressed(KeyCode code)
{
if ( m_bConsoleStyle )
{
return;
}
if ( code == KEY_ESCAPE )
{
OnCommand("Cancel");
}
else
{
BaseClass::OnKeyCodePressed(code);
}
}
//-----------------------------------------------------------------------------
// Purpose: Singleton accessor
//-----------------------------------------------------------------------------
extern vgui::DHANDLE<CLoadingDialog> g_hLoadingDialog;
CLoadingDialog *LoadingDialog()
{
return g_hLoadingDialog.Get();
}

View File

@@ -0,0 +1,76 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef LOADINGDIALOG_H
#define LOADINGDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Frame.h>
#include <vgui_controls/HTML.h>
//-----------------------------------------------------------------------------
// Purpose: Dialog for displaying level loading status
//-----------------------------------------------------------------------------
class CLoadingDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CLoadingDialog, vgui::Frame );
public:
CLoadingDialog( vgui::Panel *parent );
~CLoadingDialog();
void Open();
bool SetProgressPoint(float fraction);
void SetStatusText(const char *statusText);
void SetSecondaryProgress(float progress);
void SetSecondaryProgressText(const char *statusText);
bool SetShowProgressText( bool show );
void DisplayGenericError(const char *failureReason, const char *extendedReason = NULL);
void DisplayVACBannedError();
void DisplayNoSteamConnectionError();
void DisplayLoggedInElsewhereError();
protected:
virtual void OnCommand(const char *command);
virtual void PerformLayout();
virtual void OnThink();
virtual void OnClose();
virtual void OnKeyCodePressed(vgui::KeyCode code);
virtual void PaintBackground( void );
private:
void SetupControlSettings( bool bForceShowProgressText );
void SetupControlSettingsForErrorDisplay( const char *settingsFile );
void HideOtherDialogs( bool bHide );
vgui::ProgressBar *m_pProgress;
vgui::ProgressBar *m_pProgress2;
vgui::Label *m_pInfoLabel;
vgui::Label *m_pTimeRemainingLabel;
vgui::Button *m_pCancelButton;
vgui::Panel *m_pLoadingBackground;
bool m_bShowingSecondaryProgress;
float m_flSecondaryProgress;
float m_flLastSecondaryProgressUpdateTime;
float m_flSecondaryProgressStartTime;
bool m_bShowingVACInfo;
bool m_bCenter;
bool m_bConsoleStyle;
float m_flProgressFraction;
CPanelAnimationVar( int, m_iAdditionalIndentX, "AdditionalIndentX", "0" );
CPanelAnimationVar( int, m_iAdditionalIndentY, "AdditionalIndentY", "0" );
};
// singleton accessor
CLoadingDialog *LoadingDialog();
#endif // LOADINGDIALOG_H

View File

@@ -0,0 +1,197 @@
//===== Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose: Tip display during level loads.
//
//===========================================================================//
#include "loadingtippanel.h"
#include "filesystem.h"
#include "keyvalues.h"
#include "vgui/isurface.h"
#include "EngineInterface.h"
#include "vstdlib/random.h"
#include "fmtstr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
ConVar ui_loading_tip_refresh( "ui_loading_tip_refresh", "5", FCVAR_DEVELOPMENTONLY );
ConVar ui_loading_tip_f1( "ui_loading_tip_f1", "0.05", FCVAR_DEVELOPMENTONLY );
ConVar ui_loading_tip_f2( "ui_loading_tip_f2", "0.40", FCVAR_DEVELOPMENTONLY );
//--------------------------------------------------------------------------------------------------------
CLoadingTipPanel::CLoadingTipPanel( Panel *pParent ) : EditablePanel( pParent, "loadingtippanel" )
{
m_flLastTipTime = 0.f;
m_iCurrentTip = 0;
m_pTipIcon = NULL;
m_smearColor = Color( 0, 0, 0, 255 );
SetupTips();
}
//--------------------------------------------------------------------------------------------------------
CLoadingTipPanel::~CLoadingTipPanel()
{
}
//--------------------------------------------------------------------------------------------------------
void CLoadingTipPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_smearColor = pScheme->GetColor( "Frame.SmearColor", Color( 0, 0, 0, 225 ) );
ReloadScheme();
}
//--------------------------------------------------------------------------------------------------------
void CLoadingTipPanel::ReloadScheme( void )
{
LoadControlSettings( "Resource/UI/loadingtippanel.res" );
m_pTipIcon = dynamic_cast< vgui::ImagePanel* >( FindChildByName( "TipIcon" ) );
NextTip();
}
//--------------------------------------------------------------------------------------------------------
void CLoadingTipPanel::SetupTips( void )
{
#ifdef _DEMO
KeyValues *pKV = new KeyValues( "Tips" );
KeyValues::AutoDelete autodelete( pKV );
if ( !pKV->LoadFromFile( g_pFullFileSystem, "scripts/tips.txt", "GAME" ) )
{
AssertMsg( false, "failed to load tips!" );
return;
}
for ( KeyValues *pKey = pKV->FindKey( "SurvivorTips" )->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
{
sTipInfo info;
V_strncpy( info.szTipTitle, "", MAX_TIP_LENGTH );
V_strncpy( info.szTipString, pKey->GetName(), MAX_TIP_LENGTH );
V_strncpy( info.szTipImage, "achievements/ACH_SURVIVE_BRIDGE", MAX_TIP_LENGTH );
m_Tips.AddToTail( info );
}
#else
TitleAchievementsDescription_t const *desc = g_pMatchFramework->GetMatchTitle()->DescribeTitleAchievements();
for ( ; desc->m_szAchievementName; ++desc )
{
sTipInfo info;
V_snprintf( info.szTipTitle, MAX_TIP_LENGTH, "#%s_NAME", desc->m_szAchievementName );
V_snprintf( info.szTipString, MAX_TIP_LENGTH, "#%s_DESC", desc->m_szAchievementName );
V_snprintf( info.szTipImage, MAX_TIP_LENGTH, "achievements/%s", desc->m_szAchievementName );
m_Tips.AddToTail( info );
}
#endif
}
//--------------------------------------------------------------------------------------------------------
void CLoadingTipPanel::NextTip( void )
{
if ( !IsEnabled() )
return;
if ( !m_Tips.Count() )
return;
if ( !m_flLastTipTime )
{
// Initialize timer on first render
m_flLastTipTime = Plat_FloatTime();
return;
}
if ( Plat_FloatTime() - m_flLastTipTime < ui_loading_tip_refresh.GetFloat() )
return;
m_flLastTipTime = Plat_FloatTime();
m_iCurrentTip = RandomInt( 0, m_Tips.Count() - 1 );
if ( !m_Tips.IsValidIndex( m_iCurrentTip ) )
return;
sTipInfo info = m_Tips[m_iCurrentTip];
if ( m_pTipIcon )
{
m_pTipIcon->SetImage( info.szTipImage );
}
SetControlString( "TipTitle", info.szTipTitle );
SetControlString( "TipText", info.szTipString );
// Set our control visible
SetVisible( true );
}
#define TOP_BORDER_HEIGHT 21
#define BOTTOM_BORDER_HEIGHT 21
int CLoadingTipPanel::DrawSmearBackgroundFade( int x0, int y0, int x1, int y1 )
{
int wide = x1 - x0;
int tall = y1 - y0;
int topTall = scheme()->GetProportionalScaledValue( TOP_BORDER_HEIGHT );
int bottomTall = scheme()->GetProportionalScaledValue( BOTTOM_BORDER_HEIGHT );
float f1 = ui_loading_tip_f1.GetFloat();
float f2 = ui_loading_tip_f2.GetFloat();
topTall = 1.00f * topTall;
bottomTall = 1.00f * bottomTall;
int middleTall = tall - ( topTall + bottomTall );
if ( middleTall < 0 )
{
middleTall = 0;
}
surface()->DrawSetColor( m_smearColor );
y0 += topTall;
if ( middleTall )
{
// middle
surface()->DrawFilledRectFade( x0, y0, x0 + f1*wide, y0 + middleTall, 0, 255, true );
surface()->DrawFilledRectFade( x0 + f1*wide, y0, x0 + f2*wide, y0 + middleTall, 255, 255, true );
surface()->DrawFilledRectFade( x0 + f2*wide, y0, x0 + wide, y0 + middleTall, 255, 0, true );
y0 += middleTall;
}
return topTall + middleTall + bottomTall;
}
//--------------------------------------------------------------------------------------------------------
void CLoadingTipPanel::PaintBackground( void )
{
BaseClass::PaintBackground();
DrawSmearBackgroundFade(
0,
-scheme()->GetProportionalScaledValue( 20 ),
GetWide(),
GetTall() );
}
void PrecacheLoadingTipIcons()
{
TitleAchievementsDescription_t const *desc = g_pMatchFramework->GetMatchTitle()->DescribeTitleAchievements();
for ( ; desc->m_szAchievementName; ++desc )
{
CFmtStr imageString( "vgui/achievements/%s", desc->m_szAchievementName );
int nImageId = vgui::surface()->DrawGetTextureId( imageString );
if ( nImageId == -1 )
{
nImageId = vgui::surface()->CreateNewTextureID();
vgui::surface()->DrawSetTextureFile( nImageId, imageString, true, false );
}
}
}

View File

@@ -0,0 +1,66 @@
//===== Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose: Tip display during level loads.
//
//===========================================================================//
#ifndef LOADING_TIP_PANEL_H
#define LOADING_TIP_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/imagepanel.h"
#include "vgui_controls/editablepanel.h"
#include "vgui_controls/label.h"
#define MAX_TIP_LENGTH 64
struct sTipInfo
{
char szTipTitle[MAX_TIP_LENGTH];
char szTipString[MAX_TIP_LENGTH];
char szTipImage[MAX_TIP_LENGTH];
};
enum eTipMode
{
TIP_MODE_SURVIVOR,
TIP_MODE_INFECTED,
TIP_MODE_ACHIEVEMENTS,
TIP_MODE_COUNT,
};
class CLoadingTipPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CLoadingTipPanel, vgui::EditablePanel )
public:
CLoadingTipPanel( Panel *pParent );
~CLoadingTipPanel();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PaintBackground( void );
void ReloadScheme( void );
void NextTip( void );
private:
void SetupTips( void );
int DrawSmearBackgroundFade( int x, int y, int wide, int tall );
Color m_smearColor;
vgui::ImagePanel *m_pTipIcon;
CUtlVector< sTipInfo > m_Tips;
float m_flLastTipTime;
int m_iCurrentTip;
};
void PrecacheLoadingTipIcons();
#endif // LOADING_TIP_PANEL_H

View File

@@ -0,0 +1,296 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifdef IS_WINDOWS_PC
#include <windows.h>
#endif
#include <stdio.h>
#include "UtlBuffer.h"
#include <vgui/VGUI.h>
#include <vgui_controls/Controls.h>
#include "FileSystem.h"
#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif
#ifdef _PS3
#include "ps3/ps3_core.h"
#include "ps3/ps3_win32stubs.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
#define TYP_LUMPY 64 // 64 + grab command number
typedef struct
{
char identification[4]; // should be WAD2 or 2DAW
int numlumps;
int infotableofs;
} wadinfo_t;
typedef struct
{
int filepos;
int disksize;
int size; // uncompressed
char type;
char compression;
char pad1, pad2;
char name[16]; // must be null terminated
} lumpinfo_t;
typedef struct
{
char name[16];
unsigned width, height;
unsigned offsets[4]; // four mip maps stored
} miptex_t;
unsigned char pixdata[256];
float linearpalette[256][3];
float d_red, d_green, d_blue;
int colors_used;
int color_used[256];
float maxdistortion;
unsigned char palLogo[768];
/*
=============
AveragePixels
=============
*/
unsigned char AveragePixels (int count)
{
return pixdata[0];
}
/*
==============
GrabMip
filename MIP x y width height
must be multiples of sixteen
==============
*/
int GrabMip ( HANDLE hdib, unsigned char *lump_p, char *lumpname, COLORREF crf, int *width, int *height)
{
#ifndef _WIN32
return 0;
#else
int i,x,y,xl,yl,xh,yh,w,h;
unsigned char *screen_p, *source;
miptex_t *qtex;
int miplevel, mipstep;
int xx, yy;
int count;
int byteimagewidth, byteimageheight;
unsigned char *byteimage;
LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0)
/* get pointer to BITMAPINFO (Win 3.0) */
lpbmi = (LPBITMAPINFO)::GlobalLock((HGLOBAL)hdib);
unsigned char *lump_start = lump_p;
xl = yl = 0;
w = lpbmi->bmiHeader.biWidth;
h = lpbmi->bmiHeader.biHeight;
*width = w;
*height = h;
byteimage = (unsigned char *)((LPSTR)lpbmi + sizeof( BITMAPINFOHEADER ) + 256 * sizeof( RGBQUAD ) );
if ( (w & 15) || (h & 15) )
return 0; //Error ("line %i: miptex sizes must be multiples of 16", scriptline);
xh = xl+w;
yh = yl+h;
qtex = (miptex_t *)lump_p;
qtex->width = (unsigned)(w);
qtex->height = (unsigned)(h);
Q_strncpy (qtex->name, lumpname, sizeof( qtex->name) );
lump_p = (unsigned char *)&qtex->offsets[4];
byteimagewidth = w;
byteimageheight = h;
source = (unsigned char *)lump_p;
qtex->offsets[0] = (unsigned)((unsigned char *)lump_p - (unsigned char *)qtex);
// We're reading from a dib, so go bottom up
screen_p = byteimage + (h - 1) * w;
for (y=yl ; y<yh ; y++)
{
for (x=xl ; x<xh ; x++)
*lump_p++ = *screen_p++;
screen_p -= 2 * w;
}
// calculate gamma corrected linear palette
for (i = 0; i < 256; i++)
{
for (int j = 0; j < 3; j++)
{
float f = (float)(palLogo[i*3+j] / 255.0);
linearpalette[i][j] = f; //pow((double)f, 2); // assume textures are done at 2.2, we want to remap them at 1.0
}
}
maxdistortion = 0;
// assume palette full if it's a transparent texture
colors_used = 256;
for (i = 0; i < 256; i++)
color_used[i] = 1;
//
// subsample for greater mip levels
//
for (miplevel = 1 ; miplevel<4 ; miplevel++)
{
d_red = d_green = d_blue = 0; // no distortion yet
qtex->offsets[miplevel] = (unsigned)(lump_p - (unsigned char *)qtex);
mipstep = 1<<miplevel;
for (y=0 ; y<h ; y+=mipstep)
{
for (x = 0 ; x<w ; x+= mipstep)
{
count = 0;
for (yy=0 ; yy<mipstep ; yy++)
{
for (xx=0 ; xx<mipstep ; xx++)
pixdata[count++] = source[(y+yy)*w + x + xx ];
}
*lump_p++ = AveragePixels (count);
}
}
}
::GlobalUnlock(lpbmi);
// Write out palette in 16bit mode
*(unsigned short *) lump_p = 256; // palette size
lump_p += sizeof(short);
memcpy(lump_p, &palLogo[0], 765);
lump_p += 765;
*lump_p++ = (unsigned char)(crf & 0xFF);
*lump_p++ = (unsigned char)((crf >> 8) & 0xFF);
*lump_p++ = (unsigned char)((crf >> 16) & 0xFF);
return lump_p - lump_start;
#endif
}
void UpdateLogoWAD( void *phdib, int r, int g, int b )
{
char logoname[ 32 ];
char *pszName;
Q_strncpy( logoname, "LOGO", sizeof( logoname ) );
pszName = &logoname[ 0 ];
HANDLE hdib = (HANDLE)phdib;
COLORREF crf = RGB( r, g, b );
if ((!pszName) || (pszName[0] == 0) || (hdib == NULL))
return;
// Generate lump
unsigned char *buf = (unsigned char *)_alloca( 16384 );
CUtlBuffer buffer( 0, 16384 );
int width = 0, height = 0;
int length = GrabMip (hdib, buf, pszName, crf, &width, &height);
if ( length == 0 )
{
return;
}
bool sizevalid = false;
if ( width == height )
{
if ( width == 16 ||
width == 32 ||
width == 64 )
{
sizevalid = true;
}
}
if ( !sizevalid )
return;
while (length & 3)
length++;
// Write Header
wadinfo_t header;
header.identification[0] = 'W';
header.identification[1] = 'A';
header.identification[2] = 'D';
header.identification[3] = '3';
header.numlumps = 1;
header.infotableofs = 0;
buffer.Put( &header, sizeof( wadinfo_t ) );
// Fill Ino info table
lumpinfo_t info;
Q_memset (&info, 0, sizeof(info));
Q_strncpy(info.name, pszName, sizeof( info.name ) );
info.filepos = (int)sizeof(wadinfo_t);
info.size = info.disksize = length;
info.type = TYP_LUMPY;
info.compression = 0;
// Write Lump
buffer.Put( buf, length );
// Write info table
buffer.Put( &info, sizeof( lumpinfo_t ) );
int savepos = buffer.TellPut();
buffer.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
header.infotableofs = length + sizeof(wadinfo_t);
buffer.Put( &header, sizeof( wadinfo_t ) );
buffer.SeekPut( CUtlBuffer::SEEK_HEAD, savepos );
// Output to file
FileHandle_t file;
file = g_pFullFileSystem->Open( "pldecal.wad", "wb" );
if ( file != FILESYSTEM_INVALID_HANDLE )
{
g_pFullFileSystem->Write( buffer.Base(), buffer.TellPut(), file );
g_pFullFileSystem->Close( file );
}
}

View File

@@ -0,0 +1,212 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "ModInfo.h"
#include "KeyValues.h"
#include "vgui_controls/Controls.h"
#include "FileSystem.h"
#include "EngineInterface.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose: singleton accessor
//-----------------------------------------------------------------------------
CModInfo &ModInfo()
{
static CModInfo s_ModInfo;
return s_ModInfo;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CModInfo::CModInfo()
{
m_pModData = new KeyValues("ModData");
m_wcsGameTitle[0] = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CModInfo::~CModInfo()
{
FreeModInfo();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModInfo::FreeModInfo()
{
if (m_pModData)
{
m_pModData->deleteThis();
m_pModData = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CModInfo::IsMultiplayerOnly()
{
return (stricmp(m_pModData->GetString("type", ""), "multiplayer_only") == 0);
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CModInfo::IsSinglePlayerOnly()
{
return (stricmp(m_pModData->GetString("type", ""), "singleplayer_only") == 0);
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
const char *CModInfo::GetFallbackDir()
{
return m_pModData->GetString("fallback_dir", "");
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
const wchar_t *CModInfo::GetGameTitle()
{
if (!m_wcsGameTitle[0])
{
// for some reason, the standard ILocalize::ConvertANSIToUnicode() strips off
// the '<27>' character in 'HALF-LIFE<46>' - so just do a straight upconvert to unicode
const char *title = m_pModData->GetString("title", "");
int i = 0;
for (; title[i] != 0; ++i)
{
m_wcsGameTitle[i] = (wchar_t)title[i];
}
m_wcsGameTitle[i] = 0;
}
return m_wcsGameTitle;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
const wchar_t *CModInfo::GetGameTitle2()
{
if (!m_wcsGameTitle2[0])
{
// for some reason, the standard ILocalize::ConvertANSIToUnicode() strips off
// the '<27>' character in 'HALF-LIFE<46>' - so just do a straight upconvert to unicode
const char *title2 = m_pModData->GetString("title2", "");
int i = 0;
for (; title2[i] != 0; ++i)
{
m_wcsGameTitle2[i] = (wchar_t)title2[i];
}
m_wcsGameTitle2[i] = 0;
}
return m_wcsGameTitle2;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
const char *CModInfo::GetGameName()
{
return m_pModData->GetString("game", "");
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
KeyValues *CModInfo::GetHiddenMaps()
{
return m_pModData->FindKey( "hidden_maps" );
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CModInfo::HasPortals()
{
return (stricmp(m_pModData->GetString("hasportals", "0"), "1") == 0);
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CModInfo::NoDifficulty()
{
return (stricmp(m_pModData->GetString("nodifficulty", "0"), "1") == 0);
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CModInfo::NoModels()
{
return (stricmp(m_pModData->GetString("nomodels", "0"), "1") == 0);
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CModInfo::NoHiModel()
{
return (stricmp(m_pModData->GetString("nohimodel", "0"), "1") == 0);
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CModInfo::NoCrosshair()
{
return (stricmp(m_pModData->GetString("nocrosshair", "1"), "1") == 0);
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CModInfo::AdvCrosshair()
{
return (stricmp(m_pModData->GetString("advcrosshair", "0"), "1") == 0);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CModInfo::LoadCurrentGameInfo()
{
// Load up gameinfo for the current mod
char const *filename = "gameinfo.txt";
m_pModData->LoadFromFile( g_pFullFileSystem, filename );
}
//-----------------------------------------------------------------------------
// Purpose: loads file from null-terminated buffer
//-----------------------------------------------------------------------------
void CModInfo::LoadGameInfoFromBuffer( const char *buffer )
{
// Load up gameinfo.txt for the current mod
m_pModData->LoadFromBuffer( "", buffer );
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CModInfo::UseGameLogo()
{
return ( Q_stricmp( m_pModData->GetString( "gamelogo", "0" ), "1" ) == 0 );
}

View File

@@ -0,0 +1,64 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef MODINFO_H
#define MODINFO_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/VGUI.h>
class KeyValues;
//-----------------------------------------------------------------------------
// Purpose: contains all the data entered about a mod in gameinfo.txt
//-----------------------------------------------------------------------------
class CModInfo
{
public:
CModInfo();
~CModInfo();
void FreeModInfo();
// loads mod info from gameinfo.txt
void LoadCurrentGameInfo();
// loads gameinfo from null-terminated string
void LoadGameInfoFromBuffer( const char *buffer );
// data accessors
const wchar_t *GetGameTitle();
const wchar_t *GetGameTitle2();
const char *GetGameName();
bool IsMultiplayerOnly();
bool IsSinglePlayerOnly();
bool HasPortals();
bool NoDifficulty();
bool NoModels();
bool NoHiModel();
bool NoCrosshair();
bool AdvCrosshair();
const char *GetFallbackDir();
bool UseGameLogo();
KeyValues *GetHiddenMaps();
private:
wchar_t m_wcsGameTitle[128];
wchar_t m_wcsGameTitle2[128];
KeyValues *m_pModData;
};
// singleton accessor
extern CModInfo &ModInfo();
#endif // MODINFO_H

View File

@@ -0,0 +1,39 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "MouseMessageForwardingPanel.h"
#include "KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
CMouseMessageForwardingPanel::CMouseMessageForwardingPanel( Panel *parent, const char *name ) : BaseClass( parent, name )
{
// don't draw an
SetPaintEnabled(false);
SetPaintBackgroundEnabled(false);
SetPaintBorderEnabled(false);
}
void CMouseMessageForwardingPanel::PerformLayout()
{
// fill out the whole area
int w, t;
GetParent()->GetSize(w, t);
SetBounds(0, 0, w, t);
}
void CMouseMessageForwardingPanel::OnMousePressed( vgui::MouseCode code )
{
CallParentFunction( new KeyValues("MousePressed", "code", code) );
}
void CMouseMessageForwardingPanel::OnMouseDoublePressed( vgui::MouseCode code )
{
CallParentFunction( new KeyValues("MouseDoublePressed", "code", code) );
}

View File

@@ -0,0 +1,29 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef MOUSEMESSAGEFORWARDINGPANEL_H
#define MOUSEMESSAGEFORWARDINGPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/Panel.h"
//-----------------------------------------------------------------------------
// Purpose: Invisible panel that forwards up mouse movement
//-----------------------------------------------------------------------------
class CMouseMessageForwardingPanel : public vgui::Panel
{
DECLARE_CLASS_SIMPLE( CMouseMessageForwardingPanel, vgui::Panel );
public:
CMouseMessageForwardingPanel( Panel *parent, const char *name );
virtual void PerformLayout( void );
virtual void OnMousePressed( vgui::MouseCode code );
virtual void OnMouseDoublePressed( vgui::MouseCode code );
};
#endif //MOUSEMESSAGEFORWARDINGPANEL_H

View File

@@ -0,0 +1,446 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <time.h>
#include "MultiplayerAdvancedDialog.h"
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui_controls/ListPanel.h>
#include <KeyValues.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/MessageBox.h>
#include <vgui_controls/CheckButton.h>
#include <vgui_controls/ComboBox.h>
#include <vgui_controls/TextEntry.h>
#include "PanelListPanel.h"
#include <vgui/IInput.h>
#include "FileSystem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
#define OPTIONS_DIR "cfg"
#define DEFAULT_OPTIONS_FILE OPTIONS_DIR "/user_default.scr"
#define OPTIONS_FILE OPTIONS_DIR "/user.scr"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CMultiplayerAdvancedDialog::CMultiplayerAdvancedDialog(vgui::Panel *parent) : BaseClass(NULL, "MultiplayerAdvancedDialog")
{
SetBounds(0, 0, 372, 160);
SetSizeable( false );
SetTitle("#GameUI_MultiplayerAdvanced", true);
Button *cancel = new Button( this, "Cancel", "#GameUI_Cancel" );
cancel->SetCommand( "Close" );
Button *ok = new Button( this, "OK", "#GameUI_OK" );
ok->SetCommand( "Ok" );
m_pListPanel = new CPanelListPanel( this, "PanelListPanel" );
m_pList = NULL;
m_pDescription = new CInfoDescription( m_pListPanel );
m_pDescription->InitFromFile( DEFAULT_OPTIONS_FILE );
m_pDescription->InitFromFile( OPTIONS_FILE );
m_pDescription->TransferCurrentValues( NULL );
LoadControlSettings("Resource\\MultiplayerAdvancedDialog.res");
CreateControls();
MoveToCenterOfScreen();
SetSizeable( false );
SetDeleteSelfOnClose( true );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CMultiplayerAdvancedDialog::~CMultiplayerAdvancedDialog()
{
delete m_pDescription;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMultiplayerAdvancedDialog::Activate()
{
BaseClass::Activate();
input()->SetAppModalSurface(GetVPanel());
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMultiplayerAdvancedDialog::OnClose()
{
BaseClass::OnClose();
MarkForDeletion();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *command -
//-----------------------------------------------------------------------------
void CMultiplayerAdvancedDialog::OnCommand( const char *command )
{
if ( !stricmp( command, "Ok" ) )
{
// OnApplyChanges();
SaveValues();
OnClose();
return;
}
BaseClass::OnCommand( command );
}
void CMultiplayerAdvancedDialog::OnKeyCodeTyped(KeyCode code)
{
// force ourselves to be closed if the escape key it pressed
if (code == KEY_ESCAPE)
{
Close();
}
else
{
BaseClass::OnKeyCodeTyped(code);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMultiplayerAdvancedDialog::GatherCurrentValues()
{
if ( !m_pDescription )
return;
// OK
CheckButton *pBox;
TextEntry *pEdit;
ComboBox *pCombo;
mpcontrol_t *pList;
CScriptObject *pObj;
CScriptListItem *pItem;
char szValue[256];
char strValue[ 256 ];
pList = m_pList;
while ( pList )
{
pObj = pList->pScrObj;
if ( !pList->pControl )
{
pObj->SetCurValue( pObj->defValue );
pList = pList->next;
continue;
}
switch ( pObj->type )
{
case O_BOOL:
pBox = (CheckButton *)pList->pControl;
Q_snprintf( szValue, ARRAYSIZE( szValue ), "%s", pBox->IsSelected() ? "1" : "0" );
break;
case O_NUMBER:
pEdit = ( TextEntry * )pList->pControl;
pEdit->GetText( strValue, sizeof( strValue ) );
Q_snprintf( szValue, ARRAYSIZE( szValue ), "%s", strValue );
break;
case O_STRING:
pEdit = ( TextEntry * )pList->pControl;
pEdit->GetText( strValue, sizeof( strValue ) );
Q_snprintf( szValue, ARRAYSIZE( szValue ), "%s", strValue );
break;
case O_LIST:
pCombo = (ComboBox *)pList->pControl;
// pCombo->GetText( strValue, sizeof( strValue ) );
int activeItem = pCombo->GetActiveItem();
pItem = pObj->pListItems;
// int n = (int)pObj->fdefValue;
while ( pItem )
{
if (!activeItem--)
break;
pItem = pItem->pNext;
}
if ( pItem )
{
Q_snprintf( szValue, ARRAYSIZE( szValue ), "%s", pItem->szValue );
}
else // Couln't find index
{
//assert(!("Couldn't find string in list, using default value"));
Q_snprintf( szValue, ARRAYSIZE( szValue ), "%s", pObj->defValue );
}
break;
}
// Remove double quotes and % characters
UTIL_StripInvalidCharacters( szValue, sizeof(szValue) );
strcpy( strValue, szValue );
pObj->SetCurValue( strValue );
pList = pList->next;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMultiplayerAdvancedDialog::CreateControls()
{
DestroyControls();
// Go through desciption creating controls
CScriptObject *pObj;
pObj = m_pDescription->pObjList;
mpcontrol_t *pCtrl;
CheckButton *pBox;
TextEntry *pEdit;
ComboBox *pCombo;
CScriptListItem *pListItem;
Panel *objParent = m_pListPanel;
while ( pObj )
{
if ( pObj->type == O_OBSOLETE )
{
pObj = pObj->pNext;
continue;
}
pCtrl = new mpcontrol_t( objParent, "mpcontrol_t" );
pCtrl->type = pObj->type;
switch ( pCtrl->type )
{
case O_BOOL:
pBox = new CheckButton( pCtrl, "DescCheckButton", pObj->prompt );
pBox->SetSelected( pObj->fdefValue != 0.0f ? true : false );
pCtrl->pControl = (Panel *)pBox;
break;
case O_STRING:
case O_NUMBER:
pEdit = new TextEntry( pCtrl, "DescTextEntry");
pEdit->InsertString(pObj->defValue);
pCtrl->pControl = (Panel *)pEdit;
break;
case O_LIST:
pCombo = new ComboBox( pCtrl, "DescComboBox", 5, false );
pListItem = pObj->pListItems;
while ( pListItem )
{
pCombo->AddItem( pListItem->szItemText, NULL );
pListItem = pListItem->pNext;
}
pCombo->ActivateItemByRow((int)pObj->fdefValue);
pCtrl->pControl = (Panel *)pCombo;
break;
default:
break;
}
if ( pCtrl->type != O_BOOL )
{
pCtrl->pPrompt = new vgui::Label( pCtrl, "DescLabel", "" );
pCtrl->pPrompt->SetContentAlignment( vgui::Label::a_west );
pCtrl->pPrompt->SetTextInset( 5, 0 );
pCtrl->pPrompt->SetText( pObj->prompt );
}
pCtrl->pScrObj = pObj;
pCtrl->SetSize( 100, 28 );
//pCtrl->SetBorder( scheme()->GetBorder(1, "DepressedButtonBorder") );
m_pListPanel->AddItem( pCtrl );
// Link it in
if ( !m_pList )
{
m_pList = pCtrl;
pCtrl->next = NULL;
}
else
{
mpcontrol_t *p;
p = m_pList;
while ( p )
{
if ( !p->next )
{
p->next = pCtrl;
pCtrl->next = NULL;
break;
}
p = p->next;
}
}
pObj = pObj->pNext;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMultiplayerAdvancedDialog::DestroyControls()
{
mpcontrol_t *p, *n;
p = m_pList;
while ( p )
{
n = p->next;
//
delete p->pControl;
delete p->pPrompt;
delete p;
p = n;
}
m_pList = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMultiplayerAdvancedDialog::SaveValues()
{
// Get the values from the controls:
GatherCurrentValues();
// Create the game.cfg file
if ( m_pDescription )
{
FileHandle_t fp;
// Add settings to config.cfg
m_pDescription->WriteToConfig();
g_pFullFileSystem->CreateDirHierarchy( OPTIONS_DIR );
fp = g_pFullFileSystem->Open( OPTIONS_FILE, "wb" );
if ( fp )
{
m_pDescription->WriteToScriptFile( fp );
g_pFullFileSystem->Close( fp );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Constructor, load/save client settings object
//-----------------------------------------------------------------------------
CInfoDescription::CInfoDescription( CPanelListPanel *panel )
: CDescription( panel )
{
setHint( "// NOTE: THIS FILE IS AUTOMATICALLY REGENERATED, \r\n\
//DO NOT EDIT THIS HEADER, YOUR COMMENTS WILL BE LOST IF YOU DO\r\n\
// User options script\r\n\
//\r\n\
// Format:\r\n\
// Version [float]\r\n\
// Options description followed by \r\n\
// Options defaults\r\n\
//\r\n\
// Option description syntax:\r\n\
//\r\n\
// \"cvar\" { \"Prompt\" { type [ type info ] } { default } }\r\n\
//\r\n\
// type = \r\n\
// BOOL (a yes/no toggle)\r\n\
// STRING\r\n\
// NUMBER\r\n\
// LIST\r\n\
//\r\n\
// type info:\r\n\
// BOOL no type info\r\n\
// NUMBER min max range, use -1 -1 for no limits\r\n\
// STRING no type info\r\n\
// LIST "" delimited list of options value pairs\r\n\
//\r\n\
//\r\n\
// default depends on type\r\n\
// BOOL is \"0\" or \"1\"\r\n\
// NUMBER is \"value\"\r\n\
// STRING is \"value\"\r\n\
// LIST is \"index\", where index \"0\" is the first element of the list\r\n\r\n\r\n" );
setDescription( "INFO_OPTIONS" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInfoDescription::WriteScriptHeader( FileHandle_t fp )
{
char am_pm[] = "AM";
tm newtime;
Plat_GetLocalTime( &newtime );
g_pFullFileSystem->FPrintf( fp, (char *)getHint() );
char timeString[64];
Plat_GetTimeString( &newtime, timeString, sizeof( timeString ) );
// Write out the comment and Cvar Info:
g_pFullFileSystem->FPrintf( fp, "// Half-Life User Info Configuration Layout Script (stores last settings chosen, too)\r\n" );
g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", timeString, am_pm );
g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" );
g_pFullFileSystem->FPrintf( fp, "VERSION %.1f\r\n\r\n", SCRIPT_VERSION );
g_pFullFileSystem->FPrintf( fp, "DESCRIPTION INFO_OPTIONS\r\n{\r\n" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInfoDescription::WriteFileHeader( FileHandle_t fp )
{
char am_pm[] = "AM";
tm newtime;
Plat_GetLocalTime( &newtime );
char timeString[64];
Plat_GetTimeString( &newtime, timeString, sizeof( timeString ) );
g_pFullFileSystem->FPrintf( fp, "// Half-Life User Info Configuration Settings\r\n" );
g_pFullFileSystem->FPrintf( fp, "// DO NOT EDIT, GENERATED BY HALF-LIFE\r\n" );
g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", timeString, am_pm );
g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" );
}
//-----------------------------------------------------------------------------

View File

@@ -0,0 +1,50 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef MULTIPLAYERADVANCEDDIALOG_H
#define MULTIPLAYERADVANCEDDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Frame.h>
#include "ScriptObject.h"
#include <vgui/KeyCode.h>
//-----------------------------------------------------------------------------
// Purpose: Displays a game-specific list of options
//-----------------------------------------------------------------------------
class CMultiplayerAdvancedDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CMultiplayerAdvancedDialog, vgui::Frame );
public:
CMultiplayerAdvancedDialog(vgui::Panel *parent);
~CMultiplayerAdvancedDialog();
virtual void Activate();
private:
void CreateControls();
void DestroyControls();
void GatherCurrentValues();
void SaveValues();
CInfoDescription *m_pDescription;
mpcontrol_t *m_pList;
CPanelListPanel *m_pListPanel;
virtual void OnCommand( const char *command );
virtual void OnClose();
virtual void OnKeyCodeTyped(vgui::KeyCode code);
};
#endif // MULTIPLAYERADVANCEDDIALOG_H

View File

@@ -0,0 +1,149 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "OptionsDialog.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/CheckButton.h"
#include "vgui_controls/PropertySheet.h"
#include "vgui_controls/Label.h"
#include "vgui_controls/QueryBox.h"
#include "vgui/ILocalize.h"
#include "vgui/ISurface.h"
#include "vgui/ISystem.h"
#include "vgui/IVGui.h"
#include "KeyValues.h"
#include "OptionsSubKeyboard.h"
#include "OptionsSubMouse.h"
#include "OptionsSubAudio.h"
#include "OptionsSubVideo.h"
#include "OptionsSubVoice.h"
#include "OptionsSubMultiplayer.h"
#include "OptionsSubDifficulty.h"
#include "OptionsSubPortal.h"
#include "ModInfo.h"
using namespace vgui;
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Basic help dialog
//-----------------------------------------------------------------------------
COptionsDialog::COptionsDialog(vgui::Panel *parent, OptionsDialogTabStyle iTabStyle) : PropertyDialog(parent, "OptionsDialog")
{
SetProportional( true );
SetDeleteSelfOnClose( true );
SetBounds(
0,
0,
vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), 512 ),
vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), 415 ) );
SetSizeable( false );
// debug timing code, this function takes too long
// double s4 = system()->GetCurrentTime();
if ( iTabStyle == OPTIONS_DIALOG_ALL_TABS )
{
SetTitle("#GameUI_Options", true);
if ( ModInfo().IsSinglePlayerOnly() && !ModInfo().NoDifficulty() )
{
AddPage(new COptionsSubDifficulty(this), "#GameUI_Difficulty");
}
if ( ModInfo().HasPortals() )
{
AddPage(new COptionsSubPortal(this), "#GameUI_Portal");
}
AddPage(new COptionsSubKeyboard(this), "#GameUI_Keyboard");
AddPage(new COptionsSubMouse(this), "#GameUI_Mouse");
m_pOptionsSubAudio = new COptionsSubAudio(this);
AddPage(m_pOptionsSubAudio, "#GameUI_Audio");
m_pOptionsSubVideo = new COptionsSubVideo(this);
AddPage(m_pOptionsSubVideo, "#GameUI_Video");
if ( !ModInfo().IsSinglePlayerOnly() )
{
AddPage(new COptionsSubVoice(this), "#GameUI_Voice");
}
// add the multiplay page last, if we're combo single/multi or just multi
if ( (ModInfo().IsMultiplayerOnly() && !ModInfo().IsSinglePlayerOnly()) ||
(!ModInfo().IsMultiplayerOnly() && !ModInfo().IsSinglePlayerOnly()) )
{
AddPage(new COptionsSubMultiplayer(this), "#GameUI_Multiplayer");
}
}
else if ( iTabStyle == OPTIONS_DIALOG_ONLY_BINDING_TABS )
{
SetTitle("#L4D360UI_Controller_Edit_Keys_Buttons", true);
AddPage(new COptionsSubKeyboard(this), "#GameUI_Console_UserSettings");
}
// double s5 = system()->GetCurrentTime();
// Msg("COptionsDialog::COptionsDialog(): %.3fms\n", (float)(s5 - s4) * 1000.0f);
SetApplyButtonVisible(true);
GetPropertySheet()->SetTabWidth(84);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
COptionsDialog::~COptionsDialog()
{
}
//-----------------------------------------------------------------------------
// Purpose: Brings the dialog to the fore
//-----------------------------------------------------------------------------
void COptionsDialog::Activate()
{
BaseClass::Activate();
EnableApplyButton(false);
}
//-----------------------------------------------------------------------------
// Purpose: Opens the dialog
//-----------------------------------------------------------------------------
void COptionsDialog::Run()
{
SetTitle("#GameUI_Options", true);
Activate();
}
//-----------------------------------------------------------------------------
// Purpose: Opens the gamma dialog directly
//-----------------------------------------------------------------------------
void COptionsDialog::OpenGammaDialog()
{
m_pOptionsSubVideo->OpenGammaDialog();
}
//-----------------------------------------------------------------------------
// Purpose: Called when the GameUI is hidden
//-----------------------------------------------------------------------------
void COptionsDialog::OnGameUIHidden()
{
// tell our children about it
for ( int i = 0 ; i < GetChildCount() ; i++ )
{
Panel *pChild = GetChild( i );
if ( pChild )
{
PostMessage( pChild, new KeyValues( "GameUIHidden" ) );
}
}
}

View File

@@ -0,0 +1,53 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef OPTIONSDIALOG_H
#define OPTIONSDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/PropertyDialog.h"
enum OptionsDialogTabStyle
{
OPTIONS_DIALOG_ALL_TABS,
OPTIONS_DIALOG_ONLY_BINDING_TABS,
OPTIONS_DIALOG_TAB_STYLE_TOTAL
};
//-----------------------------------------------------------------------------
// Purpose: Holds all the game option pages
//-----------------------------------------------------------------------------
class COptionsDialog : public vgui::PropertyDialog
{
DECLARE_CLASS_SIMPLE( COptionsDialog, vgui::PropertyDialog );
public:
COptionsDialog(vgui::Panel *parent, OptionsDialogTabStyle iTabStyle = OPTIONS_DIALOG_ALL_TABS );
~COptionsDialog();
void Run();
virtual void Activate();
void OpenGammaDialog();
MESSAGE_FUNC( OnGameUIHidden, "GameUIHidden" ); // called when the GameUI is hidden
private:
class COptionsSubAudio *m_pOptionsSubAudio;
class COptionsSubVideo *m_pOptionsSubVideo;
};
#define OPTIONS_MAX_NUM_ITEMS 15
struct OptionData_t;
#endif // OPTIONSDIALOG_H

View File

@@ -0,0 +1,413 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "OptionsSubAudio.h"
#include "CvarSlider.h"
#include "EngineInterface.h"
#include "ModInfo.h"
#include "vgui_controls/ComboBox.h"
#include "vgui_controls/QueryBox.h"
#include "tier1/KeyValues.h"
#include "tier1/convar.h"
#include "vgui/IInput.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
#include "tier1/strtools.h"
#include "gameui_util.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
// This member is static so that the updated audio language can be referenced during shutdown
char* COptionsSubAudio::m_pchUpdatedAudioLanguage = (char*)GetLanguageShortName( k_Lang_English );
enum SoundQuality_e
{
SOUNDQUALITY_LOW,
SOUNDQUALITY_MEDIUM,
SOUNDQUALITY_HIGH,
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
COptionsSubAudio::COptionsSubAudio(vgui::Panel *parent) : PropertyPage(parent, NULL)
{
m_pSFXSlider = new CCvarSlider( this, "SFXSlider", "#GameUI_SoundEffectVolume", 0.0f, 1.0f, "volume" );
m_pMusicSlider = new CCvarSlider( this, "MusicSlider", "#GameUI_MusicVolume", 0.0f, 1.0f, "Snd_MusicVolume" );
m_pCloseCaptionCombo = new ComboBox( this, "CloseCaptionCheck", 6, false );
m_pCloseCaptionCombo->AddItem( "#GameUI_NoClosedCaptions", NULL );
m_pCloseCaptionCombo->AddItem( "#GameUI_SubtitlesAndSoundEffects", NULL );
m_pCloseCaptionCombo->AddItem( "#GameUI_Subtitles", NULL );
m_pSoundQualityCombo = new ComboBox( this, "SoundQuality", 6, false );
m_pSoundQualityCombo->AddItem( "#GameUI_High", new KeyValues("SoundQuality", "quality", SOUNDQUALITY_HIGH) );
m_pSoundQualityCombo->AddItem( "#GameUI_Medium", new KeyValues("SoundQuality", "quality", SOUNDQUALITY_MEDIUM) );
m_pSoundQualityCombo->AddItem( "#GameUI_Low", new KeyValues("SoundQuality", "quality", SOUNDQUALITY_LOW) );
m_pSpeakerSetupCombo = new ComboBox( this, "SpeakerSetup", 6, false );
m_pSpeakerSetupCombo->AddItem( "#GameUI_Headphones", new KeyValues("SpeakerSetup", "speakers", 0) );
m_pSpeakerSetupCombo->AddItem( "#GameUI_2Speakers", new KeyValues("SpeakerSetup", "speakers", 2) );
m_pSpeakerSetupCombo->AddItem( "#GameUI_4Speakers", new KeyValues("SpeakerSetup", "speakers", 4) );
m_pSpeakerSetupCombo->AddItem( "#GameUI_5Speakers", new KeyValues("SpeakerSetup", "speakers", 5) );
m_pSpeakerSetupCombo->AddItem( "#GameUI_7Speakers", new KeyValues("SpeakerSetup", "speakers", 7) );
m_pSpokenLanguageCombo = new ComboBox (this, "AudioSpokenLanguage", 6, false );
LoadControlSettings("Resource\\OptionsSubAudio.res");
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
COptionsSubAudio::~COptionsSubAudio()
{
}
//-----------------------------------------------------------------------------
// Purpose: Reloads data
//-----------------------------------------------------------------------------
void COptionsSubAudio::OnResetData()
{
m_bRequireRestart = false;
m_pSFXSlider->Reset();
m_pMusicSlider->Reset();
// reset the combo boxes
// close captions
CGameUIConVarRef closecaption("closecaption");
CGameUIConVarRef cc_subtitles("cc_subtitles");
if (closecaption.GetBool())
{
if (cc_subtitles.GetBool())
{
m_pCloseCaptionCombo->ActivateItem(2);
}
else
{
m_pCloseCaptionCombo->ActivateItem(1);
}
}
else
{
m_pCloseCaptionCombo->ActivateItem(0);
}
// speakers
CGameUIConVarRef snd_surround_speakers("Snd_Surround_Speakers");
int speakers = snd_surround_speakers.GetInt();
{for (int itemID = 0; itemID < m_pSpeakerSetupCombo->GetItemCount(); itemID++)
{
KeyValues *kv = m_pSpeakerSetupCombo->GetItemUserData(itemID);
if (kv && kv->GetInt("speakers") == speakers)
{
m_pSpeakerSetupCombo->ActivateItem(itemID);
}
}}
// sound quality is made up from several cvars
CGameUIConVarRef Snd_PitchQuality("Snd_PitchQuality");
CGameUIConVarRef dsp_slow_cpu("dsp_slow_cpu");
int quality = SOUNDQUALITY_LOW;
if (dsp_slow_cpu.GetBool() == false)
{
quality = SOUNDQUALITY_MEDIUM;
}
if (Snd_PitchQuality.GetBool())
{
quality = SOUNDQUALITY_HIGH;
}
// find the item in the list and activate it
{for (int itemID = 0; itemID < m_pSoundQualityCombo->GetItemCount(); itemID++)
{
KeyValues *kv = m_pSoundQualityCombo->GetItemUserData(itemID);
if (kv && kv->GetInt("quality") == quality)
{
m_pSoundQualityCombo->ActivateItem(itemID);
}
}}
//
// Audio Languages
//
char szCurrentLanguage[50] = "";
char szAvailableLanguages[512] = "";
szAvailableLanguages[0] = NULL;
// Fallback to current engine language
engine->GetUILanguage( szCurrentLanguage, sizeof( szCurrentLanguage ));
// In a Steam environment we get the current language
#if !defined( NO_STEAM )
// When Steam isn't running we can't get the language info...
if ( steamapicontext->SteamApps() )
{
Q_strncpy( szCurrentLanguage, steamapicontext->SteamApps()->GetCurrentGameLanguage(), sizeof(szCurrentLanguage) );
Q_strncpy( szAvailableLanguages, steamapicontext->SteamApps()->GetAvailableGameLanguages(), sizeof(szAvailableLanguages) );
}
#endif
// Get the spoken language and store it for comparison purposes
m_nCurrentAudioLanguage = PchLanguageToELanguage( szCurrentLanguage );
// Check to see if we have a list of languages from Steam
if ( V_strlen( szAvailableLanguages ) )
{
// Populate the combo box with each available language
CSplitString languagesList( szAvailableLanguages, "," );
for ( int i=0; i < languagesList.Count(); i++ )
{
const ELanguage languageCode = PchLanguageToELanguage( languagesList[i] );
m_pSpokenLanguageCombo->AddItem( GetLanguageVGUILocalization( languageCode ), new KeyValues ("Audio Languages", "language", languageCode) );
}
}
else
{
// Add the current language to the combo
m_pSpokenLanguageCombo->AddItem( GetLanguageVGUILocalization( m_nCurrentAudioLanguage ), new KeyValues ("Audio Languages", "language", m_nCurrentAudioLanguage) );
}
// Activate the current language in the combo
{for (int itemID = 0; itemID < m_pSpokenLanguageCombo->GetItemCount(); itemID++)
{
KeyValues *kv = m_pSpokenLanguageCombo->GetItemUserData( itemID );
if ( kv && kv->GetInt( "language" ) == m_nCurrentAudioLanguage )
{
m_pSpokenLanguageCombo->ActivateItem( itemID );
break;
}
}}
}
//-----------------------------------------------------------------------------
// Purpose: Applies changes
//-----------------------------------------------------------------------------
void COptionsSubAudio::OnApplyChanges()
{
m_pSFXSlider->ApplyChanges();
m_pMusicSlider->ApplyChanges();
// set the cvars appropriately
// Tracker 28933: Note we can't do this because closecaption is marked
// FCVAR_USERINFO and it won't get sent to server is we direct set it, we
// need to pass it along to the engine parser!!!
// ConVar *closecaption = (ConVar *)cvar->FindVar("closecaption");
int closecaption_value = 0;
CGameUIConVarRef cc_subtitles( "cc_subtitles" );
switch (m_pCloseCaptionCombo->GetActiveItem())
{
default:
case 0:
closecaption_value = 0;
cc_subtitles.SetValue( 0 );
break;
case 1:
closecaption_value = 1;
cc_subtitles.SetValue( 0 );
break;
case 2:
closecaption_value = 1;
cc_subtitles.SetValue( 1 );
break;
}
// Stuff the close caption change to the console so that it can be
// sent to the server (FCVAR_USERINFO) so that you don't have to restart
// the level for the change to take effect.
char cmd[ 64 ];
Q_snprintf( cmd, sizeof( cmd ), "closecaption %i\n", closecaption_value );
engine->ClientCmd_Unrestricted( cmd );
CGameUIConVarRef snd_surround_speakers( "Snd_Surround_Speakers" );
int speakers = m_pSpeakerSetupCombo->GetActiveItemUserData()->GetInt( "speakers" );
snd_surround_speakers.SetValue( speakers );
// quality
CGameUIConVarRef Snd_PitchQuality( "Snd_PitchQuality" );
CGameUIConVarRef dsp_slow_cpu( "dsp_slow_cpu" );
int quality = m_pSoundQualityCombo->GetActiveItemUserData()->GetInt( "quality" );
switch ( quality )
{
case SOUNDQUALITY_LOW:
dsp_slow_cpu.SetValue(true);
Snd_PitchQuality.SetValue(false);
break;
case SOUNDQUALITY_MEDIUM:
dsp_slow_cpu.SetValue(false);
Snd_PitchQuality.SetValue(false);
break;
default:
Assert("Undefined sound quality setting.");
case SOUNDQUALITY_HIGH:
dsp_slow_cpu.SetValue(false);
Snd_PitchQuality.SetValue(true);
break;
};
// headphones at high quality get enhanced stereo turned on
CGameUIConVarRef dsp_enhance_stereo( "dsp_enhance_stereo" );
if (speakers == 0 && quality == SOUNDQUALITY_HIGH)
{
dsp_enhance_stereo.SetValue( 1 );
}
else
{
dsp_enhance_stereo.SetValue( 0 );
}
// Audio spoken language
KeyValues *kv = m_pSpokenLanguageCombo->GetItemUserData( m_pSpokenLanguageCombo->GetActiveItem() );
const ELanguage nUpdatedAudioLanguage = (ELanguage)( kv ? kv->GetInt( "language" ) : k_Lang_English );
if ( nUpdatedAudioLanguage != m_nCurrentAudioLanguage )
{
// Store new language in static member so that it can be accessed during shutdown when this instance is gone
m_pchUpdatedAudioLanguage = (char *) GetLanguageShortName( nUpdatedAudioLanguage );
// Inform user that they need to restart in order change language at this time
QueryBox *qb = new QueryBox( "#GameUI_ChangeLanguageRestart_Title", "#GameUI_ChangeLanguageRestart_Info", GetParent()->GetParent()->GetParent() );
if (qb != NULL)
{
qb->SetOKCommand( new KeyValues( "Command", "command", "RestartWithNewLanguage" ) );
qb->SetOKButtonText( "#GameUI_ChangeLanguageRestart_OkButton" );
qb->SetCancelButtonText( "#GameUI_ChangeLanguageRestart_CancelButton" );
qb->AddActionSignalTarget( GetParent()->GetParent()->GetParent() );
qb->DoModal();
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Called on controls changing, enables the Apply button
//-----------------------------------------------------------------------------
void COptionsSubAudio::OnControlModified()
{
PostActionSignal(new KeyValues("ApplyButtonEnable"));
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the engine needs to be restarted
//-----------------------------------------------------------------------------
bool COptionsSubAudio::RequiresRestart()
{
// nothing in audio requires a restart like now
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubAudio::OnCommand( const char *command )
{
if ( !stricmp( command, "TestSpeakers" ) )
{
// ask them if they REALLY want to test the speakers if they're in a game already.
if (engine->IsConnected())
{
QueryBox *qb = new QueryBox("#GameUI_TestSpeakersWarning_Title", "#GameUI_TestSpeakersWarning_Info" );
if (qb != NULL)
{
qb->SetOKCommand(new KeyValues("RunTestSpeakers"));
qb->SetOKButtonText("#GameUI_TestSpeakersWarning_OkButton");
qb->SetCancelButtonText("#GameUI_TestSpeakersWarning_CancelButton");
qb->AddActionSignalTarget( this );
qb->DoModal();
}
else
{
// couldn't create the warning dialog for some reason, so just test the speakers.
RunTestSpeakers();
}
}
else
{
// player isn't connected to a game so there's no reason to warn them about being disconnected.
// create the command to execute
RunTestSpeakers();
}
}
else if ( !stricmp( command, "ShowThirdPartyAudioCredits" ) )
{
OpenThirdPartySoundCreditsDialog();
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose: Run the test speakers map.
//-----------------------------------------------------------------------------
void COptionsSubAudio::RunTestSpeakers()
{
engine->ClientCmd_Unrestricted( "disconnect\nwait\nwait\nsv_lan 1\nsetmaster enable\nmaxplayers 1\n\nhostname \"Speaker Test\"\nprogress_enable\nmap test_speakers\n" );
}
//-----------------------------------------------------------------------------
// Purpose: Open third party audio credits dialog
//-----------------------------------------------------------------------------
void COptionsSubAudio::OpenThirdPartySoundCreditsDialog()
{
if (!m_OptionsSubAudioThirdPartyCreditsDlg.Get())
{
m_OptionsSubAudioThirdPartyCreditsDlg = new COptionsSubAudioThirdPartyCreditsDlg(GetVParent());
}
m_OptionsSubAudioThirdPartyCreditsDlg->Activate();
}
COptionsSubAudioThirdPartyCreditsDlg::COptionsSubAudioThirdPartyCreditsDlg( vgui::VPANEL hParent ) : BaseClass( NULL, NULL )
{
SetProportional( true );
#ifdef GAMEUI_BASEMODPANEL_VGUI
// parent is ignored, since we want look like we're steal focus from the parent (we'll become modal below)
SetScheme( GAMEUI_BASEMODPANEL_SCHEME );
#endif
SetTitle( "#GameUI_ThirdPartyAudio_Title", true );
SetSize(
vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), 500 ),
vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), 200 ) );
MoveToCenterOfScreen();
SetSizeable( false );
SetDeleteSelfOnClose( true );
}
void COptionsSubAudioThirdPartyCreditsDlg::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/OptionsSubAudioThirdPartyDlg.res" );
}
void COptionsSubAudioThirdPartyCreditsDlg::Activate()
{
BaseClass::Activate();
input()->SetAppModalSurface(GetVPanel());
}
void COptionsSubAudioThirdPartyCreditsDlg::OnKeyCodeTyped(vgui::KeyCode code)
{
// force ourselves to be closed if the escape key it pressed
if (code == KEY_ESCAPE)
{
Close();
}
else
{
BaseClass::OnKeyCodeTyped(code);
}
}

View File

@@ -0,0 +1,80 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef OPTIONS_SUB_AUDIO_H
#define OPTIONS_SUB_AUDIO_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/PropertyPage.h"
#include <language.h>
#include "vgui_controls/frame.h"
#include "vgui/keycode.h"
class CLabeledCommandComboBox;
class CCvarSlider;
//-----------------------------------------------------------------------------
// Purpose: Audio Details, Part of OptionsDialog
//-----------------------------------------------------------------------------
class COptionsSubAudio : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( COptionsSubAudio, vgui::PropertyPage );
public:
COptionsSubAudio(vgui::Panel *parent);
~COptionsSubAudio();
virtual void OnResetData();
virtual void OnApplyChanges();
virtual void OnCommand( const char *command );
bool RequiresRestart();
static char* GetUpdatedAudioLanguage() { return m_pchUpdatedAudioLanguage; }
private:
MESSAGE_FUNC( OnControlModified, "ControlModified" );
MESSAGE_FUNC( OnTextChanged, "TextChanged" )
{
OnControlModified();
}
MESSAGE_FUNC( RunTestSpeakers, "RunTestSpeakers" );
vgui::ComboBox *m_pSpeakerSetupCombo;
vgui::ComboBox *m_pSoundQualityCombo;
CCvarSlider *m_pSFXSlider;
CCvarSlider *m_pMusicSlider;
vgui::ComboBox *m_pCloseCaptionCombo;
bool m_bRequireRestart;
vgui::ComboBox *m_pSpokenLanguageCombo;
MESSAGE_FUNC( OpenThirdPartySoundCreditsDialog, "OpenThirdPartySoundCreditsDialog" );
vgui::DHANDLE<class COptionsSubAudioThirdPartyCreditsDlg> m_OptionsSubAudioThirdPartyCreditsDlg;
ELanguage m_nCurrentAudioLanguage;
static char *m_pchUpdatedAudioLanguage;
};
//-----------------------------------------------------------------------------
// Purpose: third-party audio credits dialog
//-----------------------------------------------------------------------------
class COptionsSubAudioThirdPartyCreditsDlg : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( COptionsSubAudioThirdPartyCreditsDlg, vgui::Frame );
public:
COptionsSubAudioThirdPartyCreditsDlg( vgui::VPANEL hParent );
virtual void Activate();
void OnKeyCodeTyped(vgui::KeyCode code);
protected:
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
};
#endif // OPTIONS_SUB_AUDIO_H

View File

@@ -0,0 +1,79 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "OptionsSubDifficulty.h"
#include "tier1/convar.h"
#include "EngineInterface.h"
#include "tier1/KeyValues.h"
#include "vgui_controls/RadioButton.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
COptionsSubDifficulty::COptionsSubDifficulty(vgui::Panel *parent) : BaseClass(parent, NULL)
{
m_pEasyRadio = new RadioButton(this, "Skill1Radio", "#GameUI_SkillEasy");
m_pNormalRadio = new RadioButton(this, "Skill2Radio", "#GameUI_SkillNormal");
m_pHardRadio = new RadioButton(this, "Skill3Radio", "#GameUI_SkillHard");
LoadControlSettings("Resource/OptionsSubDifficulty.res");
}
//-----------------------------------------------------------------------------
// Purpose: resets controls
//-----------------------------------------------------------------------------
void COptionsSubDifficulty::OnResetData()
{
ConVarRef var( "skill" );
if (var.GetInt() == 1)
{
m_pEasyRadio->SetSelected(true);
}
else if (var.GetInt() == 3)
{
m_pHardRadio->SetSelected(true);
}
else
{
m_pNormalRadio->SetSelected(true);
}
}
//-----------------------------------------------------------------------------
// Purpose: sets data based on control settings
//-----------------------------------------------------------------------------
void COptionsSubDifficulty::OnApplyChanges()
{
ConVarRef var( "skill" );
if ( m_pEasyRadio->IsSelected() )
{
var.SetValue( 1 );
}
else if ( m_pHardRadio->IsSelected() )
{
var.SetValue( 3 );
}
else
{
var.SetValue( 2 );
}
}
//-----------------------------------------------------------------------------
// Purpose: enables apply button on radio buttons being pressed
//-----------------------------------------------------------------------------
void COptionsSubDifficulty::OnRadioButtonChecked()
{
PostActionSignal(new KeyValues("ApplyButtonEnable"));
}

View File

@@ -0,0 +1,38 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef OPTIONS_SUB_DIFFICULTY_H
#define OPTIONS_SUB_DIFFICULTY_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/PropertyPage.h"
//-----------------------------------------------------------------------------
// Purpose: Difficulty selection options
//-----------------------------------------------------------------------------
class COptionsSubDifficulty : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( COptionsSubDifficulty, vgui::PropertyPage );
public:
COptionsSubDifficulty(vgui::Panel *parent);
virtual void OnResetData();
virtual void OnApplyChanges();
MESSAGE_FUNC( OnRadioButtonChecked, "RadioButtonChecked" );
private:
vgui::RadioButton *m_pEasyRadio;
vgui::RadioButton *m_pNormalRadio;
vgui::RadioButton *m_pHardRadio;
};
#endif // OPTIONS_SUB_DIFFICULTY_H

View File

@@ -0,0 +1,43 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "OptionsSubGame.h"
#include "BasePanel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
COptionsSubGame::COptionsSubGame( vgui::Panel *parent, const char *name ) : BaseClass( parent, name )
{
SetDeleteSelfOnClose( true );
LoadControlSettings( "Resource/OptionsSubGame.res" );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
COptionsSubGame::~COptionsSubGame()
{
}
void COptionsSubGame::OnClose( void )
{
#if defined( BASEPANEL_LEGACY_SOURCE1 )
BasePanel()->RunCloseAnimation( "CloseOptionsSubGame" );
#endif
BaseClass::OnClose();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubGame::OnCommand( const char *command )
{
BaseClass::OnCommand( command );
}

View File

@@ -0,0 +1,35 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef OPTIONS_SUB_GAME_H
#define OPTIONS_SUB_GAME_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/Frame.h"
//-----------------------------------------------------------------------------
// Purpose: Game Settings, Part of OptionsDialog
//-----------------------------------------------------------------------------
class COptionsSubGame : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( COptionsSubGame, vgui::Frame );
public:
COptionsSubGame( vgui::Panel *parent, const char *name );
~COptionsSubGame( void );
virtual void OnCommand( const char *command );
virtual void OnClose( void );
private:
};
#endif // OPTIONS_SUB_GAME_H

View File

@@ -0,0 +1,898 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "OptionsSubKeyboard.h"
#include "EngineInterface.h"
#include "VControlsListPanel.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/Label.h"
#include "vgui_controls/ListPanel.h"
#include "vgui_controls/QueryBox.h"
#include "vgui/Cursor.h"
#include "vgui/IVGui.h"
#include "vgui/ISurface.h"
#include "tier1/KeyValues.h"
#include "tier1/convar.h"
#include "vgui/KeyCode.h"
#include "vgui/MouseCode.h"
#include "vgui/ISystem.h"
#include "vgui/IInput.h"
#include "FileSystem.h"
#include "tier1/UtlBuffer.h"
#include "igameuifuncs.h"
#include "vstdlib/IKeyValuesSystem.h"
#include "tier2/tier2.h"
#include "inputsystem/iinputsystem.h"
#include "gameui_util.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
COptionsSubKeyboard::COptionsSubKeyboard(vgui::Panel *parent) : PropertyPage(parent, NULL)
{
Q_memset( m_Bindings, 0, sizeof( m_Bindings ));
m_nSplitScreenUser = 0;
// For joystick buttons, controls which user are binding/unbinding
if ( !IsGameConsole() )
{
//HACK HACK: Probably the entire gameui needs to have a splitscrene context for which player the settings apply to, but this is only
// on the PC...
static CGameUIConVarRef in_forceuser( "in_forceuser" );
if ( in_forceuser.IsValid() )
{
m_nSplitScreenUser = clamp( in_forceuser.GetInt(), 0, 1 );
}
else
{
m_nSplitScreenUser = MAX( 0, engine->GetActiveSplitScreenPlayerSlot() );
}
}
// create the key bindings list
CreateKeyBindingList();
// Store all current key bindings
SaveCurrentBindings();
// Parse default descriptions
ParseActionDescriptions();
m_pSetBindingButton = new Button(this, "ChangeKeyButton", "");
m_pClearBindingButton = new Button(this, "ClearKeyButton", "");
LoadControlSettings("Resource/OptionsSubKeyboard.res");
m_pSetBindingButton->SetEnabled(false);
m_pClearBindingButton->SetEnabled(false);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
COptionsSubKeyboard::~COptionsSubKeyboard()
{
DeleteSavedBindings();
}
//-----------------------------------------------------------------------------
// Purpose: reloads current keybinding
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::OnResetData()
{
// Populate list based on current settings
FillInCurrentBindings();
if ( IsVisible() )
{
m_pKeyBindList->SetSelectedItem(0);
}
}
//-----------------------------------------------------------------------------
// Purpose: saves out keybinding changes
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::OnApplyChanges()
{
ApplyAllBindings();
}
//-----------------------------------------------------------------------------
// Purpose: Create key bindings list control
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::CreateKeyBindingList()
{
// Create the control
m_pKeyBindList = new VControlsListPanel(this, "listpanel_keybindlist");
}
//-----------------------------------------------------------------------------
// Purpose: binds double-clicking or hitting enter in the keybind list to changing the key
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::OnKeyCodeTyped(vgui::KeyCode code)
{
if (code == KEY_ENTER)
{
OnCommand("ChangeKey");
}
else
{
BaseClass::OnKeyCodeTyped(code);
}
}
//-----------------------------------------------------------------------------
// Purpose: command handler
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::OnCommand( const char *command )
{
if ( !stricmp( command, "Defaults" ) )
{
// open a box asking if we want to restore defaults
QueryBox *box = new QueryBox("#GameUI_KeyboardSettings", "#GameUI_KeyboardSettingsText");
box->AddActionSignalTarget(this);
box->SetOKCommand(new KeyValues("Command", "command", "DefaultsOK"));
box->DoModal();
}
else if ( !stricmp(command, "DefaultsOK"))
{
// Restore defaults from default keybindings file
FillInDefaultBindings();
m_pKeyBindList->RequestFocus();
}
else if ( !m_pKeyBindList->IsCapturing() && !stricmp( command, "ChangeKey" ) )
{
m_pKeyBindList->StartCaptureMode(dc_blank);
}
else if ( !m_pKeyBindList->IsCapturing() && !stricmp( command, "ClearKey" ) )
{
// OnKeyCodePressed( ButtonCodeToJoystickButtonCode( KEY_DELETE, CL4DBasePanel::GetSingleton().GetLastActiveUserId() ) );
OnKeyCodePressed( KEY_DELETE ); // <<< PC only code, no need for joystick management
m_pKeyBindList->RequestFocus();
}
else if ( !stricmp(command, "Advanced") )
{
OpenKeyboardAdvancedDialog();
}
else
{
BaseClass::OnCommand( command );
}
}
const char *UTIL_Parse( const char *data, char *token, int sizeofToken )
{
data = engine->ParseFile( data, token, sizeofToken );
return data;
}
static char *UTIL_CopyString( const char *in )
{
int len = strlen( in ) + 1;
char *out = new char[ len ];
Q_strncpy( out, in, len );
return out;
}
char *UTIL_va(char *format, ...)
{
va_list argptr;
static char string[4][1024];
static int curstring = 0;
curstring = ( curstring + 1 ) % 4;
va_start (argptr, format);
Q_vsnprintf( string[curstring], 1024, format, argptr );
va_end (argptr);
return string[curstring];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::ParseActionDescriptions( void )
{
char szBinding[256];
char szDescription[256];
KeyValues *item;
// Load the default keys list
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
if ( !g_pFullFileSystem->ReadFile( "scripts/kb_act.lst", NULL, buf ) )
return;
const char *data = (const char*)buf.Base();
int sectionIndex = 0;
char token[512];
while ( 1 )
{
data = UTIL_Parse( data, token, sizeof(token) );
// Done.
if ( strlen( token ) <= 0 )
break;
Q_strncpy( szBinding, token, sizeof( szBinding ) );
data = UTIL_Parse( data, token, sizeof(token) );
if ( strlen(token) <= 0 )
{
break;
}
Q_strncpy(szDescription, token, sizeof( szDescription ) );
// Skip '======' rows
if ( szDescription[ 0 ] != '=' )
{
// Flag as special header row if binding is "blank"
if (!stricmp(szBinding, "blank"))
{
// add header item
int nColumn1 = 286;
int nColumn2 = 128;
if ( IsProportional() )
{
nColumn1 = vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), nColumn1 );
nColumn2 = vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), nColumn2 );
}
m_pKeyBindList->AddSection(++sectionIndex, szDescription);
m_pKeyBindList->AddColumnToSection(sectionIndex, "Action", szDescription, SectionedListPanel::COLUMN_BRIGHT, nColumn1 );
m_pKeyBindList->AddColumnToSection(sectionIndex, "Key", "#GameUI_KeyButton", SectionedListPanel::COLUMN_BRIGHT, nColumn2 );
}
else
{
// Create a new: blank item
item = new KeyValues( "Item" );
// fill in data
item->SetString("Action", szDescription);
item->SetString("Binding", szBinding);
item->SetString("Key", "");
// Add to list
m_pKeyBindList->AddItem(sectionIndex, item);
item->deleteThis();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Search current data set for item which has the specified binding string
// Input : *binding - string to find
// Output : KeyValues or NULL on failure
//-----------------------------------------------------------------------------
KeyValues *COptionsSubKeyboard::GetItemForBinding( const char *binding )
{
static int bindingSymbol = KeyValuesSystem()->GetSymbolForString("Binding");
// Loop through all items
for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
{
KeyValues *item = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
if ( !item )
continue;
KeyValues *bindingItem = item->FindKey(bindingSymbol);
const char *bindString = bindingItem->GetString();
// Check the "Binding" key
if (!stricmp(bindString, binding))
return item;
}
// Didn't find it
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Bind the specified keyname to the specified item
// Input : *item - Item to which to add the key
// *keyname - The key to be added
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::AddBinding( KeyValues *item, const char *keyname )
{
// See if it's already there as a binding
if ( !stricmp( item->GetString( "Key", "" ), keyname ) )
return;
// Make sure it doesn't live anywhere
RemoveKeyFromBindItems( item, keyname );
const char *binding = item->GetString( "Binding", "" );
// Loop through all the key bindings and set all entries that have
// the same binding. This allows us to have multiple entries pointing
// to the same binding.
for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
{
KeyValues *curitem = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
if ( !curitem )
continue;
const char *curbinding = curitem->GetString( "Binding", "" );
if (!stricmp(curbinding, binding))
{
curitem->SetString( "Key", keyname );
m_pKeyBindList->InvalidateItem(i);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Remove all keys from list
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::ClearBindItems( void )
{
for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
{
KeyValues *item = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
if ( !item )
continue;
// Reset keys
item->SetString( "Key", "" );
m_pKeyBindList->InvalidateItem(i);
}
m_pKeyBindList->InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Remove all instances of the specified key from bindings
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::RemoveKeyFromBindItems( KeyValues *org_item, const char *key )
{
Assert( key && key[ 0 ] );
if ( !key || !key[ 0 ] )
return;
int len = Q_strlen( key );
char *pszKey = new char[len + 1];
if ( !pszKey )
return;
Q_memcpy( pszKey, key, len+1 );
for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
{
KeyValues *item = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
if ( !item )
continue;
// If it's bound to the primary: then remove it
if ( !stricmp( pszKey, item->GetString( "Key", "" ) ) )
{
bool bClearEntry = true;
if ( org_item )
{
// Only clear it out if the actual binding isn't the same. This allows
// us to have the same key bound to multiple entries in the keybinding list
// if they point to the same command.
const char *org_binding = org_item->GetString( "Binding", "" );
const char *binding = item->GetString( "Binding", "" );
if ( !stricmp( org_binding, binding ) )
{
bClearEntry = false;
}
}
if ( bClearEntry )
{
item->SetString( "Key", "" );
m_pKeyBindList->InvalidateItem(i);
}
}
}
delete [] pszKey;
// Make sure the display is up to date
m_pKeyBindList->InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Ask the engine for all bindings and set up the list
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::FillInCurrentBindings( void )
{
// reset the unbind list
// we only unbind keys used by the normal config items (not custom binds)
m_KeysToUnbind.RemoveAll();
// Clear any current settings
ClearBindItems();
bool bJoystick = false;
CGameUIConVarRef var( "joystick" );
if ( var.IsValid() )
{
bJoystick = var.GetBool();
}
for ( int i = 0; i < BUTTON_CODE_LAST; i++ )
{
ButtonCode_t bc = ( ButtonCode_t )i;
bool bIsJoystickCode = IsJoystickCode( bc );
// Skip Joystick buttons for the "other" user
if ( bIsJoystickCode && GetJoystickForCode( bc ) != m_nSplitScreenUser )
continue;
// Look up binding
const char *binding = gameuifuncs->GetBindingForButtonCode( bc );
if ( !binding )
continue;
// See if there is an item for this one?
KeyValues *item = GetItemForBinding( binding );
if ( item )
{
// Bind it by name
const char *keyName = g_pInputSystem->ButtonCodeToString( bc );
// Already in list, means user had two keys bound to this item. We'll only note the first one we encounter
char const *currentKey = item->GetString( "Key", "" );
if ( currentKey && currentKey[ 0 ] )
{
ButtonCode_t currentBC = (ButtonCode_t)gameuifuncs->GetButtonCodeForBind( currentKey );
// If we're using a joystick, joystick bindings override keyboard ones
bool bShouldOverride = bJoystick && bIsJoystickCode && !IsJoystickCode(currentBC);
if ( !bShouldOverride )
continue;
// Remove the key we're about to override from the unbinding list
m_KeysToUnbind.FindAndRemove( currentBC );
}
AddBinding( item, keyName );
// remember to apply unbinding of this key when we apply
m_KeysToUnbind.AddToTail( bc );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Clean up memory used by saved bindings
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::DeleteSavedBindings( void )
{
for ( int i = 0; i < BUTTON_CODE_LAST; i++ )
{
if ( m_Bindings[ i ].binding )
{
delete[] m_Bindings[ i ].binding;
m_Bindings[ i ].binding = NULL;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Copy all bindings into save array
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::SaveCurrentBindings( void )
{
DeleteSavedBindings();
for (int i = 0; i < BUTTON_CODE_LAST; i++)
{
const char *binding = gameuifuncs->GetBindingForButtonCode( (ButtonCode_t)i );
if ( !binding || !binding[0])
continue;
// Copy the binding string
m_Bindings[ i ].binding = UTIL_CopyString( binding );
}
}
//-----------------------------------------------------------------------------
// Purpose: Tells the engine to bind a key
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::BindKey( ButtonCode_t bc, const char *binding )
{
char const *pszKeyName = g_pInputSystem->ButtonCodeToString( bc );
Assert( pszKeyName );
if ( !pszKeyName || !*pszKeyName )
return;
int nSlot = GetJoystickForCode( bc );
engine->ClientCmd_Unrestricted( UTIL_va( "cmd%d bind \"%s\" \"%s\"\n", nSlot + 1, pszKeyName, binding ) );
}
//-----------------------------------------------------------------------------
// Purpose: Tells the engine to unbind a key
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::UnbindKey( ButtonCode_t bc )
{
char const *pszKeyName = g_pInputSystem->ButtonCodeToString( bc );
Assert( pszKeyName );
if ( !pszKeyName || !*pszKeyName )
return;
int nSlot = GetJoystickForCode( bc );
engine->ClientCmd_Unrestricted( UTIL_va( "cmd%d unbind \"%s\"\n", nSlot + 1, pszKeyName ) );
}
//-----------------------------------------------------------------------------
// Purpose: Go through list and bind specified keys to actions
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::ApplyAllBindings( void )
{
// unbind everything that the user unbound
for (int i = 0; i < m_KeysToUnbind.Count(); i++)
{
ButtonCode_t bc = m_KeysToUnbind[ i ];
UnbindKey( bc );
}
m_KeysToUnbind.RemoveAll();
// free binding memory
DeleteSavedBindings();
for (int i = 0; i < m_pKeyBindList->GetItemCount(); i++)
{
KeyValues *item = m_pKeyBindList->GetItemData(m_pKeyBindList->GetItemIDFromRow(i));
if ( !item )
continue;
// See if it has a binding
const char *binding = item->GetString( "Binding", "" );
if ( !binding || !binding[ 0 ] )
continue;
const char *keyname;
// Check main binding
keyname = item->GetString( "Key", "" );
if ( keyname && keyname[ 0 ] )
{
ButtonCode_t code = g_pInputSystem->StringToButtonCode( keyname );
if ( IsJoystickCode( code ) )
{
code = ButtonCodeToJoystickButtonCode( code, m_nSplitScreenUser );
}
// Tell the engine
BindKey( code, binding );
if ( code != BUTTON_CODE_INVALID )
{
m_Bindings[ code ].binding = UTIL_CopyString( binding );
}
}
}
// Now exec their custom bindings
engine->ClientCmd_Unrestricted( "exec userconfig.cfg\nhost_writeconfig\n" );
}
//-----------------------------------------------------------------------------
// Purpose: Read in defaults from game's default config file and populate list
// using those defaults
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::FillInDefaultBindings( void )
{
FileHandle_t fh = g_pFullFileSystem->Open( "cfg/config_default.cfg", "rb" );
if (fh == FILESYSTEM_INVALID_HANDLE)
return;
// L4D: also unbind other keys
engine->ClientCmd_Unrestricted( "unbindall\n" );
int size = g_pFullFileSystem->Size(fh);
CUtlBuffer buf( 0, size, CUtlBuffer::TEXT_BUFFER );
g_pFullFileSystem->Read( buf.Base(), size, fh );
g_pFullFileSystem->Close(fh);
// Clear out all current bindings
ClearBindItems();
const char *data = (const char*)buf.Base();
// loop through all the binding
while ( data != NULL )
{
char cmd[64];
data = UTIL_Parse( data, cmd, sizeof(cmd) );
if ( cmd[ 0 ] == '\0' )
break;
if ( !Q_stricmp(cmd, "bind") ||
!Q_stricmp(cmd, "cmd2 bind") )
{
// FIXME: If we ever support > 2 player splitscreen this will need to be reworked.
int nJoyStick = 0;
if ( !stricmp(cmd, "cmd2 bind") )
{
nJoyStick = 1;
}
// Key name
char szKeyName[256];
data = UTIL_Parse( data, szKeyName, sizeof(szKeyName) );
if ( szKeyName[ 0 ] == '\0' )
break; // Error
char szBinding[256];
data = UTIL_Parse( data, szBinding, sizeof(szBinding) );
if ( szKeyName[ 0 ] == '\0' )
break; // Error
// Skip it if it's a bind for the other slit
if ( nJoyStick != m_nSplitScreenUser )
continue;
// Find item
KeyValues *item = GetItemForBinding( szBinding );
if ( item )
{
// Bind it
AddBinding( item, szKeyName );
}
}
else
{
// L4D: Use Defaults also resets cvars listed in config_default.cfg
CGameUIConVarRef var( cmd );
if ( var.IsValid() )
{
char szValue[256] = "";
data = UTIL_Parse( data, szValue, sizeof(szValue) );
var.SetValue( szValue );
}
}
}
PostActionSignal(new KeyValues("ApplyButtonEnable"));
// Make sure console and escape key are always valid
KeyValues *item = GetItemForBinding( "toggleconsole" );
if ( item )
{
// Bind it
AddBinding( item, "`" );
}
item = GetItemForBinding( "cancelselect" );
if ( item )
{
// Bind it
AddBinding( item, "ESCAPE" );
}
}
//-----------------------------------------------------------------------------
// Purpose: User clicked on item: remember where last active row/column was
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::ItemSelected(int itemID)
{
m_pKeyBindList->SetItemOfInterest(itemID);
if (m_pKeyBindList->IsItemIDValid(itemID))
{
// find the details, see if we should be enabled/clear/whatever
m_pSetBindingButton->SetEnabled(true);
KeyValues *kv = m_pKeyBindList->GetItemData(itemID);
if (kv)
{
const char *key = kv->GetString("Key", NULL);
if (key && *key)
{
m_pClearBindingButton->SetEnabled(true);
}
else
{
m_pClearBindingButton->SetEnabled(false);
}
if (kv->GetInt("Header"))
{
m_pSetBindingButton->SetEnabled(false);
}
}
}
else
{
m_pSetBindingButton->SetEnabled(false);
m_pClearBindingButton->SetEnabled(false);
}
}
//-----------------------------------------------------------------------------
// Purpose: called when the capture has finished
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::Finish( ButtonCode_t code )
{
int r = m_pKeyBindList->GetItemOfInterest();
// Retrieve clicked row and column
m_pKeyBindList->EndCaptureMode( dc_arrow );
// Find item for this row
KeyValues *item = m_pKeyBindList->GetItemData(r);
if ( item )
{
// Handle keys: but never rebind the escape key
// Esc just exits bind mode silently
if ( code != BUTTON_CODE_NONE && code != KEY_ESCAPE && code != BUTTON_CODE_INVALID )
{
// Bind the named key
AddBinding( item, g_pInputSystem->ButtonCodeToString( code ) );
PostActionSignal( new KeyValues( "ApplyButtonEnable" ) );
}
m_pKeyBindList->InvalidateItem(r);
}
m_pSetBindingButton->SetEnabled(true);
m_pClearBindingButton->SetEnabled(true);
}
//-----------------------------------------------------------------------------
// Purpose: Scans for captured key presses
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::OnThink()
{
BaseClass::OnThink();
if ( m_pKeyBindList->IsCapturing() )
{
ButtonCode_t code = BUTTON_CODE_INVALID;
if ( engine->CheckDoneKeyTrapping( code ) )
{
Finish( code );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Check for enter key and go into keybinding mode if it was pressed
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::OnKeyCodePressed(vgui::KeyCode code)
{
// Enter key pressed and not already trapping next key/button press
if ( !m_pKeyBindList->IsCapturing() )
{
// Grab which item was set as interesting
int r = m_pKeyBindList->GetItemOfInterest();
// Check that it's visible
int x, y, w, h;
bool visible = m_pKeyBindList->GetCellBounds(r, 1, x, y, w, h);
if (visible)
{
if ( KEY_DELETE == code )
{
// find the current binding and remove it
KeyValues *kv = m_pKeyBindList->GetItemData(r);
const char *key = kv->GetString("Key", NULL);
if (key && *key)
{
RemoveKeyFromBindItems(NULL, key);
}
m_pClearBindingButton->SetEnabled(false);
m_pKeyBindList->InvalidateItem(r);
PostActionSignal(new KeyValues("ApplyButtonEnable"));
// message handled, don't pass on
return;
}
}
}
// Allow base class to process message instead
BaseClass::OnKeyCodePressed( code );
}
//-----------------------------------------------------------------------------
// Purpose: advanced keyboard settings dialog
//-----------------------------------------------------------------------------
class COptionsSubKeyboardAdvancedDlg : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( COptionsSubKeyboardAdvancedDlg, vgui::Frame );
public:
COptionsSubKeyboardAdvancedDlg( vgui::VPANEL hParent ) : BaseClass( NULL, NULL )
{
// parent is ignored, since we want look like we're steal focus from the parent (we'll become modal below)
SetTitle("#GameUI_KeyboardAdvanced_Title", true);
SetSize( 280, 140 );
LoadControlSettings( "resource/OptionsSubKeyboardAdvancedDlg.res" );
MoveToCenterOfScreen();
SetSizeable( false );
SetDeleteSelfOnClose( true );
}
virtual void Activate()
{
BaseClass::Activate();
input()->SetAppModalSurface(GetVPanel());
// reset the data
CGameUIConVarRef con_enable( "con_enable" );
if ( con_enable.IsValid() )
{
SetControlInt("ConsoleCheck", con_enable.GetInt() ? 1 : 0);
}
CGameUIConVarRef hud_fastswitch( "hud_fastswitch", true );
if ( hud_fastswitch.IsValid() )
{
SetControlInt("FastSwitchCheck", hud_fastswitch.GetInt() ? 1 : 0);
}
}
virtual void OnApplyData()
{
// apply data
CGameUIConVarRef con_enable( "con_enable" );
con_enable.SetValue( GetControlInt( "ConsoleCheck", 0 ) );
CGameUIConVarRef hud_fastswitch( "hud_fastswitch", true );
hud_fastswitch.SetValue( GetControlInt( "FastSwitchCheck", 0 ) );
}
virtual void OnCommand( const char *command )
{
if ( !stricmp(command, "OK") )
{
// apply the data
OnApplyData();
Close();
}
else
{
BaseClass::OnCommand( command );
}
}
void OnKeyCodeTyped(KeyCode code)
{
// force ourselves to be closed if the escape key it pressed
if (code == KEY_ESCAPE)
{
Close();
}
else
{
BaseClass::OnKeyCodeTyped(code);
}
}
};
//-----------------------------------------------------------------------------
// Purpose: Open advanced keyboard options
//-----------------------------------------------------------------------------
void COptionsSubKeyboard::OpenKeyboardAdvancedDialog()
{
if (!m_OptionsSubKeyboardAdvancedDlg.Get())
{
m_OptionsSubKeyboardAdvancedDlg = new COptionsSubKeyboardAdvancedDlg(GetVParent());
}
m_OptionsSubKeyboardAdvancedDlg->Activate();
}

View File

@@ -0,0 +1,103 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef OPTIONS_SUB_KEYBOARD_H
#define OPTIONS_SUB_KEYBOARD_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/UtlVector.h"
#include "tier1/UtlSymbol.h"
#include "vgui_controls/PropertyPage.h"
class VControlsListPanel;
//-----------------------------------------------------------------------------
// Purpose: Keyboard Details, Part of OptionsDialog
//-----------------------------------------------------------------------------
class COptionsSubKeyboard : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( COptionsSubKeyboard, vgui::PropertyPage );
public:
COptionsSubKeyboard(vgui::Panel *parent);
~COptionsSubKeyboard();
virtual void OnResetData();
virtual void OnApplyChanges();
virtual void OnKeyCodePressed( vgui::KeyCode code );
virtual void OnThink();
// Trap row selection message
MESSAGE_FUNC_INT( ItemSelected, "ItemSelected", itemID );
private:
void Finish( ButtonCode_t code );
//-----------------------------------------------------------------------------
// Purpose: Used for saving engine keybindings in case user hits cancel button
//-----------------------------------------------------------------------------
struct KeyBinding
{
char *binding;
};
// Create the key binding list control
void CreateKeyBindingList( void );
virtual void OnCommand( const char *command );
// Tell engine to bind/unbind a key
void BindKey( ButtonCode_t bc, const char *binding );
void UnbindKey( ButtonCode_t bc );
// Save/restore/cleanup engine's current bindings ( for handling cancel button )
void SaveCurrentBindings( void );
void DeleteSavedBindings( void );
// Get column 0 action descriptions for all keys
void ParseActionDescriptions( void );
// Populate list of actions with current engine keybindings
void FillInCurrentBindings( void );
// Remove all current bindings from list of bindings
void ClearBindItems( void );
// Fill in bindings with mod-specified defaults
void FillInDefaultBindings( void );
// Copy bindings out of list and set them in the engine
void ApplyAllBindings( void );
// Bind a key to the item
void AddBinding( KeyValues *item, const char *keyname );
// Remove all instances of a key from all bindings
void RemoveKeyFromBindItems( KeyValues *org_item, const char *key );
// Find item by binding name
KeyValues *GetItemForBinding( const char *binding );
private:
void OpenKeyboardAdvancedDialog();
vgui::DHANDLE<class COptionsSubKeyboardAdvancedDlg> m_OptionsSubKeyboardAdvancedDlg;
virtual void OnKeyCodeTyped(vgui::KeyCode code);
VControlsListPanel *m_pKeyBindList;
vgui::Button *m_pSetBindingButton;
vgui::Button *m_pClearBindingButton;
// List of saved bindings for the keys
KeyBinding m_Bindings[ BUTTON_CODE_LAST ];
// List of all the keys that need to have their binding removed
CUtlVector<ButtonCode_t> m_KeysToUnbind;
int m_nSplitScreenUser;
};
#endif // OPTIONS_SUB_KEYBOARD_H

View File

@@ -0,0 +1,206 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "OptionsSubMouse.h"
//#include "CommandCheckButton.h"
#include "KeyToggleCheckButton.h"
#include "CvarNegateCheckButton.h"
#include "CvarToggleCheckButton.h"
#include "CvarSlider.h"
#include "EngineInterface.h"
#include <KeyValues.h>
#include <vgui/IScheme.h>
#include "tier1/convar.h"
#include <stdio.h>
#include <vgui_controls/TextEntry.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
COptionsSubMouse::COptionsSubMouse(vgui::Panel *parent) : PropertyPage(parent, NULL)
{
m_pReverseMouseCheckBox = new CCvarNegateCheckButton(
this,
"ReverseMouse",
"#GameUI_ReverseMouse",
"m_pitch" );
m_pMouseFilterCheckBox = new CCvarToggleCheckButton(
this,
"MouseFilter",
"#GameUI_MouseFilter",
"m_filter" );
m_pJoystickCheckBox = new CCvarToggleCheckButton(
this,
"Joystick",
"#GameUI_Joystick",
"joystick" );
m_pJoystickSouthpawCheckBox = new CCvarToggleCheckButton(
this,
"JoystickSouthpaw",
"#GameUI_JoystickSouthpaw",
"joy_movement_stick" );
m_pReverseJoystickCheckBox = new CCvarToggleCheckButton(
this,
"ReverseJoystick",
"#GameUI_ReverseJoystick",
"joy_inverty" );
m_pQuickInfoCheckBox = new CCvarToggleCheckButton(
this,
"HudQuickInfo",
"#GameUI_HudQuickInfo",
"hud_quickinfo" );
m_pMouseSensitivitySlider = new CCvarSlider( this, "Slider", "#GameUI_MouseSensitivity",
1.0f, 20.0f, "sensitivity", true );
m_pMouseSensitivityLabel = new TextEntry(this, "SensitivityLabel");
m_pMouseSensitivityLabel->AddActionSignalTarget(this);
m_pJoyYawSensitivitySlider = new CCvarSlider( this, "JoystickYawSlider", "#GameUI_JoystickYawSensitivity",
-0.5f, -7.0f, "joy_yawsensitivity", true );
m_pJoyYawSensitivityPreLabel = new Label(this, "JoystickYawSensitivityPreLabel", "#GameUI_JoystickLookSpeedYaw" );
m_pJoyPitchSensitivitySlider = new CCvarSlider( this, "JoystickPitchSlider", "#GameUI_JoystickPitchSensitivity",
0.5f, 7.0f, "joy_pitchsensitivity", true );
m_pJoyPitchSensitivityPreLabel = new Label(this, "JoystickPitchSensitivityPreLabel", "#GameUI_JoystickLookSpeedPitch" );
LoadControlSettings("Resource\\OptionsSubMouse.res");
//float sensitivity = engine->pfnGetCvarFloat( "sensitivity" );
ConVarRef var( "sensitivity" );
if ( var.IsValid() )
{
float sensitivity = var.GetFloat();
char buf[64];
Q_snprintf(buf, sizeof(buf), " %.1f", sensitivity);
m_pMouseSensitivityLabel->SetText(buf);
}
UpdateJoystickPanels();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COptionsSubMouse::~COptionsSubMouse()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubMouse::OnResetData()
{
m_pReverseMouseCheckBox->Reset();
m_pMouseFilterCheckBox->Reset();
m_pJoystickCheckBox->Reset();
m_pJoystickSouthpawCheckBox->Reset();
m_pMouseSensitivitySlider->Reset();
m_pQuickInfoCheckBox->Reset();
m_pReverseJoystickCheckBox->Reset();
m_pJoyYawSensitivitySlider->Reset();
m_pJoyPitchSensitivitySlider->Reset();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubMouse::OnApplyChanges()
{
m_pReverseMouseCheckBox->ApplyChanges();
m_pMouseFilterCheckBox->ApplyChanges();
m_pJoystickCheckBox->ApplyChanges();
m_pJoystickSouthpawCheckBox->ApplyChanges();
m_pMouseSensitivitySlider->ApplyChanges();
m_pQuickInfoCheckBox->ApplyChanges();
m_pReverseJoystickCheckBox->ApplyChanges();
m_pJoyYawSensitivitySlider->ApplyChanges();
m_pJoyPitchSensitivitySlider->ApplyChanges();
engine->ClientCmd_Unrestricted( "joyadvancedupdate" );
}
//-----------------------------------------------------------------------------
// Purpose: sets background color & border
//-----------------------------------------------------------------------------
void COptionsSubMouse::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubMouse::OnControlModified(Panel *panel)
{
PostActionSignal(new KeyValues("ApplyButtonEnable"));
// the HasBeenModified() check is so that if the value is outside of the range of the
// slider, it won't use the slider to determine the display value but leave the
// real value that we determined in the constructor
if (panel == m_pMouseSensitivitySlider && m_pMouseSensitivitySlider->HasBeenModified())
{
UpdateSensitivityLabel();
}
else if (panel == m_pJoystickCheckBox)
{
UpdateJoystickPanels();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubMouse::OnTextChanged(Panel *panel)
{
if (panel == m_pMouseSensitivityLabel)
{
char buf[64];
m_pMouseSensitivityLabel->GetText(buf, 64);
float fValue = (float) atof(buf);
if (fValue >= 1.0)
{
m_pMouseSensitivitySlider->SetSliderValue(fValue);
PostActionSignal(new KeyValues("ApplyButtonEnable"));
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubMouse::UpdateSensitivityLabel()
{
char buf[64];
Q_snprintf(buf, sizeof( buf ), " %.1f", m_pMouseSensitivitySlider->GetSliderValue());
m_pMouseSensitivityLabel->SetText(buf);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubMouse::UpdateJoystickPanels()
{
bool bEnabled = m_pJoystickCheckBox->IsSelected();
m_pReverseJoystickCheckBox->SetEnabled( bEnabled );
m_pJoystickSouthpawCheckBox->SetEnabled( bEnabled );
m_pJoyYawSensitivitySlider->SetEnabled( bEnabled );
m_pJoyYawSensitivityPreLabel->SetEnabled( bEnabled );
m_pJoyPitchSensitivitySlider->SetEnabled( bEnabled );
m_pJoyPitchSensitivityPreLabel->SetEnabled( bEnabled );
}

View File

@@ -0,0 +1,73 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef OPTIONS_SUB_MOUSE_H
#define OPTIONS_SUB_MOUSE_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/PropertyPage.h>
class CCvarNegateCheckButton;
class CKeyToggleCheckButton;
class CCvarToggleCheckButton;
class CCvarSlider;
namespace vgui
{
class Label;
class Panel;
}
//-----------------------------------------------------------------------------
// Purpose: Mouse Details, Part of OptionsDialog
//-----------------------------------------------------------------------------
class COptionsSubMouse : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( COptionsSubMouse, vgui::PropertyPage );
public:
COptionsSubMouse(vgui::Panel *parent);
~COptionsSubMouse();
virtual void OnResetData();
virtual void OnApplyChanges();
protected:
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
private:
MESSAGE_FUNC_PTR( OnControlModified, "ControlModified", panel );
MESSAGE_FUNC_PTR( OnTextChanged, "TextChanged", panel );
MESSAGE_FUNC_PTR( OnCheckButtonChecked, "CheckButtonChecked", panel )
{
OnControlModified( panel );
}
void UpdateSensitivityLabel();
void UpdateJoystickPanels();
CCvarNegateCheckButton *m_pReverseMouseCheckBox;
CCvarToggleCheckButton *m_pMouseFilterCheckBox;
CCvarToggleCheckButton *m_pJoystickCheckBox;
CCvarToggleCheckButton *m_pJoystickSouthpawCheckBox;
CCvarToggleCheckButton *m_pQuickInfoCheckBox;
CCvarToggleCheckButton *m_pReverseJoystickCheckBox;
CCvarSlider *m_pMouseSensitivitySlider;
vgui::TextEntry *m_pMouseSensitivityLabel;
CCvarSlider *m_pJoyYawSensitivitySlider;
vgui::Label *m_pJoyYawSensitivityPreLabel;
CCvarSlider *m_pJoyPitchSensitivitySlider;
vgui::Label *m_pJoyPitchSensitivityPreLabel;
};
#endif // OPTIONS_SUB_MOUSE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef OPTIONSSUBMULTIPLAYER_H
#define OPTIONSSUBMULTIPLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/PropertyPage.h>
class CLabeledCommandComboBox;
class CBitmapImagePanel;
class CCvarToggleCheckButton;
class CCvarTextEntry;
class CCvarSlider;
class CrosshairImagePanel;
class CMultiplayerAdvancedDialog;
class AdvancedCrosshairImagePanel;
enum ConversionErrorType
{
CE_SUCCESS,
CE_MEMORY_ERROR,
CE_CANT_OPEN_SOURCE_FILE,
CE_ERROR_PARSING_SOURCE,
CE_SOURCE_FILE_FORMAT_NOT_SUPPORTED,
CE_ERROR_WRITING_OUTPUT_FILE,
CE_ERROR_LOADING_DLL
};
struct TGAHeader {
byte identsize; // size of ID field that follows 18 byte header (0 usually)
byte colourmaptype; // type of colour map 0=none, 1=has palette
byte imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
short colourmapstart; // first colour map entry in palette
short colourmaplength; // number of colours in palette
byte colourmapbits; // number of bits per palette entry 15,16,24,32
short xstart; // image x origin
short ystart; // image y origin
short width; // image width in pixels
short height; // image height in pixels
byte bits; // image bits per pixel 8,16,24,32
byte descriptor; // image descriptor bits (vh flip bits)
};
//-----------------------------------------------------------------------------
// Purpose: multiplayer options property page
//-----------------------------------------------------------------------------
class COptionsSubMultiplayer : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( COptionsSubMultiplayer, vgui::PropertyPage );
public:
COptionsSubMultiplayer(vgui::Panel *parent);
~COptionsSubMultiplayer();
virtual vgui::Panel *CreateControlByName(const char *controlName);
protected:
// Called when page is loaded. Data should be reloaded from document into controls.
virtual void OnResetData();
// Called when the OK / Apply button is pressed. Changed data should be written into document.
virtual void OnApplyChanges();
virtual void OnCommand( const char *command );
private:
void InitModelList(CLabeledCommandComboBox *cb);
void InitLogoList(CLabeledCommandComboBox *cb);
void RemapModel();
void RemapLogo();
MESSAGE_FUNC_PTR( OnTextChanged, "TextChanged", panel );
MESSAGE_FUNC_PARAMS( OnSliderMoved, "SliderMoved", data );
MESSAGE_FUNC( OnApplyButtonEnable, "ControlModified" );
MESSAGE_FUNC_CHARPTR( OnFileSelected, "FileSelected", fullpath );
void RemapPalette(char *filename, int topcolor, int bottomcolor);
void ColorForName(char const *pszColorName, int &r, int &g, int &b);
CBitmapImagePanel *m_pModelImage;
CLabeledCommandComboBox *m_pModelList;
char m_ModelName[128];
vgui::ImagePanel *m_pLogoImage;
CLabeledCommandComboBox *m_pLogoList;
char m_LogoName[128];
CCvarSlider *m_pPrimaryColorSlider;
CCvarSlider *m_pSecondaryColorSlider;
CCvarToggleCheckButton *m_pHighQualityModelCheckBox;
// Mod specific general checkboxes
vgui::Dar< CCvarToggleCheckButton * > m_cvarToggleCheckButtons;
// --- crosshair controls ----------------------------------
CLabeledCommandComboBox *m_pCrosshairSize;
void InitCrosshairSizeList(CLabeledCommandComboBox *cb);
CCvarToggleCheckButton *m_pCrosshairTranslucencyCheckbox;
vgui::ComboBox *m_pCrosshairColorComboBox;
void InitCrosshairColorEntries();
void ApplyCrosshairColorChanges();
CrosshairImagePanel *m_pCrosshairImage;
// called when the appearance of the crosshair has changed.
void RedrawCrosshairImage();
// ---------------------------------------------------------
// --- advanced crosshair controls
AdvancedCrosshairImagePanel *m_pAdvCrosshairImage;
CCvarSlider *m_pAdvCrosshairRedSlider;
CCvarSlider *m_pAdvCrosshairBlueSlider;
CCvarSlider *m_pAdvCrosshairGreenSlider;
CCvarSlider *m_pAdvCrosshairScaleSlider;
CLabeledCommandComboBox *m_pAdvCrosshairStyle;
void InitAdvCrosshairStyleList(CLabeledCommandComboBox *cb);
void RedrawAdvCrosshairImage();
// -----
// --- client download filter
vgui::ComboBox *m_pDownloadFilterCombo;
// Begin Spray Import Functions
ConversionErrorType ConvertJPEGToTGA(const char *jpgPath, const char *tgaPath);
ConversionErrorType ConvertBMPToTGA(const char *bmpPath, const char *tgaPath);
ConversionErrorType ConvertTGA(const char *tgaPath);
unsigned char *ReadTGAAsRGBA(const char *tgaPath, int &width, int &height, ConversionErrorType &errcode, TGAHeader &tgaHeader);
ConversionErrorType StretchRGBAImage(const unsigned char *srcBuf, const int srcWidth, const int srcHeight, unsigned char *destBuf, const int destWidth, const int destHeight);
ConversionErrorType PadRGBAImage(const unsigned char *srcBuf, const int srcWidth, const int srcHeight, unsigned char *destBuf, const int destWidth, const int destHeight);
ConversionErrorType ConvertTGAToVTF(const char *tgaPath);
ConversionErrorType WriteSprayVMT(const char *vtfPath);
void SelectLogo(const char *logoName);
// End Spray Import Functions
int m_nTopColor;
int m_nBottomColor;
int m_nLogoR;
int m_nLogoG;
int m_nLogoB;
vgui::DHANDLE<CMultiplayerAdvancedDialog> m_hMultiplayerAdvancedDialog;
vgui::FileOpenDialog *m_hImportSprayDialog;
};
#endif // OPTIONSSUBMULTIPLAYER_H

View File

@@ -0,0 +1,98 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "OptionsSubPortal.h"
#include "CvarToggleCheckButton.h"
#include "vgui_controls/ComboBox.h"
#include "EngineInterface.h"
#include <KeyValues.h>
#include <vgui/IScheme.h>
#include "tier1/convar.h"
#include <stdio.h>
#include <vgui_controls/TextEntry.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
COptionsSubPortal::COptionsSubPortal(vgui::Panel *parent) : PropertyPage(parent, NULL)
{
m_pPortalFunnelCheckBox = new CCvarToggleCheckButton(
this,
"PortalFunnel",
"#GameUI_PortalFunnel",
"sv_player_funnel_into_portals" );
m_pPortalDepthCombo = new ComboBox( this, "PortalDepth", 6, false );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth0", new KeyValues("PortalDepth", "depth", 0) );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth1", new KeyValues("PortalDepth", "depth", 1) );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth2", new KeyValues("PortalDepth", "depth", 2) );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth3", new KeyValues("PortalDepth", "depth", 3) );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth4", new KeyValues("PortalDepth", "depth", 4) );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth5", new KeyValues("PortalDepth", "depth", 5) );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth6", new KeyValues("PortalDepth", "depth", 6) );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth7", new KeyValues("PortalDepth", "depth", 7) );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth8", new KeyValues("PortalDepth", "depth", 8) );
m_pPortalDepthCombo->AddItem( "#GameUI_PortalDepth9", new KeyValues("PortalDepth", "depth", 9) );
LoadControlSettings("Resource\\OptionsSubPortal.res");
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COptionsSubPortal::~COptionsSubPortal()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubPortal::OnResetData()
{
m_pPortalFunnelCheckBox->Reset();
// Portal render depth
ConVarRef r_portal_stencil_depth("r_portal_stencil_depth");
if ( r_portal_stencil_depth.IsValid() )
{
m_pPortalDepthCombo->ActivateItem(r_portal_stencil_depth.GetInt());
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubPortal::OnApplyChanges()
{
m_pPortalFunnelCheckBox->ApplyChanges();
// Portal render depth
if ( m_pPortalDepthCombo->IsEnabled() )
{
ConVarRef r_portal_stencil_depth( "r_portal_stencil_depth" );
r_portal_stencil_depth.SetValue( m_pPortalDepthCombo->GetActiveItem() );
}
}
//-----------------------------------------------------------------------------
// Purpose: sets background color & border
//-----------------------------------------------------------------------------
void COptionsSubPortal::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubPortal::OnControlModified()
{
PostActionSignal(new KeyValues("ApplyButtonEnable"));
}

View File

@@ -0,0 +1,59 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef OPTIONS_SUB_PORTAL_H
#define OPTIONS_SUB_PORTAL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/PropertyPage.h>
class CLabeledCommandComboBox;
class CCvarToggleCheckButton;
namespace vgui
{
class Label;
class Panel;
}
//-----------------------------------------------------------------------------
// Purpose: Mouse Details, Part of OptionsDialog
//-----------------------------------------------------------------------------
class COptionsSubPortal : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( COptionsSubPortal, vgui::PropertyPage );
public:
COptionsSubPortal(vgui::Panel *parent);
~COptionsSubPortal();
virtual void OnResetData();
virtual void OnApplyChanges();
protected:
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
private:
MESSAGE_FUNC( OnCheckButtonChecked, "CheckButtonChecked" )
{
OnControlModified();
}
MESSAGE_FUNC( OnControlModified, "ControlModified" );
MESSAGE_FUNC( OnTextChanged, "TextChanged" )
{
OnControlModified();
}
CCvarToggleCheckButton *m_pPortalFunnelCheckBox;
vgui::ComboBox *m_pPortalDepthCombo;
};
#endif // OPTIONS_SUB_MOUSE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,86 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef OPTIONS_SUB_VIDEO_H
#define OPTIONS_SUB_VIDEO_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Panel.h>
#include <vgui_controls/ComboBox.h>
#include <vgui_controls/PropertyPage.h>
#include "EngineInterface.h"
#include "igameuifuncs.h"
#include "URLButton.h"
#include "vgui_controls/frame.h"
class CCvarSlider;
//-----------------------------------------------------------------------------
// Purpose: Video Details, Part of OptionsDialog
//-----------------------------------------------------------------------------
class COptionsSubVideo : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( COptionsSubVideo, vgui::PropertyPage );
public:
COptionsSubVideo(vgui::Panel *parent);
~COptionsSubVideo();
virtual void OnResetData();
virtual void OnApplyChanges();
virtual void PerformLayout();
virtual bool RequiresRestart();
MESSAGE_FUNC( OpenGammaDialog, "OpenGammaDialog" );
static vgui::DHANDLE<class CGammaDialog> m_hGammaDialog;
private:
void SetCurrentResolutionComboItem();
MESSAGE_FUNC( OnDataChanged, "ControlModified" );
MESSAGE_FUNC_PTR_CHARPTR( OnTextChanged, "TextChanged", panel, text );
MESSAGE_FUNC( OpenAdvanced, "OpenAdvanced" );
MESSAGE_FUNC( LaunchBenchmark, "LaunchBenchmark" );
void PrepareResolutionList();
int m_nSelectedMode; // -1 if we are running in a nonstandard mode
vgui::ComboBox *m_pMode;
vgui::ComboBox *m_pWindowed;
vgui::ComboBox *m_pAspectRatio;
vgui::Button *m_pGammaButton;
vgui::Button *m_pAdvanced;
vgui::Button *m_pBenchmark;
vgui::DHANDLE<class COptionsSubVideoAdvancedDlg> m_hOptionsSubVideoAdvancedDlg;
bool m_bRequireRestart;
MESSAGE_FUNC( OpenThirdPartyVideoCreditsDialog, "OpenThirdPartyVideoCreditsDialog" );
vgui::URLButton *m_pThirdPartyCredits;
vgui::DHANDLE<class COptionsSubVideoThirdPartyCreditsDlg> m_OptionsSubVideoThirdPartyCreditsDlg;
};
class COptionsSubVideoThirdPartyCreditsDlg : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( COptionsSubVideoThirdPartyCreditsDlg, vgui::Frame );
public:
COptionsSubVideoThirdPartyCreditsDlg( vgui::VPANEL hParent );
virtual void Activate();
void OnKeyCodeTyped(vgui::KeyCode code);
protected:
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
};
#endif // OPTIONS_SUB_VIDEO_H

View File

@@ -0,0 +1,371 @@
//========= Copyright <20> Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//==========================================================================//
#include "OptionsSubVoice.h"
#include "CvarSlider.h"
#include <vgui/IVGui.h>
#include <vgui_controls/ImagePanel.h>
#include <vgui_controls/CheckButton.h>
#include <vgui_controls/Slider.h>
#include "EngineInterface.h"
#include "ivoicetweak.h"
#include "CvarToggleCheckButton.h"
#include "tier1/KeyValues.h"
#include "tier1/convar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COptionsSubVoice::COptionsSubVoice(vgui::Panel *parent) : PropertyPage(parent, NULL)
{
#if !defined( NO_VOICE )
m_pVoiceTweak = engine->GetVoiceTweakAPI();
#endif
m_pMicMeter = new ImagePanel(this, "MicMeter");
m_pMicMeter2 = new ImagePanel(this, "MicMeter2");
m_pReceiveSliderLabel = new Label(this, "ReceiveLabel", "#GameUI_VoiceReceiveVolume");
m_pReceiveVolume = new CCvarSlider( this, "VoiceReceive", "#GameUI_ReceiveVolume", 0.0f, 1.0f, "voice_scale" );
m_pMicrophoneSliderLabel = new Label(this, "MicrophoneLabel", "#GameUI_VoiceTransmitVolume");
m_pMicrophoneVolume = new Slider( this, "#GameUI_MicrophoneVolume" );
m_pMicrophoneVolume->SetRange( 0, 100 );
m_pMicrophoneVolume->AddActionSignalTarget( this );
m_pVoiceEnableCheckButton = new CCvarToggleCheckButton( this, "voice_modenable", "#GameUI_EnableVoice", "voice_modenable" );
m_pMicBoost = new CheckButton(this, "MicBoost", "#GameUI_BoostMicrophone" );
m_pMicBoost->AddActionSignalTarget( this );
// Open mic controls
m_pThresholdSliderLabel = new Label(this, "ThresholdLabel", "#GameUI_VoiceThreshold");
m_pThresholdVolume = new CCvarSlider( this, "VoiceThreshold", "#GameUI_VoiceThreshold", 0, 16384, "voice_threshold" );
m_pOpenMicEnableCheckButton = new CCvarToggleCheckButton( this, "voice_vox", "#GameUI_EnableOpenMic", "voice_vox" );
m_pTestMicrophoneButton = new Button(this, "TestMicrophone", "#GameUI_TestMicrophone");
LoadControlSettings("Resource\\OptionsSubVoice.res");
m_bVoiceOn = false;
m_pMicMeter2->SetVisible(false);
// no voice tweak - then disable all buttons
if (!m_pVoiceTweak)
{
m_pReceiveVolume->SetEnabled(false);
m_pMicrophoneVolume->SetEnabled(false);
m_pVoiceEnableCheckButton->SetEnabled(false);
m_pMicBoost->SetEnabled(false);
m_pTestMicrophoneButton->SetEnabled(false);
m_pOpenMicEnableCheckButton->SetEnabled(false);
m_pThresholdVolume->SetEnabled(false);
}
else
{
OnResetData();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COptionsSubVoice::~COptionsSubVoice()
{
// turn off voice if it was on, since we're leaving this page
if (m_bVoiceOn)
{
EndTestMicrophone();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::OnResetData()
{
if (!m_pVoiceTweak)
return;
float micVolume = m_pVoiceTweak->GetControlFloat( MicrophoneVolume );
m_pMicrophoneVolume->SetValue( (int)( 100.0f * micVolume ) );
m_nMicVolumeValue = m_pMicrophoneVolume->GetValue();
float fMicBoost = m_pVoiceTweak->GetControlFloat( MicBoost );
m_pMicBoost->SetSelected( fMicBoost != 0.0f );
m_bMicBoostSelected = m_pMicBoost->IsSelected();
m_pReceiveVolume->Reset();
m_fReceiveVolume = m_pReceiveVolume->GetSliderValue();
m_pThresholdVolume->Reset();
m_nVoiceThresholdValue = m_pThresholdVolume->GetSliderValue();
m_pOpenMicEnableCheckButton->Reset();
m_bOpenMicSelected = m_pOpenMicEnableCheckButton->IsSelected();
m_pVoiceEnableCheckButton->Reset();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::OnSliderMoved( int position )
{
if ( m_pVoiceTweak )
{
if ( m_pMicrophoneVolume->GetValue() != m_nMicVolumeValue )
{
PostActionSignal(new KeyValues("ApplyButtonEnable"));
}
if ( m_pThresholdVolume->GetSliderValue() != m_nVoiceThresholdValue )
{
PostActionSignal(new KeyValues("ApplyButtonEnable"));
m_pThresholdVolume->ApplyChanges();
m_nVoiceThresholdValue = m_pThresholdVolume->GetSliderValue();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::OnCheckButtonChecked( int state )
{
if ( m_pVoiceTweak )
{
// if our state is different
if ( m_pMicBoost->IsSelected() != m_bMicBoostSelected)
{
PostActionSignal(new KeyValues("ApplyButtonEnable"));
}
if ( m_pOpenMicEnableCheckButton->IsSelected() != m_bOpenMicSelected )
{
PostActionSignal(new KeyValues("ApplyButtonEnable"));
m_pOpenMicEnableCheckButton->ApplyChanges();
m_bOpenMicSelected = m_pOpenMicEnableCheckButton->IsSelected();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::OnApplyChanges()
{
if (!m_pVoiceTweak)
return;
m_nMicVolumeValue = m_pMicrophoneVolume->GetValue();
float fMicVolume = (float) m_nMicVolumeValue / 100.0f;
m_pVoiceTweak->SetControlFloat( MicrophoneVolume, fMicVolume );
m_bMicBoostSelected = m_pMicBoost->IsSelected();
m_pVoiceTweak->SetControlFloat( MicBoost, m_bMicBoostSelected ? 1.0f : 0.0f );
m_pReceiveVolume->ApplyChanges();
m_fReceiveVolume = m_pReceiveVolume->GetSliderValue();
m_pThresholdVolume->ApplyChanges();
m_nVoiceThresholdValue = m_pThresholdVolume->GetSliderValue();
m_pOpenMicEnableCheckButton->ApplyChanges();
m_pVoiceEnableCheckButton->ApplyChanges();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::StartTestMicrophone()
{
if (!m_pVoiceTweak || m_bVoiceOn)
return;
m_bVoiceOn = true;
UseCurrentVoiceParameters();
if (m_pVoiceTweak->StartVoiceTweakMode())
{
m_pTestMicrophoneButton->SetText("#GameUI_StopTestMicrophone");
m_pReceiveVolume->SetEnabled(false);
m_pMicrophoneVolume->SetEnabled(false);
m_pVoiceEnableCheckButton->SetEnabled(false);
m_pMicBoost->SetEnabled(false);
m_pMicrophoneSliderLabel->SetEnabled(false);
m_pReceiveSliderLabel->SetEnabled(false);
m_pMicMeter2->SetVisible(true);
}
else
{
ResetVoiceParameters();
// we couldn't start it
m_bVoiceOn = false;
return;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::UseCurrentVoiceParameters()
{
int nVal = m_pMicrophoneVolume->GetValue();
float val = (float) nVal / 100.0f;
m_pVoiceTweak->SetControlFloat( MicrophoneVolume, val );
bool bSelected = m_pMicBoost->IsSelected();
val = bSelected ? 1.0f : 0.0f;
m_pVoiceTweak->SetControlFloat( MicBoost, val );
// get where the current slider is
m_nReceiveSliderValue = m_pReceiveVolume->GetValue();
m_pReceiveVolume->ApplyChanges();
m_nVoiceThresholdValue = m_pThresholdVolume->GetValue();
m_pThresholdVolume->ApplyChanges();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::ResetVoiceParameters()
{
float fMicVolume = (float) m_nMicVolumeValue / 100.0f;
m_pVoiceTweak->SetControlFloat( MicrophoneVolume, fMicVolume );
m_pVoiceTweak->SetControlFloat( MicBoost, m_bMicBoostSelected ? 1.0f : 0.0f );
// restore the old value
ConVarRef voice_scale( "voice_scale" );
voice_scale.SetValue( m_fReceiveVolume );
m_pReceiveVolume->Reset();
// set the slider to 'new' value, but we've reset the 'start' value where it was
m_pReceiveVolume->SetValue( m_nReceiveSliderValue );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::EndTestMicrophone()
{
if (!m_pVoiceTweak || !m_bVoiceOn)
return;
if ( m_pVoiceTweak->IsStillTweaking() )
{
m_pVoiceTweak->EndVoiceTweakMode();
}
ResetVoiceParameters();
m_pTestMicrophoneButton->SetText("#GameUI_TestMicrophone");
m_bVoiceOn = false;
m_pReceiveVolume->SetEnabled(true);
m_pMicrophoneVolume->SetEnabled(true);
m_pVoiceEnableCheckButton->SetEnabled(true);
m_pMicBoost->SetEnabled(true);
m_pMicrophoneSliderLabel->SetEnabled(true);
m_pReceiveSliderLabel->SetEnabled(true);
m_pMicMeter2->SetVisible(false);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::OnCommand( const char *command)
{
if (!stricmp(command, "TestMicrophone"))
{
if (!m_bVoiceOn)
{
StartTestMicrophone();
}
else
{
EndTestMicrophone();
}
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::OnPageHide()
{
// turn off voice if it was on, since we're leaving this page
if (m_bVoiceOn)
{
EndTestMicrophone();
}
BaseClass::OnPageHide();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::OnControlModified()
{
PostActionSignal(new KeyValues("ApplyButtonEnable"));
}
#define BAR_WIDTH 160
#define BAR_INCREMENT 8
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COptionsSubVoice::OnThink()
{
BaseClass::OnThink();
if ( m_bVoiceOn )
{
if ( m_pVoiceTweak->IsStillTweaking() == false )
{
DevMsg( 1, "Lost Voice Tweak channels, resetting\n" );
EndTestMicrophone();
}
else
{
float val = m_pVoiceTweak->GetControlFloat( SpeakingVolume );
int nValue = static_cast<int>( val*32768.0f + 0.5f );
// Throttle this if they're using "open mic" style communication
if ( m_pOpenMicEnableCheckButton->IsSelected() )
{
// Test against it our threshold value
float flThreshold = ( (float) m_pThresholdVolume->GetSliderValue() / 32768.0f );
if ( val < flThreshold )
{
nValue = 0; // Zero the display
}
}
int width = (BAR_WIDTH * nValue) / 32768;
width = ((width + (BAR_INCREMENT-1)) / BAR_INCREMENT) * BAR_INCREMENT; // round to nearest BAR_INCREMENT
int wide, tall;
m_pMicMeter2->GetSize(wide, tall);
m_pMicMeter2->SetSize(width, tall);
m_pMicMeter2->Repaint();
}
}
}

View File

@@ -0,0 +1,80 @@
//========= Copyright <20> Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//==========================================================================//
#ifndef OPTIONS_SUB_VOICE_H
#define OPTIONS_SUB_VOICE_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/PropertyPage.h>
typedef struct IVoiceTweak_s IVoiceTweak;
class CCvarSlider;
class CCvarToggleCheckButton;
//-----------------------------------------------------------------------------
// Purpose: Voice Details, Part of OptionsDialog
//-----------------------------------------------------------------------------
class COptionsSubVoice : public vgui::PropertyPage
{
DECLARE_CLASS_SIMPLE( COptionsSubVoice, vgui::PropertyPage );
public:
COptionsSubVoice(vgui::Panel *parent);
~COptionsSubVoice();
virtual void OnResetData();
virtual void OnApplyChanges();
protected:
virtual void OnThink(); // called every frame before painting, but only if panel is visible
private:
virtual void OnCommand( const char *command );
MESSAGE_FUNC( OnPageHide, "PageHide" );
MESSAGE_FUNC_INT( OnSliderMoved, "SliderMoved", position );
MESSAGE_FUNC_INT( OnCheckButtonChecked, "CheckButtonChecked", state );
MESSAGE_FUNC( OnControlModified, "ControlModified" );
void StartTestMicrophone();
void EndTestMicrophone();
void UseCurrentVoiceParameters();
void ResetVoiceParameters();
IVoiceTweak *m_pVoiceTweak; // Engine voice tweak API.
vgui::CheckButton *m_pMicBoost;
vgui::ImagePanel *m_pMicMeter;
vgui::ImagePanel *m_pMicMeter2;
vgui::Button *m_pTestMicrophoneButton;
vgui::Label *m_pMicrophoneSliderLabel;
vgui::Slider *m_pMicrophoneVolume;
vgui::Label *m_pReceiveSliderLabel;
CCvarSlider *m_pReceiveVolume;
// "Open mic" settings
vgui::Label *m_pThresholdSliderLabel;
CCvarSlider *m_pThresholdVolume;
CCvarToggleCheckButton *m_pOpenMicEnableCheckButton;
CCvarToggleCheckButton *m_pVoiceEnableCheckButton;
int m_nVoiceThresholdValue;
int m_nMicVolumeValue;
bool m_bMicBoostSelected;
bool m_bOpenMicSelected;
float m_fReceiveVolume;
int m_nReceiveSliderValue;
bool m_bVoiceOn;
};
#endif // OPTIONS_SUB_VOICE_H

View File

@@ -0,0 +1,306 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <assert.h>
#include <vgui_controls/ScrollBar.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include <KeyValues.h>
#include <vgui/MouseCode.h>
#include <vgui/KeyCode.h>
#include <vgui/IInput.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include "PanelListPanel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
class VScrollBarReversedButtons : public ScrollBar
{
public:
VScrollBarReversedButtons( Panel *parent, const char *panelName, bool vertical );
virtual void ApplySchemeSettings( IScheme *pScheme );
};
VScrollBarReversedButtons::VScrollBarReversedButtons( Panel *parent, const char *panelName, bool vertical ) : ScrollBar( parent, panelName, vertical )
{
}
void VScrollBarReversedButtons::ApplySchemeSettings( IScheme *pScheme )
{
ScrollBar::ApplySchemeSettings( pScheme );
Button *pButton;
pButton = GetButton( 0 );
pButton->SetArmedColor( pButton->GetSchemeColor("DimBaseText", pScheme), pButton->GetBgColor());
pButton->SetDepressedColor( pButton->GetSchemeColor("DimBaseText", pScheme), pButton->GetBgColor());
pButton->SetDefaultColor( pButton->GetFgColor(), pButton->GetBgColor());
pButton = GetButton( 1 );
pButton->SetArmedColor( pButton->GetSchemeColor("DimBaseText", pScheme), pButton->GetBgColor());
pButton->SetDepressedColor( pButton->GetSchemeColor("DimBaseText", pScheme), pButton->GetBgColor());
pButton->SetDefaultColor( pButton->GetFgColor(), pButton->GetBgColor());
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : x -
// y -
// wide -
// tall -
// Output :
//-----------------------------------------------------------------------------
CPanelListPanel::CPanelListPanel( vgui::Panel *parent, char const *panelName, bool inverseButtons ) : Panel( parent, panelName )
{
SetBounds( 0, 0, 100, 100 );
_sliderYOffset = 0;
if (inverseButtons)
{
_vbar = new VScrollBarReversedButtons(this, "CPanelListPanelVScroll", true );
}
else
{
_vbar = new ScrollBar(this, "CPanelListPanelVScroll", true );
}
_vbar->SetBounds( 0, 0, 20, 20 );
_vbar->SetVisible(false);
_vbar->AddActionSignalTarget( this );
_embedded = new Panel( this, "PanelListEmbedded" );
_embedded->SetBounds( 0, 0, 20, 20 );
_embedded->SetPaintBackgroundEnabled( false );
_embedded->SetPaintBorderEnabled( false );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CPanelListPanel::~CPanelListPanel()
{
// free data from table
DeleteAllItems();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CPanelListPanel::computeVPixelsNeeded( void )
{
int pixels =0;
DATAITEM *item;
Panel *panel;
for ( int i = 0; i < _dataItems.GetCount(); i++ )
{
item = _dataItems[ i ];
if ( !item )
continue;
panel = item->panel;
if ( !panel )
continue;
int w, h;
panel->GetSize( w, h );
pixels += h;
}
pixels+=5; // add a buffer after the last item
return pixels;
}
//-----------------------------------------------------------------------------
// Purpose: Returns the panel to use to render a cell
// Input : column -
// row -
// Output : Panel
//-----------------------------------------------------------------------------
Panel *CPanelListPanel::GetCellRenderer( int row )
{
DATAITEM *item = _dataItems[ row ];
if ( item )
{
Panel *panel = item->panel;
return panel;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: adds an item to the view
// data->GetName() is used to uniquely identify an item
// data sub items are matched against column header name to be used in the table
// Input : *item -
//-----------------------------------------------------------------------------
int CPanelListPanel::AddItem( Panel *panel )
{
InvalidateLayout();
DATAITEM *newitem = new DATAITEM;
newitem->panel = panel;
panel->SetParent( _embedded );
return _dataItems.PutElement( newitem );
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
int CPanelListPanel::GetItemCount( void )
{
return _dataItems.GetCount();
}
//-----------------------------------------------------------------------------
// Purpose: returns pointer to data the row holds
// Input : itemIndex -
// Output : KeyValues
//-----------------------------------------------------------------------------
Panel *CPanelListPanel::GetItem(int itemIndex)
{
if ( itemIndex < 0 || itemIndex >= _dataItems.GetCount() )
return NULL;
return _dataItems[itemIndex]->panel;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : itemIndex -
// Output : DATAITEM
//-----------------------------------------------------------------------------
CPanelListPanel::DATAITEM *CPanelListPanel::GetDataItem( int itemIndex )
{
if ( itemIndex < 0 || itemIndex >= _dataItems.GetCount() )
return NULL;
return _dataItems[ itemIndex ];
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : index -
//-----------------------------------------------------------------------------
void CPanelListPanel::RemoveItem(int itemIndex)
{
DATAITEM *item = _dataItems[ itemIndex ];
delete item->panel;
delete item;
_dataItems.RemoveElementAt(itemIndex);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: clears and deletes all the memory used by the data items
//-----------------------------------------------------------------------------
void CPanelListPanel::DeleteAllItems()
{
for (int i = 0; i < _dataItems.GetCount(); i++)
{
if ( _dataItems[i] )
{
delete _dataItems[i]->panel;
}
delete _dataItems[i];
}
_dataItems.RemoveAll();
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPanelListPanel::OnMouseWheeled(int delta)
{
int val = _vbar->GetValue();
val -= (delta * 3 * 5);
_vbar->SetValue(val);
}
//-----------------------------------------------------------------------------
// Purpose: relayouts out the panel after any internal changes
//-----------------------------------------------------------------------------
void CPanelListPanel::PerformLayout()
{
int wide, tall;
GetSize( wide, tall );
int vpixels = computeVPixelsNeeded();
//!! need to make it recalculate scroll positions
_vbar->SetVisible(true);
_vbar->SetEnabled(false);
_vbar->SetRange( 0, vpixels - tall + 24);
_vbar->SetRangeWindow( 24 /*vpixels / 10*/ );
_vbar->SetButtonPressedScrollValue( 24 );
_vbar->SetPos(wide - 20, _sliderYOffset);
_vbar->SetSize(18, tall - 2 - _sliderYOffset);
_vbar->InvalidateLayout();
int top = _vbar->GetValue();
_embedded->SetPos( 0, -top );
_embedded->SetSize( wide-20, vpixels );
// Now lay out the controls on the embedded panel
int y = 0;
int h = 0;
for ( int i = 0; i < _dataItems.GetCount(); i++, y += h )
{
DATAITEM *item = _dataItems[ i ];
if ( !item || !item->panel )
continue;
h = item->panel->GetTall();
item->panel->SetBounds( 8, y, wide-36, h );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPanelListPanel::PaintBackground()
{
Panel::PaintBackground();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *inResourceData -
//-----------------------------------------------------------------------------
void CPanelListPanel::ApplySchemeSettings(IScheme *pScheme)
{
Panel::ApplySchemeSettings(pScheme);
SetBorder(pScheme->GetBorder("ButtonDepressedBorder"));
SetBgColor(GetSchemeColor("Label.BgColor", GetBgColor(), pScheme));
// _labelFgColor = GetSchemeColor("WindowFgColor");
// _selectionFgColor = GetSchemeColor("ListSelectionFgColor", _labelFgColor);
}
void CPanelListPanel::OnSliderMoved( int position )
{
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CPanelListPanel::SetSliderYOffset( int pixels )
{
_sliderYOffset = pixels;
}

View File

@@ -0,0 +1,79 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if !defined( PANELLISTPANEL_H )
#define PANELLISTPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/VGUI.h>
#include <vgui_controls/Panel.h>
class KeyValues;
//-----------------------------------------------------------------------------
// Purpose: A list of variable height child panels
//-----------------------------------------------------------------------------
class CPanelListPanel : public vgui::Panel
{
DECLARE_CLASS_SIMPLE( CPanelListPanel, vgui::Panel );
public:
typedef struct dataitem_s
{
// Always store a panel pointer
vgui::Panel *panel;
} DATAITEM;
CPanelListPanel( vgui::Panel *parent, char const *panelName, bool inverseButtons = false );
~CPanelListPanel();
// DATA & ROW HANDLING
// The list now owns the panel
virtual int computeVPixelsNeeded( void );
virtual int AddItem( vgui::Panel *panel );
virtual int GetItemCount( void );
virtual vgui::Panel *GetItem(int itemIndex); // returns pointer to data the row holds
virtual void RemoveItem(int itemIndex); // removes an item from the table (changing the indices of all following items)
virtual void DeleteAllItems(); // clears and deletes all the memory used by the data items
// career-mode UI wants to nudge sub-controls around
void SetSliderYOffset(int pixels);
// PAINTING
virtual vgui::Panel *GetCellRenderer( int row );
MESSAGE_FUNC_INT( OnSliderMoved, "ScrollBarSliderMoved", position );
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
vgui::Panel *GetEmbedded()
{
return _embedded;
}
protected:
DATAITEM *GetDataItem( int itemIndex );
virtual void PerformLayout();
virtual void PaintBackground();
virtual void OnMouseWheeled(int delta);
private:
// list of the column headers
vgui::Dar<DATAITEM *> _dataItems;
vgui::ScrollBar *_vbar;
vgui::Panel *_embedded;
int _tableStartX;
int _tableStartY;
int _sliderYOffset;
};
#endif // PANELLISTPANEL_H

View File

@@ -0,0 +1,250 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "PlayerListDialog.h"
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui_controls/ListPanel.h>
#include <KeyValues.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/MessageBox.h>
#include "EngineInterface.h"
#include "game/client/IGameClientExports.h"
#include "GameUI_Interface.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CPlayerListDialog::CPlayerListDialog(vgui::Panel *parent) : BaseClass(parent, "PlayerListDialog")
{
SetSize(320, 240);
SetTitle("#GameUI_CurrentPlayers", true);
m_pMuteButton = new Button(this, "MuteButton", "");
m_pPlayerList = new ListPanel(this, "PlayerList");
m_pPlayerList->AddColumnHeader(0, "Name", "#GameUI_PlayerName", 180);
m_pPlayerList->AddColumnHeader(1, "Properties", "#GameUI_Properties", 80);
m_pPlayerList->SetEmptyListText("#GameUI_NoOtherPlayersInGame");
LoadControlSettings("Resource/PlayerListDialog.res");
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CPlayerListDialog::~CPlayerListDialog()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPlayerListDialog::Activate()
{
BaseClass::Activate();
// refresh player list
m_pPlayerList->DeleteAllItems();
int maxClients = engine->GetMaxClients();
for (int i = 1; i <= maxClients; i++)
{
// get the player info from the engine
player_info_t pi;
if ( !engine->GetPlayerInfo(i, &pi) )
continue;
char szPlayerIndex[32];
Q_snprintf(szPlayerIndex, sizeof( szPlayerIndex ), "%d", i);
// collate user data then add it to the table
KeyValues *data = new KeyValues(szPlayerIndex);
data->SetString("Name", pi.name );
data->SetInt("index", i);
// add to the list
m_pPlayerList->AddItem(data, 0, false, false);
}
// refresh player properties info
RefreshPlayerProperties();
// select the first item by default
m_pPlayerList->SetSingleSelectedItem( m_pPlayerList->GetItemIDFromRow(0) );
// toggle button states
OnItemSelected();
}
//-----------------------------------------------------------------------------
// Purpose: walks the players and sets their info display in the list
//-----------------------------------------------------------------------------
void CPlayerListDialog::RefreshPlayerProperties()
{
for (int i = 0; i <= m_pPlayerList->GetItemCount(); i++)
{
KeyValues *data = m_pPlayerList->GetItem(i);
if (!data)
continue;
// assemble properties
int playerIndex = data->GetInt("index");
player_info_t pi;
if ( !engine->GetPlayerInfo( playerIndex, &pi) )
{
// disconnected
data->SetString("properties", "Disconnected");
continue;
}
data->SetString( "name", pi.name );
bool muted = false, friends = false, bot = false;
if ( GameClientExports() && GameClientExports()->IsPlayerGameVoiceMuted(playerIndex) )
{
muted = true;
}
if ( pi.fakeplayer )
{
bot = true;
}
if (bot)
{
data->SetString("properties", "CPU Player");
}
else if (muted && friends)
{
data->SetString("properties", "Friend; Muted");
}
else if (muted)
{
data->SetString("properties", "Muted");
}
else if (friends)
{
data->SetString("properties", "Friend");
}
else
{
data->SetString("properties", "");
}
}
m_pPlayerList->RereadAllItems();
}
//-----------------------------------------------------------------------------
// Purpose: Handles the AddFriend command
//-----------------------------------------------------------------------------
void CPlayerListDialog::OnCommand(const char *command)
{
if (!stricmp(command, "Mute"))
{
ToggleMuteStateOfSelectedUser();
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: toggles whether a user is muted or not
//-----------------------------------------------------------------------------
void CPlayerListDialog::ToggleMuteStateOfSelectedUser()
{
if (!GameClientExports())
return;
for ( int iSelectedItem = 0; iSelectedItem < m_pPlayerList->GetSelectedItemsCount(); iSelectedItem++ )
{
KeyValues *data = m_pPlayerList->GetItem( m_pPlayerList->GetSelectedItem( iSelectedItem ) );
if (!data)
return;
int playerIndex = data->GetInt("index");
Assert(playerIndex);
if (GameClientExports()->IsPlayerGameVoiceMuted(playerIndex))
{
GameClientExports()->UnmutePlayerGameVoice(playerIndex);
}
else
{
GameClientExports()->MutePlayerGameVoice(playerIndex);
}
}
RefreshPlayerProperties();
OnItemSelected();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPlayerListDialog::OnItemSelected()
{
// make sure the data is up-to-date
RefreshPlayerProperties();
// set the button state based on the selected item
bool bMuteButtonEnabled = false;
if (m_pPlayerList->GetSelectedItemsCount() > 0)
{
KeyValues *data = m_pPlayerList->GetItem(m_pPlayerList->GetSelectedItem(0));
player_info_t pi;
int iLocalPlayer = engine->GetLocalPlayer();
int iPlayerIndex = data->GetInt("index");
bool isValidPlayer = engine->GetPlayerInfo( iPlayerIndex, &pi );
// make sure the player is not a bot, or the user
// Matt - changed this check to see if player indeces match, instead of using friends ID
if ( pi.fakeplayer || iPlayerIndex == iLocalPlayer ) // || pi.friendsID == g_pFriendsUser->GetFriendsID() )
{
// invalid player,
isValidPlayer = false;
}
if (data && isValidPlayer && GameClientExports() && GameClientExports()->IsPlayerGameVoiceMuted(data->GetInt("index")))
{
m_pMuteButton->SetText("#GameUI_UnmuteIngameVoice");
}
else
{
m_pMuteButton->SetText("#GameUI_MuteIngameVoice");
}
if (GameClientExports() && isValidPlayer)
{
bMuteButtonEnabled = true;
}
}
else
{
m_pMuteButton->SetText("#GameUI_MuteIngameVoice");
}
m_pMuteButton->SetEnabled( bMuteButtonEnabled );
}

View File

@@ -0,0 +1,41 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef PLAYERLISTDIALOG_H
#define PLAYERLISTDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/Frame.h>
//-----------------------------------------------------------------------------
// Purpose: List of players, their ingame-name and their friends-name
//-----------------------------------------------------------------------------
class CPlayerListDialog : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CPlayerListDialog, vgui::Frame );
public:
CPlayerListDialog(vgui::Panel *parent);
~CPlayerListDialog();
virtual void Activate();
private:
MESSAGE_FUNC( OnItemSelected, "ItemSelected" );
virtual void OnCommand(const char *command);
void ToggleMuteStateOfSelectedUser();
void RefreshPlayerProperties();
vgui::ListPanel *m_pPlayerList;
vgui::Button *m_pMuteButton;
};
#endif // PLAYERLISTDIALOG_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,275 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef __BASEMODFRAME_H__
#define __BASEMODFRAME_H__
#include "vgui_controls/Panel.h"
#include "vgui_controls/Frame.h"
#include "tier1/utllinkedlist.h"
#include "basemodpanel.h"
class CUniformRandomStream;
namespace BaseModUI {
class BaseModHybridButton;
struct DialogMetrics_t
{
int titleY;
int titleHeight;
int dialogY;
int dialogHeight;
};
enum MenuTiles_e
{
MT_TOP_LEFT = 0,
MT_TOP,
MT_TOP_RIGHT,
MT_LEFT,
MT_INTERIOR,
MT_INTERIOR_ALT,
MT_RIGHT,
MT_BOTTOM_LEFT,
MT_BOTTOM,
MT_BOTTOM_RIGHT,
MAX_MENU_TILES
};
enum DialogStyle_e
{
DS_SIMPLE = 1,
DS_CONFIRMATION = 2,
DS_WAITSCREEN = 3,
DS_CUSTOMTITLE = 4,
};
//=============================================================================
//
//=============================================================================
class IBaseModFrameListener
{
public:
virtual void RunFrame() = 0;
};
//=============================================================================
//
//=============================================================================
class CBaseModFrame : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CBaseModFrame, vgui::Frame );
public:
CBaseModFrame( vgui::Panel *parent, const char *panelName, bool okButtonEnabled = true,
bool cancelButtonEnabled = true, bool imgBloodSplatterEnabled = true, bool doButtonEnabled = true );
virtual ~CBaseModFrame();
virtual void SetTitle(const char *title, bool surfaceTitle);
virtual void SetTitle(const wchar_t *title, bool surfaceTitle);
virtual void SetDataSettings( KeyValues *pSettings );
virtual void LoadLayout();
void ReloadSettings();
virtual void OnKeyCodePressed(vgui::KeyCode code);
#ifndef _GAMECONSOLE
virtual void OnKeyCodeTyped( vgui::KeyCode code );
#endif
virtual void OnMousePressed( vgui::MouseCode code );
virtual void OnOpen();
virtual void OnClose();
virtual void OnThink();
virtual void Activate();
virtual void OnCommand( char const *szCommand );
virtual vgui::Panel *NavigateBack();
CBaseModFrame *SetNavBack( CBaseModFrame* navBack );
CBaseModFrame *GetNavBack() { return m_NavBack.Get(); }
bool CanNavBack() { return m_bCanNavBack; }
virtual void PostChildPaint();
virtual void PaintBackground();
virtual void FindAndSetActiveControl();
virtual void RunFrame();
// Load the control settings
virtual void LoadControlSettings( const char *dialogResourceName, const char *pathID = NULL, KeyValues *pPreloadedKeyValues = NULL, KeyValues *pConditions = NULL );
MESSAGE_FUNC_CHARPTR( OnNavigateTo, "OnNavigateTo", panelName );
static void AddFrameListener( IBaseModFrameListener * frameListener );
static void RemoveFrameListener( IBaseModFrameListener * frameListener );
static void RunFrameOnListeners();
virtual bool GetFooterEnabled();
void CloseWithoutFade();
void ToggleTitleSafeBorder();
void PushModalInputFocus(); // Makes this panel take modal input focus and maintains stack of previous panels with focus. For PC only.
void PopModalInputFocus(); // Removes modal input focus and gives focus to previous panel on stack. For PC only.
bool CheckAndDisplayErrorIfNotLoggedIn(); // Displays error if not logged into Steam (no-op on X360)
void DrawGenericBackground();
void DrawDialogBackground( const char *pMajor = NULL, const wchar_t *pMajorFormatted = NULL, const char *pMinor = NULL, const wchar_t *pMinorFormatted = NULL, DialogMetrics_t *pMetrics = NULL, bool bAllCapsTitle = false, int iTitleXOffset = INT_MAX );
void SetupAsDialogStyle();
void SetDialogTitle( const char *pTitle = NULL, const wchar_t *pTitleFormatted = NULL, bool bShowController = false, int nTilesWide = 0, int nTilesTall = 0, int nTitleTilesWide = 0 );
void SetDialogSubTitle( const char *pTitle = NULL, const wchar_t *pTitleFormatted = NULL, bool bShowController = false, int nTilesWide = 0, int nTilesTall = 0, int nTitleTilesWide = 0 );
void GetDialogTileSize( int &nTileWidth, int &nTileHeight );
void SetUseAlternateTiles( bool bUseAlternate ) { m_bUseAlternateTiles = bUseAlternate; };
bool UsesAlternateTiles( void ) const { return m_bUseAlternateTiles; }
static char const * GetEntityOverMouseCursorInEngine();
virtual KeyValues * GetResourceLoadConditions() { return m_pResourceLoadConditions; }
WINDOW_TYPE GetWindowType();
WINDOW_PRIORITY GetWindowPriority();
void RestoreFocusToActiveControl();
protected:
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void ApplySettings(KeyValues *inResourceData);
virtual void PerformLayout();
virtual void PostApplySettings();
virtual void CreateVirtualUiControls();
virtual void ExecuteCommandForEntity( char const *szEntityName );
virtual void GetEntityNameForControl( char const *szControlId, char chEntityName[256] );
virtual void ResolveEntityName( char const *szEntityName, char chEntityName[256] );
void SetOkButtonEnabled( bool bEnabled );
void SetCancelButtonEnabled( bool bEnabled );
void SetUpperGarnishEnabled( bool bEnabled );
void SetFooterEnabled( bool bEnabled );
void DrawControllerIndicator();
protected:
static CUtlVector< IBaseModFrameListener * > m_FrameListeners;
static bool m_DrawTitleSafeBorder;
vgui::Panel* m_ActiveControl;
vgui::Label* m_LblTitle;
bool m_FooterEnabled;
bool m_OkButtonEnabled;
bool m_CancelButtonEnabled;
bool m_bLayoutLoaded;
bool m_bIsFullScreen;
bool m_bDelayPushModalInputFocus; // set to true if we need to consider taking modal input focus, but can't do it yet
char m_ResourceName[64];
KeyValues *m_pResourceLoadConditions;
private:
friend class CBaseModPanel;
void SetWindowType(WINDOW_TYPE windowType);
void SetWindowPriority( WINDOW_PRIORITY pri );
void SetCanBeActiveWindowType(bool allowed);
bool GetCanBeActiveWindowType();
WINDOW_TYPE m_WindowType;
WINDOW_PRIORITY m_WindowPriority;
bool m_CanBeActiveWindowType;
vgui::DHANDLE<CBaseModFrame> m_NavBack; // panel to nav back to
bool m_bCanNavBack; // can we nav back: use this to distinguish between "no panel set" vs "panel has gone away" for nav back
CUtlVector<vgui::HPanel> m_vecModalInputFocusStack;
int m_nDialogStyle;
vgui::HFont m_hTitleFont;
wchar_t m_TitleString[256];
vgui::HFont m_hSubTitleFont;
wchar_t m_SubTitleString[256];
Color m_SubTitleColor;
Color m_SubTitleColorAlt;
int m_nSubTitleWide;
int m_nSubTitleTall;
int m_nTitleWide;
int m_nTitleTall;
int m_nTitleOffsetX;
int m_nTitleOffsetY;
Color m_TitleColor;
Color m_TitleColorAlt;
Color m_MessageBoxTitleColor;
Color m_MessageBoxTitleColorAlt;
int m_nTileWidth;
int m_nTileHeight;
int m_nOriginalTall;
int m_nOriginalWide;
int m_nTilesWide;
int m_nTilesTall;
int m_nTitleTilesWide;
int m_nPinFromBottom;
int m_nPinFromLeft;
int m_nFooterOffsetY;
bool m_bUseAlternateTiles;
int m_nTileImageId[MAX_MENU_TILES];
int m_nAltTileImageId[MAX_MENU_TILES];
int m_nAltRandomTileImageId[2];
int m_nAltSeed;
CUniformRandomStream m_RandomStream;
bool m_bLayoutFixed;
vgui::HFont m_hButtonFont;
bool m_bShowController;
protected:
CPanelAnimationVarAliasType( int, m_iHeaderY, "header_y", "19", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iHeaderTall, "header_tall", "41", "proportional_int" );
CPanelAnimationVarAliasType( int, m_iTitleXOffset, "header_title_x", "180", "proportional_int" ); // pixels left of center
protected:
// Virtual UI Settings
KeyValues *m_pVuiSettings;
CUtlVector< BaseModHybridButton * > m_arrVirtualUiControls;
};
};
class CBackgroundMapActiveControlManager
{
public:
CBackgroundMapActiveControlManager();
public:
void NavigateToEntity( char const *szEntity );
void Reset();
void Apply();
protected:
char m_chLastActiveEntity[256];
};
extern CBackgroundMapActiveControlManager g_BackgroundMapActiveControlManager;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,771 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef _BASEMODFACTORYBASEPANEL_H__
#define _BASEMODFACTORYBASEPANEL_H__
#define GAMEUI_BASEMODPANEL_VGUI
#define GAMEUI_BASEMODPANEL_SCHEME "basemodui_scheme"
#include "vgui_controls/Panel.h"
#include "vgui_controls/Frame.h"
#include "vgui_controls/Button.h"
#include "tier1/utllinkedlist.h"
#include "../OptionsDialog.h"
#include "../OptionsSubKeyboard.h"
#include "avi/ibik.h"
#include "ixboxsystem.h"
#include "matchmaking/imatchframework.h"
#include "utlmap.h"
#include "ugc_workshop_manager.h"
#if defined( PORTAL2_PUZZLEMAKER )
extern ConVar cm_current_community_map;
#endif // PORTAL2_PUZZLEMAKER
#define BASEMODPANEL_SINGLETON BaseModUI::CBaseModPanel::GetSingleton()
#if !defined( NO_STEAM )
extern CWorkshopManager &WorkshopManager( void );
#endif //
// must supply some non-trivial time to let the movie startup smoothly
#define TRANSITION_FROM_OVERLAY_DELAY_TIME 0.5f // how long to wait before starting the fade
#define TRANSITION_OVERLAY_FADE_TIME 0.7f // how fast to fade
#define COMMUNITY_MAP_PATH "maps/workshop" // Path to Workshop maps downloaded from Steam
#define COMMUNITY_MAP_THUMBNAIL_PREFIX "thumb" // Prefix for thumbnail filename
enum OverlayResult_t
{
RESULT_OK = 0,
RESULT_FAIL_OVERLAY_DISABLED,
RESULT_FAIL_INVALID_UNIVERSE,
RESULT_FAIL_INVALID_USER_ID,
RESULT_FAIL_MISSING_API
};
enum {
UGC_PRIORITY_GENERIC = 0, // Misc files
UGC_PRIORITY_BSP, // Content
UGC_PRIORITY_THUMBNAIL, // Thumbnails for content
UGC_PRIORITY_USER_MAP, // User created maps
};
enum ECommunityMapQueueMode {
QUEUEMODE_INVALID = -1, // Nothing has been set, any queue calls are invalid!
QUEUEMODE_USER_QUEUE, // User is moving through their specified queue
QUEUEMODE_USER_COOP_QUEUE, // User is moving through their specified coop queue
QUEUEMODE_QUICK_PLAY, // User is quick playing with a filter
QUEUEMODE_COOP_QUICK_PLAY, // User is quick playing coop maps
};
#if !defined( NO_STEAM )
// Handle file requests for community maps (downloads thumbnail / content)
class CBaseCommunityRequest : public CBasePublishedFileRequest
{
public:
CBaseCommunityRequest( PublishedFileId_t nFileID ) :
CBasePublishedFileRequest( nFileID )
{}
virtual void OnLoaded( PublishedFileInfo_t &info );
};
// Handle file requests for community maps (downloads thumbnail / content)
class CCommunityMapRequest : public CBaseCommunityRequest
{
public:
typedef CBaseCommunityRequest BaseClass;
CCommunityMapRequest( PublishedFileId_t nFileID, uint32 nSubscribeTime ) :
BaseClass( nFileID ),
m_unSubscribeTime( nSubscribeTime )
{}
virtual void OnLoaded( PublishedFileInfo_t &info );
virtual void OnError( EResult nErrorCode );
uint32 m_unSubscribeTime;
};
// Handle file requests for partner's community coop maps (downloads thumbnail / content)
class CCommunityMapCoopRequest : public CBaseCommunityRequest
{
public:
typedef CBaseCommunityRequest BaseClass;
CCommunityMapCoopRequest( PublishedFileId_t nFileID, UGCHandle_t hFile, UGCHandle_t hPreviewFile ) :
BaseClass( nFileID ), m_hCoopFile( hFile ), m_hCoopPreviewFile( hPreviewFile )
{}
virtual void OnLoaded( PublishedFileInfo_t &info );
virtual void OnError( EResult nErrorCode );
UGCHandle_t m_hCoopFile;
UGCHandle_t m_hCoopPreviewFile;
};
class CCommunityMapSPQuickplayRequest : public CBaseCommunityRequest
{
public:
typedef CBaseCommunityRequest BaseClass;
CCommunityMapSPQuickplayRequest( PublishedFileId_t nFileID ) :
BaseClass( nFileID )
{}
virtual void OnLoaded( PublishedFileInfo_t &info );
virtual void OnError( EResult nErrorCode );
};
// Handle file requests for community coop quickplay
class CCommunityMapCoopQuickplayRequest : public CBaseCommunityRequest
{
public:
typedef CBaseCommunityRequest BaseClass;
CCommunityMapCoopQuickplayRequest( PublishedFileId_t nFileID ) :
BaseClass( nFileID )
{}
virtual void OnLoaded( PublishedFileInfo_t &info );
virtual void OnError( EResult nErrorCode );
};
// Handle file requests for community map queue history (downloads thumbnail)
class CQueueHistoryEntryRequest : public CBaseCommunityRequest
{
public:
typedef CBaseCommunityRequest BaseClass;
CQueueHistoryEntryRequest( PublishedFileId_t nFileID ) :
BaseClass( nFileID ),
m_unLastPlayedTime( 0 ),
m_unCompletionTime( 0 )
{}
CQueueHistoryEntryRequest( PublishedFileId_t nFileID, uint32 nLastPlayedTime, uint32 nCompletionTime ) :
BaseClass( nFileID ),
m_unLastPlayedTime( nLastPlayedTime ),
m_unCompletionTime( nCompletionTime )
{}
virtual void OnLoaded( PublishedFileInfo_t &info );
virtual void OnError( EResult nErrorCode );
uint32 m_unLastPlayedTime;
uint32 m_unCompletionTime;
};
// Handle file requests for community maps (downloads thumbnail / content)
class CUserPublishedFileRequest : public CBaseCommunityRequest
{
public:
typedef CBaseCommunityRequest BaseClass;
CUserPublishedFileRequest( PublishedFileId_t nFileID ) :
BaseClass( nFileID )
{}
virtual void OnLoaded( PublishedFileInfo_t &info );
virtual void OnError( EResult nErrorCode );
};
#endif // !NO_STEAM
struct SaveGameInfo_t
{
SaveGameInfo_t()
{
m_nFileTime = 0;
m_nElapsedSeconds = 0;
m_nChapterNum = 1;
m_bIsAutoSave = false;
m_bIsCloudSave = false;
m_bIsInCloud = false;
}
CUtlString m_InternalIDname;
CUtlString m_Filename;
CUtlString m_FullFilename;
CUtlString m_ScreenshotFilename;
CUtlString m_MapName;
CUtlString m_Comment;
time_t m_nFileTime;
unsigned int m_nElapsedSeconds;
int m_nChapterNum;
bool m_bIsAutoSave;
bool m_bIsCloudSave;
bool m_bIsInCloud;
};
namespace BaseModUI
{
enum WINDOW_TYPE
{
WT_NONE = 0,
WT_ACHIEVEMENTS,
WT_AUDIO,
WT_AUDIOVIDEO,
WT_CLOUD,
WT_CONTROLLER,
WT_CONTROLLER_STICKS,
WT_CONTROLLER_BUTTONS,
WT_DOWNLOADS,
WT_GAMELOBBY,
WT_GAMEOPTIONS,
WT_GAMESETTINGS,
WT_GENERICCONFIRMATION,
WT_INGAMEDIFFICULTYSELECT,
WT_INGAMEMAINMENU,
WT_INGAMECHAPTERSELECT,
WT_INGAMEKICKPLAYERLIST,
WT_VOTEOPTIONS,
WT_KEYBOARDMOUSE,
WT_LOADINGPROGRESS,
WT_MAINMENU,
WT_ENDINGSPLITSCREEN,
WT_MULTIPLAYER,
WT_OPTIONS,
WT_OPTIONSCLOUD,
WT_SEARCHINGFORLIVEGAMES,
WT_SIGNINDIALOG,
WT_STEAMLINKDIALOG,
WT_SINGLEPLAYER,
WT_COOPMODESELECT,
WT_GENERICWAITSCREEN,
WT_ATTRACTSCREEN,
WT_STARTCOOPGAME,
WT_ALLGAMESEARCHRESULTS,
WT_PVP_LOBBY,
WT_FOUNDPUBLICGAMES,
WT_TRANSITIONSCREEN,
WT_PASSWORDENTRY,
WT_VIDEO,
WT_STEAMCLOUDCONFIRM,
WT_STEAMGROUPSERVERS,
WT_CUSTOMCAMPAIGNS,
WT_ADDONS,
WT_DOWNLOADCAMPAIGN,
WT_LEADERBOARD,
WT_ADDONASSOCIATION,
WT_GETLEGACYDATA,
WT_NEWGAME,
WT_CHALLENGEMODE,
WT_SAVEGAME,
WT_LOADGAME,
WT_MOVIEPLAYER,
WT_COMMENTARY,
WT_XBOXLIVE,
WT_AUTOSAVENOTICE,
WT_FADEOUTSTARTGAME,
WT_ADVANCEDVIDEO,
WT_KEYBINDINGS,
WT_SOUNDTEST,
WT_PORTALLEADERBOARD,
WT_PORTALCOOPLEADERBOARD,
WT_PORTALLEADERBOARDHUD,
WT_COOPEXITCHOICE,
WT_EXTRAS,
WT_FADEOUTTOECONUI,
#if defined( PORTAL2_PUZZLEMAKER )
WT_COMMUNITYMAP,
WT_RATEMAP,
WT_PLAYTESTDEMOS,
WT_PLAYTESTUPLOADWAIT,
WT_EDITORMAINMENU,
WT_EDITORCHAMBERLIST,
WT_PUZZLEMAKEREXITCONRFIRMATION,
WT_PUZZLEMAKERSAVEDIALOG,
WT_PUZZLEMAKERCOMPILEDIALOG,
WT_PUZZLEMAKERPUBLISHPROGRESS,
WT_QUICKPLAY,
#endif // PORTAL2_PUZZLEMAKER
WT_WINDOW_COUNT // WT_WINDOW_COUNT must be last in the list!
};
enum WINDOW_PRIORITY
{
WPRI_NONE,
WPRI_BKGNDSCREEN,
WPRI_NORMAL,
WPRI_WAITSCREEN,
WPRI_MESSAGE,
WPRI_LOADINGPLAQUE,
WPRI_TOPMOST, // must be highest priority, no other windows can obscure
WPRI_COUNT // WPRI_COUNT must be last in the list!
};
enum UISound_t
{
UISOUND_BACK,
UISOUND_ACCEPT,
UISOUND_INVALID,
UISOUND_COUNTDOWN,
UISOUND_FOCUS,
UISOUND_CLICK,
UISOUND_DENY,
UISOUND_TILE_CLICK1,
UISOUND_TILE_CLICK2,
};
class CBaseModFrame;
class CBaseModFooterPanel;
class CBaseModTransitionPanel;
//=============================================================================
//
//=============================================================================
class CBaseModPanel : public vgui::EditablePanel, public IMatchEventsSink
{
DECLARE_CLASS_SIMPLE( CBaseModPanel, vgui::EditablePanel );
public:
CBaseModPanel();
~CBaseModPanel();
// IMatchEventSink implementation
public:
virtual void OnEvent( KeyValues *pEvent );
public:
static CBaseModPanel& GetSingleton();
static CBaseModPanel* GetSingletonPtr();
void ReloadScheme();
CBaseModFrame* OpenWindow( const WINDOW_TYPE& wt, CBaseModFrame * caller, bool hidePrevious = true, KeyValues *pParameters = NULL );
CBaseModFrame* GetWindow( const WINDOW_TYPE& wt );
void OnFrameClosed( WINDOW_PRIORITY pri, WINDOW_TYPE wt );
void DbgShowCurrentUIState();
bool IsLevelLoading();
void OnClientReady();
WINDOW_TYPE GetActiveWindowType();
WINDOW_PRIORITY GetActiveWindowPriority();
void SetActiveWindow( CBaseModFrame * frame );
bool OpenMessageDialog( const char *lpszTitle, const char *lpszMessage );
enum CloseWindowsPolicy_t
{
CLOSE_POLICY_DEFAULT = 0, // will keep msg boxes alive
CLOSE_POLICY_EVEN_MSGS = 1, // will kill even msg boxes
CLOSE_POLICY_EVEN_LOADING = 2, // will kill even loading screen
CLOSE_POLICY_KEEP_BKGND = 0x100, // will keep bkgnd screen
};
void CloseAllWindows( int ePolicyFlags = CLOSE_POLICY_DEFAULT );
void OnGameUIActivated();
void OnGameUIHidden();
void OpenFrontScreen( bool bIgnoreMatchSession = false );
void RunFrame();
void OnLevelLoadingStarted( char const *levelName, bool bShowProgressDialog );
void OnLevelLoadingFinished( KeyValues *kvEvent );
bool UpdateProgressBar(float progress, const char *statusText);
void OnCreditsFinished(void);
void SetOkButtonEnabled( bool enabled );
void SetCancelButtonEnabled( bool enabled );
const char *GetUISoundName( UISound_t uiSound );
void PlayUISound( UISound_t uiSound );
void StartExitingProcess( bool bWarmRestart );
CBaseModFooterPanel* GetFooterPanel();
void SetLastActiveUserId( int userId );
int GetLastActiveUserId();
void OpenOptionsDialog( Panel *parent );
void OpenKeyBindingsDialog( Panel *parent );
MESSAGE_FUNC_CHARPTR( OnNavigateTo, "OnNavigateTo", panelName );
MESSAGE_FUNC_PARAMS( MigrateHostToClient, "MigrateHostToClient", params );
bool IsMenuBackgroundMovieValid( void );
bool IsBackgroundMusicPlaying();
bool StartBackgroundMusic( float fVol );
void UpdateBackgroundMusicVolume( float fVol );
void ReleaseBackgroundMusic();
void OnTileSetChanged( void ); // We've swapped from a menu with one tile set to another
void SafeNavigateTo( Panel *pExpectedFrom, Panel *pDesiredTo, bool bAllowStealFocus );
#if defined( _X360 ) && defined( _DEMO )
void OnDemoTimeout();
#endif
int MapNameToChapter( const char *pMapName, bool bSinglePlayer = true );
int MapNameToSubChapter( const char *pMapName );
const char *ChapterToMapName( int nChapter );
const char *ActToMapName( int nAct );
const char *GetMapName( int nChapter, int nMap, bool bSinglePlayer = true );
int GetMapNumInChapter( int nChapter, const char *pMapName, bool bSinglePlayer = true );
int ChapterToAct( int nChapter );
int GetChapterProgress();
int GetNumChapters( bool bSinglePlayer = true );
int GetNumMaps( bool bSinglePlayer = true );
int GetNumMapsInChapter( int nChapter, bool bSinglePlayer = true );
int GetCoopTrackFromChapter( int nChapterNum );
int GetCoopChapterFromTrack( int nTrackNum );
bool GetSaveGameInfos( CUtlVector< SaveGameInfo_t > &saveGameInfos, bool bFindAll = true );
int GetMostRecentSaveGame( CUtlVector< SaveGameInfo_t > &saveGameInfos );
bool IsOpaqueOverlayActive();
bool LoadingProgressWantsIsolatedRender( bool bContextValid );
bool RenderMovie( BIKMaterial_t hBIKMaterial );
void CalculateMovieParameters( BIKMaterial_t hBIKMaterial, bool bLetterbox = false );
void ResetAttractDemoTimeout( bool bForce = false );
void DrawColoredText( int x, int y, Color color, const char *pAnsiText, vgui::HFont hFont = vgui::INVALID_FONT );
void SetupPartnerInScience();
XUID GetPartnerXUID() { return m_xuidAvatarImage; }
CUtlString &GetPartnerName() { return m_PartnerNameString; }
vgui::IImage *GetPartnerImage() { return m_pAvatarImage; }
char const *GetPartnerDescKey();
#if defined( PORTAL2_PUZZLEMAKER )
void SetupCommunityMapLoad();
void SetForceUseAlternateTileSet( bool bUseAlternateTileSet ) { m_bForceUseAlternateTileSet = bUseAlternateTileSet; }
bool ForceUseAlternateTileSet( void ) const { return m_bForceUseAlternateTileSet; }
#endif // PORTAL2_PUZZLEMAKER
bool IsTransitionEffectEnabled();
CBaseModTransitionPanel *GetTransitionEffectPanel();
void AddFadeinDelayAfterOverlay( float flDelay, bool bHideAndFadeinLater = false );
void SetupBackgroundPresentation();
int GetImageId( const char *pImageName );
void ComputeCroppedTexcoords( float flBackgroundSourceAspectRatio /* ie. 16/9, 16/10 */, float flPhysicalAspectRatio /*GetWidth() / GetHeight() */, float &sMin, float &tMin, float &sMax, float &tMax );
void MoveToCommunityMapQueue( void ) { m_bMoveToCommunityMapQueue = true; }
void MoveToEditorMainMenu( void ) { m_bMoveToEditorMainMenu = true; }
#if !defined( NO_STEAM )
//
// Community map queue methods
//
bool RemoveCommunityMap( PublishedFileId_t nID );
unsigned int GetNumCommunityMapsInQueue( void ) const { return m_vecCommunityMapsQueue.Count(); }
const PublishedFileInfo_t *GetCommunityMap( int nIndex );
const PublishedFileInfo_t *GetCommunityMapByFileID( PublishedFileId_t nID ) const;
const PublishedFileInfo_t *GetNextSubscribedMapInQueue() const;
float GetQueueBaselineRequestTime( void ) const { return m_flQueueBaselineRequestTime; }
bool HasReceivedQueueBaseline( void ) const { return m_bReceivedQueueBaseline; }
int GetNumCommunityMapsPlayedThisSession( void ) const { return m_nNumCommunityMapsPlayedThisSession; }
void SetNumCommunityMapsPlayedThisSession( int nNumMapsPlayed );
bool QueueCommunityMapReady( void ) const;
bool IsValidMapForCurrentQueueMode( const PublishedFileInfo_t *pFileInfo ) const;
#if !defined( _GAMECONSOLE )
EWorkshopEnumerationType GetCurrentQuickPlayEnumerationType() const { return m_eCurrentQuickPlayEnumerationType; }
void SetCurrentQuickPlayEnumerationType( EWorkshopEnumerationType eQuickPlayEnumerationType ) { m_eCurrentQuickPlayEnumerationType = eQuickPlayEnumerationType; }
#endif
const PublishedFileInfo_t *GetNextCommunityMapInQueueBasedOnQueueMode() const;
//
// User published map methods
//
bool RemoveUserPublishedMap( PublishedFileId_t nID );
const PublishedFileInfo_t *GetUserPublishedMapByFileID( PublishedFileId_t nID );
const PublishedFileInfo_t *GetUserPublishedMap( int nIndex );
float GetUserPublishedMapsBaselineRequestTime( void ) const { return m_flUserPublishedMapsBaselineRequestTime; }
bool HasReceivedUserPublishedMapsBaseline( void ) const { return m_bReceivedUserPublishedMapsBaseline; }
void AddUserPublishedMap( PublishedFileId_t nMapID );
unsigned int GetNumUserPublishedMaps( void ) const { return m_vecUserPublishedMaps.Count(); }
//
// Queue history methods
//
void QueryForQueueHistory( void );
bool RemoveQueueHistoryEntry( PublishedFileId_t nID );
unsigned int GetNumQueueHistoryEntries( void ) const { return m_vecQueueHistoryEntries.Count(); }
const PublishedFileInfo_t *GetQueueHistoryEntry( int nIndex );
const PublishedFileInfo_t *GetQueueHistoryEntryByFileID( PublishedFileId_t nID );
float GetQueueHistoryBaselineRequestTime( void ) const { return m_flQueueHistoryBaselineRequestTime; }
bool HasReceivedQueueHistoryBaseline( void ) const { return m_bReceivedQueueHistoryBaseline; }
bool QueueHistoryReady( void ) const;
//
// Local map play order (for scripts playing sounds)
//
bool LoadLocalMapPlayOrder( void ); // Load the local play order off disk
bool SaveLocalMapPlayOrder( void );
int GetLocalMapIndexByPublishedFileID( PublishedFileId_t unFileID );
bool SetLocalMapPlayed( PublishedFileId_t unFileID );
//
// UGC methods
//
bool CreateThumbnailFileRequest( const PublishedFileInfo_t &info );
bool CreateMapFileRequest( const PublishedFileInfo_t &info, bool bUserMadeMap = false );
//
// Basic queue / history helper functions
//
bool UnsubscribeFromMap( PublishedFileId_t nMapID );
bool SubscribeToMap( PublishedFileId_t nMapID );
bool MarkCommunityMapPlayedTime( PublishedFileId_t nMapID, uint32 nTime );
bool MarkCommunityMapCompletionTime( PublishedFileId_t nMapID, uint32 nTime );
// FIXME: This is totally hosed now once we work past the int range, but I have no easy way to communicate this state to the server!
PublishedFileId_t GetCurrentCommunityMapID( void ) const;
void SetCurrentCommunityMapID( PublishedFileId_t mapID );
void ClearCurrentCommunityMapID( void );
int GetCurrentCommunityMapQueuePosition( void );
PublishedFileId_t GetNextCommunityMapID( void ) const { return m_nNextFileID; }
void SetNextCommunityMapID( PublishedFileId_t nMapID ) { m_nNextFileID = nMapID; }
// Quick play options
void SetCommunityMapQueueMode( ECommunityMapQueueMode mode ) { m_eCommunityMapQueueMode = mode; }
ECommunityMapQueueMode GetCommunityMapQueueMode( void ) const { return m_eCommunityMapQueueMode; }
float GetQuickPlayBaselineRequestTime( void ) const { return m_flQuickPlayBaselineRequestTime; }
bool HasReceivedQuickPlayBaseline( void ) const { return m_bReceivedQuickPlayBaseline; }
unsigned int GetNumQuickPlayEntries( void ) const { return m_vecQuickPlayMaps.Count(); }
const PublishedFileInfo_t *GetCurrentCommunityMap( void );
const PublishedFileInfo_t *GetNextQuickPlayMapInQueue() const;
bool RemoveQuickPlayMapFromQueue( PublishedFileId_t nID );
bool QuickPlayEntriesReady( void ) const;
bool QuickPlayEntriesError( void ) const;
bool IsQuickplay( void ) const { return m_eCommunityMapQueueMode == QUEUEMODE_COOP_QUICK_PLAY || m_eCommunityMapQueueMode == QUEUEMODE_QUICK_PLAY; }
bool IsCommunityCoop( void ) const { return m_eCommunityMapQueueMode == QUEUEMODE_COOP_QUICK_PLAY || m_eCommunityMapQueueMode == QUEUEMODE_USER_COOP_QUEUE; }
// Overlay / Workshop functions
OverlayResult_t ViewAllCommunityMapsInWorkshop( void );
OverlayResult_t ViewCommunityMapInWorkshop( PublishedFileId_t nFileID );
OverlayResult_t ViewAuthorsWorkshop( CSteamID user );
#endif // !NO_STEAM
#if !defined( _GAMECONSOLE )
bool QueryForQuickPlayMaps();
#endif // !_GAMECONSOLE
// --------------------------------------
protected:
CBaseModPanel(const CBaseModPanel&);
CBaseModPanel& operator=(const CBaseModPanel&);
void ApplySchemeSettings(vgui::IScheme *pScheme);
void PaintBackground();
virtual void PostChildPaint();
void OnCommand(const char *command);
void OnSetFocus();
virtual void OnKeyCodePressed( vgui::KeyCode code );
MESSAGE_FUNC( OnMovedPopupToFront, "OnMovedPopupToFront" );
private:
void DrawCopyStats();
void OnEngineLevelLoadingSession( KeyValues *pEvent );
bool ActivateBackgroundEffects();
void SelectBackgroundPresentation();
bool IsUserIdleForAttractMode();
void PrecacheCommonImages();
// Background movie playback
bool InitBackgroundMovie( void );
bool RenderBackgroundMovie();
void ShutdownBackgroundMovie( void );
void GetBackgroundMovieName( char *pOutBuffer, int nOutBufferSize );
void GetBackgroundMusicName( char *pOutBuffer, int nOutBufferSize, bool bMono );
void TransitionToNewBackgroundMovie( void );
#if !defined( NO_STEAM )
//
// Community map files
//
// Enumeration of subscribed files by this user
CCallResult<CBaseModPanel, RemoteStorageEnumerateUserSubscribedFilesResult_t> m_callbackEnumerateSubscribedMaps;
void Steam_OnEnumerateSubscribedMaps( RemoteStorageEnumerateUserSubscribedFilesResult_t *pResult, bool bError );
CCallResult<CBaseModPanel, RemoteStorageEnumerateUserPublishedFilesResult_t> m_callbackEnumeratePublishedMaps;
void Steam_OnEnumeratePublishedMaps( RemoteStorageEnumerateUserPublishedFilesResult_t *pResult, bool bError );
void QueryForCommunityMaps( void );
void QueryForUserPublishedMaps( void );
CUtlVector< PublishedFileId_t > m_vecCommunityMapsQueue;
CUtlVector< PublishedFileId_t > m_vecUserPublishedMaps;
void AddCommunityMap( PublishedFileId_t nMapID, uint32 nSubscribeTime );
void AddQuickPlayMap( PublishedFileId_t nMapID );
// This decides what the next quickplay map ID will be based on the passed in map ID
PublishedFileId_t DetermineNextQuickPlayMapID( PublishedFileId_t nCurrentMap ) const;
int m_nTotalSubscriptionsLoaded; // Number of subscriptions we've received from the Steam server. This may not be the total number available, meaning we need to requery.
bool m_bReceivedQueueBaseline; // Whether or not we've heard back successfully from Steam on our queue status
float m_flQueueBaselineRequestTime; // Time that the baseline was requested from the GC
bool m_bQueueReady; // We have all our information from Steam about our queue now
bool m_bReceivedUserPublishedMapsBaseline; // Whether or not we've received a baseline back from Steam on our published files
float m_flUserPublishedMapsBaselineRequestTime; // Time that the baseline was requested from the GC
int m_nNumCommunityMapsPlayedThisSession; // How many maps (in sequence) the player has played through this session
PublishedFileId_t m_nNextFileID;
//
// Queue history
//
#if !defined( _GAMECONSOLE )
CCallResult<CBaseModPanel, RemoteStorageEnumeratePublishedFilesByUserActionResult_t> m_callbackEnumeratePublishedFilesByUserAction;
void Steam_OnEnumeratePublishedFilesByUserAction( RemoteStorageEnumeratePublishedFilesByUserActionResult_t *pResult, bool bError );
CCallResult<CBaseModPanel, RemoteStorageEnumerateWorkshopFilesResult_t> m_callbackEnumerateWorkshopFiles;
void Steam_OnEnumerateWorkshopFiles( RemoteStorageEnumerateWorkshopFilesResult_t*pResult, bool bError );
bool QueryForQuickPlayMaps_Internal( EWorkshopEnumerationType eEnumerationType );
EWorkshopEnumerationType m_eCurrentQuickPlayEnumerationType;
#endif // !_GAMECONSOLE
void RequestQueueHistory_Internal( void );
void AddQueueHistoryEntry( PublishedFileId_t nMapID, uint32 nLastPlayedTime, uint32 nCompletionTime );
CUtlVector< PublishedFileId_t > m_vecQueueHistoryEntries; // All queue history entries we've retrieved
float m_flQueueHistoryBaselineRequestTime;// Time that the baseline was requested from the GC
bool m_bReceivedQueueHistoryBaseline; // Whether or not we've heard back successfully from Steam on our queue history entries
int m_nTotalQueueHistoryEntriesLoaded; // Number of queue history entries we've received from the Steam server. This may not be the total number available, meaning we need to requery.
bool m_bQueueHistoryReady;
//
// UGC Request Manager
//
bool m_bUGCRequestsPaused;
//
// Quick play queue
//
ECommunityMapQueueMode m_eCommunityMapQueueMode;
CUtlVector< PublishedFileId_t > m_vecQuickPlayMaps;
int32 m_nTotalQuickPlayEntriesLoaded;
bool m_bReceivedQuickPlayBaseline;
float m_flQuickPlayBaselineRequestTime;
bool m_bQuickPlayQueueReady;
bool m_bQuickPlayQueueError;
#endif // !NO_STEAM
bool m_bSetup;
int m_nStartupFrames;
BIKMaterial_t m_BIKHandle;
float m_flU0, m_flV0, m_flU1, m_flV1;
float m_flMovieFadeInTime; // Time to be fully faded in
int m_nMoviePlaybackWidth;
int m_nMoviePlaybackHeight;
bool m_bMovieFailed;
bool m_bMovieLetterbox;
static CBaseModPanel* m_CFactoryBasePanel;
vgui::HScheme m_UIScheme;
vgui::HFont m_hDefaultFont;
vgui::HFont m_hSteamCloudFont;
vgui::DHANDLE< CBaseModFrame > m_Frames[WT_WINDOW_COUNT];
vgui::DHANDLE< CBaseModFooterPanel > m_FooterPanel;
vgui::DHANDLE< COptionsDialog > m_hOptionsDialog; // standalone options dialog - PC only
vgui::DHANDLE< CBaseModTransitionPanel > m_pTransitionPanel;
WINDOW_TYPE m_ActiveWindow[WPRI_COUNT];
int m_lastActiveUserId;
float m_flFadeinDelayAfterOverlay;
bool m_bHideAndFadeinLater;
float m_flOverlayFadeOutTime;
float m_flMusicFadeInTime;
bool m_bAllowMovie;
int m_iStartupImageID;
int m_iBackgroundImageID;
int m_iFadeOutOverlayImageID;
int m_DelayActivation;
int m_ExitingFrameCount;
bool m_LevelLoading;
bool m_bWarmRestartMode;
bool m_bClosingAllWindows;
float m_flBlurScale;
float m_flLastBlurTime;
CUtlString m_BackgroundMusicString;
int m_nBackgroundMusicGUID;
bool m_bFadeMusicUp;
int m_iProductImageID;
int m_iAltProductImageID;
int m_nProductImageX;
int m_nProductImageY;
int m_nProductImageWide;
int m_nProductImageTall;
int m_iCloudImageID[2]; // 0 = downloading, 1 = uploading
int m_iCloudPosition[4];
int m_iCloudProgressPosition[4];
int m_iCloudTextPosition[2];
Color m_clrCloudRemaining, m_clrCloudDone, m_clrCloudDoneFade;
Color m_clrSteamCloudText;
int m_nCurrentActPresentation;
float m_flAttractDemoTimeout;
CUtlString m_LastLoadedLevelName;
vgui::IImage *m_pAvatarImage;
XUID m_xuidAvatarImage;
CUtlString m_PartnerNameString;
bool m_bMoveToCommunityMapQueue;
bool m_bMoveToEditorMainMenu;
int m_nActivationCount;
bool m_bForceUseAlternateTileSet;
CUtlVector< int > m_CommonImages;
};
};
#endif

View File

@@ -0,0 +1,22 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef __BASEMOD360UI_H__
#define __BASEMOD360UI_H__
#include "basemodpanel.h"
#include "basemodframe.h"
#include "UIGameData.h"
#include "GameUI_Interface.h"
#include "const.h"
#ifndef _CERT
extern int UI_IsDebug();
#else
# define UI_IsDebug() 0
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
#ifndef __GAMEMODES_H__
#define __GAMEMODES_H__
#include "basemodui.h"
#include "vhybridbutton.h"
struct GameModeInfo_t
{
CUtlString m_NameId;
CUtlString m_NameText;
CUtlString m_CommandText;
CUtlString m_TitleText;
CUtlString m_HintText;
CUtlString m_HintTextDisabled;
int m_nImageId;
bool m_bEnabled;
BaseModUI::BaseModHybridButton *m_pHybridButton;
};
class GameModes : public vgui::Button
{
public:
DECLARE_CLASS_SIMPLE( GameModes, vgui::Button );
GameModes( vgui::Panel *pParent, const char *pName );
virtual ~GameModes();
virtual void PaintBackground( void );
virtual void ApplySettings( KeyValues *pInResourceData );
virtual void NavigateTo();
virtual void NavigateFrom();
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnCommand( const char *command );
virtual void OnMousePressed( vgui::MouseCode code );
virtual void OnKeyCodePressed( vgui::KeyCode code );
bool ScrollLeft();
bool ScrollRight( int nCount = 0 );
void SetEnabled( const char *pNameId, bool bEnabled );
bool SetActive( const char *pNameId, bool bForce );
bool GetLastActiveNameId( char *pOutBuffer, int nOutBufferSize );
bool IsScrollBusy();
int GetNumGameInfos();
BaseModUI::BaseModHybridButton *GetHybridButton( int nIndex );
private:
void SetActiveGameMode( int nActive, bool bKeepFocus );
int NameIdToModeInfo( const char *pNameId );
int DrawColoredText( vgui::HFont hFont, int x, int y, Color color, const char *pAnsiText, float alphaScale = 1.0f );
int DrawSmearBackgroundFade( int x, int y, int wide, int tall );
// the active pic
int m_nPicOffsetX;
int m_nPicWidth;
int m_nPicHeight;
// the button and hint underneath the active pic
int m_nMenuTitleX;
int m_nMenuTitleY;
int m_nMenuTitleWide;
int m_nMenuTitleTall;
int m_nMenuTitleActualTall;
// the sub pics to the right of the active pic
int m_nSubPics;
int m_nSubPicGap;
int m_nSubPicOffsetX;
int m_nSubPicOffsetY;
int m_nSubPicWidth;
int m_nSubPicHeight;
int m_nNameFontHeight;
vgui::HFont m_hNameFont;
int m_nSubPicX;
int m_nSubPicY;
// arrows
int m_nArrowWidth;
int m_nArrowHeight;
int m_nArrowOffsetY;
int m_nLeftArrowX;
int m_nLeftArrowY;
int m_nRightArrowX;
int m_nRightArrowY;
int m_nRightArrowOffsetX;
int m_nActive;
float m_startScrollTime;
bool m_bLeftScroll;
bool m_bHideLabels;
int m_nScrollMultipleCount;
int m_nBorderImageId;
int m_nTopBorderImageId;
int m_nBottomBorderImageId;
int m_nLeftArrowId;
int m_nRightArrowId;
Color m_smearColor;
CUtlVector< GameModeInfo_t > m_GameModeInfos;
};
#endif

View File

@@ -0,0 +1,962 @@
//========= Copyright <20> 1996-2011, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "basemodui.h"
#include "steamcloudsync.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
#include "filesystem.h"
#include "matchmaking/portal2/imatchext_portal2.h"
#include "memdbgon.h"
#ifdef GAME_STEAM_CLOUD_SYNC_SUPPORTED
ConVar ui_steam_cloud_enabled( "ui_steam_cloud_enabled", "1", FCVAR_DEVELOPMENTONLY );
ConVar ui_steam_cloud_start_delay( "ui_steam_cloud_start_delay", "1.3", FCVAR_DEVELOPMENTONLY );
ConVar ui_steam_cloud_maxcount( "ui_steam_cloud_maxcount", "7", FCVAR_DEVELOPMENTONLY );
#define CloudMsg( ... ) Msg( "[GAME STEAM CLOUD] " __VA_ARGS__ )
#ifdef _PS3
#define CloudTimePrintf "%016llx.sav"
#else
#error
#endif
#define CloudHddName( sPrefix, sName ) CFmtStr( "%s%s/steam/remote/%s", sPrefix, g_pPS3PathInfo->SystemCachePath(), sName )
enum BackOffTimeX_t
{
BACK_OFF_SUCCESS = 1,
BACK_OFF_CBCK_FAIL = 3,
BACK_OFF_LIST_FAIL = 10,
};
class CGameSteamCloudSync : public IGameSteamCloudSync
{
public:
CGameSteamCloudSync() :
m_flTimeStamp( 0.0f ),
m_CallbackOnServersConnected( this, &CGameSteamCloudSync::Steam_OnServersConnected ),
m_CallbackOnServersDisconnected( this, &CGameSteamCloudSync::Steam_OnServersDisconnected ),
m_bLoggedOn( false ),
m_ePhase( PHASE_BOOT ),
m_idxCloudWorkItem( 0 ),
m_uiSaveContainerVersion( 0 ),
m_numErrorPasses( 0 ),
m_flRandomErrorFactor( 1.0f )
{
m_gscp.m_numSaveGamesToSync = 3;
}
public:
virtual void Sync( Sync_t eSyncReason = SYNC_DEFAULT );
virtual void AbortAll();
virtual void RunFrame();
virtual bool IsSyncInProgress( GameSteamCloudSyncInfo_t *pGSCSI );
virtual void GetPreferences( GameSteamCloudPreferences_t &gscp );
virtual void OnEvent( KeyValues *pEvent );
virtual bool IsFileInCloud( char const *szInternalName );
protected:
STEAM_CALLBACK( CGameSteamCloudSync, Steam_OnServersConnected, SteamServersConnected_t, m_CallbackOnServersConnected );
STEAM_CALLBACK( CGameSteamCloudSync, Steam_OnServersDisconnected, SteamServersDisconnected_t, m_CallbackOnServersDisconnected );
protected:
bool CanStartNewRequest( bool bServerList = false );
void RequestCloudListFromCloudServer();
void UpdateSteamCloudTOC();
void ReconcileSteamCloudAndSaveContainer();
void PrepareWorkList();
void NoteFileSyncedToCloudHdd( time_t tFile );
void SetNumSaveGamesToSync( int numSaveGames );
void AbortImpl( bool bSteamServersDisconnected );
protected:
enum CloudSyncPhase_t
{
PHASE_BOOT,
PHASE_LIST_SERVER,
PHASE_AWAITING_SERVER_LIST,
PHASE_AWAITING_VALIDATION,
PHASE_WORK,
PHASE_AWAITING_WORK_CALLBACK,
PHASE_NEXT_WORK_ITEM,
PHASE_IDLE
};
CloudSyncPhase_t m_ePhase;
int m_numErrorPasses;
float m_flRandomErrorFactor;
uint32 m_uiSaveContainerVersion;
//////////////////////////////////////////////////////////////////////////
protected:
STEAM_CALLBACK_MANUAL( CGameSteamCloudSync, Steam_OnRemoteStorageAppSyncStatusCheck, RemoteStorageAppSyncStatusCheck_t, m_CallbackOnRemoteStorageAppSyncStatusCheck );
STEAM_CALLBACK_MANUAL( CGameSteamCloudSync, Steam_OnRemoteStorageAppSyncedClient, RemoteStorageAppSyncedClient_t, m_CallbackOnRemoteStorageAppSyncedClient );
STEAM_CALLBACK_MANUAL( CGameSteamCloudSync, Steam_OnRemoteStorageAppSyncedServer, RemoteStorageAppSyncedServer_t, m_CallbackOnRemoteStorageAppSyncedServer );
protected:
void RunFrame_DELETE_FROM_CONTAINER();
void RunFrame_EXTRACT_FROM_CONTAINER();
void RunFrame_STORE_INTO_CONTAINER();
//////////////////////////////////////////////////////////////////////////
protected:
float m_flTimeStamp;
bool m_bLoggedOn;
GameSteamCloudPreferences_t m_gscp, m_gscpInternal;
CPS3SaveRestoreAsyncStatus m_ps3saveStatus;
public:
struct CloudFile_t
{
char m_chName[32];
char m_chSave[32];
time_t m_timeModification;
bool m_bInCloud;
bool m_bOnHdd;
bool m_bInSave;
bool m_bCloudSave;
};
enum CloudWorkType_t
{
DELETE_FROM_CONTAINER,
DELETE_FROM_HDD,
DELETE_FROM_CLOUD,
DOWNLOAD_FROM_CLOUD,
EXTRACT_FROM_CONTAINER,
UPLOAD_INTO_CLOUD,
STORE_INTO_CONTAINER,
};
enum CloudWorkStateFlags_t
{
WORK_DEFAULT = 0,
WORK_DEPENDS_ON_PREV = ( 1 << 0 ),
WORK_ABORT_ALL_ON_FAIL = ( 1 << 1 ),
WORK_SUCCEEDED = ( 1 << 2 ),
WORK_FAILED = ( 1 << 3 ),
};
struct CloudWorkItem_t
{
CloudWorkType_t m_eWork;
int m_idxCloudFile;
uint32 m_eStateFlags;
int m_iProgress;
};
CUtlVector< CloudFile_t > m_arrCloudInfo;
CUtlVector< time_t > m_arrSyncedToHdd;
CUtlVector< CloudWorkItem_t > m_arrCloudWorkItems;
int m_idxCloudWorkItem;
};
static CGameSteamCloudSync g_GameSteamCloudSync;
IGameSteamCloudSync *g_pGameSteamCloudSync = &g_GameSteamCloudSync;
//////////////////////////////////////////////////////////////////////////
bool CGameSteamCloudSync::CanStartNewRequest( bool bServerList )
{
float flTimeout = ui_steam_cloud_start_delay.GetFloat();
if ( bServerList && ( m_numErrorPasses > 0 ) )
{
flTimeout *= (1+m_numErrorPasses)*3;
if ( m_flRandomErrorFactor == 1.0f )
m_flRandomErrorFactor = RandomFloat( 0.99f, 1.3f );
flTimeout *= m_flRandomErrorFactor;
}
if ( Plat_FloatTime() - m_flTimeStamp < flTimeout )
return false;
if ( !m_bLoggedOn ||
engine->IsDrawingLoadingImage() || engine->IsInGame() ||
ps3saveuiapi->IsSaveUtilBusy() )
{
m_flTimeStamp = Plat_FloatTime();
if ( bServerList )
m_numErrorPasses = 0;
return false;
}
if ( bServerList )
m_flRandomErrorFactor = 1.0f;
return true;
}
void CGameSteamCloudSync::Sync( Sync_t eSyncReason )
{
switch ( m_ePhase )
{
case PHASE_BOOT:
if ( eSyncReason != SYNC_GAMEBOOTREADY )
return;
if ( !steamapicontext || !steamapicontext->SteamRemoteStorage() )
{
CloudMsg( "GAMEBOOTREADY, SteamRemoteStorage interface missing, CLOUD DISABLED!\n" );
return;
}
else
{
// Need to update the value right away here, game profile not logged in yet
int32 iValue = 0;
steamapicontext->SteamUserStats()->GetStat( "PS3.CFG.sys.cloud_saves", &iValue );
SetNumSaveGamesToSync( iValue );
}
CloudMsg( "GAMEBOOTREADY, activating...\n" );
g_pFullFileSystem->CreateDirHierarchy( CloudHddName( "", "" ) );
m_ePhase = PHASE_LIST_SERVER;
m_flTimeStamp = Plat_FloatTime(); // let initialization happen before we do cloud work
return;
}
}
void CGameSteamCloudSync::AbortAll()
{
CloudMsg( "ABORTALL requested in phase %d @%.3f...\n", m_ePhase, Plat_FloatTime() );
AbortImpl( false );
}
bool CGameSteamCloudSync::IsSyncInProgress( GameSteamCloudSyncInfo_t *pGSCSI )
{
static GameSteamCloudSyncInfo_t gscsi;
if ( !pGSCSI )
pGSCSI = &gscsi;
switch ( m_ePhase )
{
case PHASE_LIST_SERVER:
if ( m_bLoggedOn )
{
pGSCSI->m_bUploadingToCloud = gscsi.m_bUploadingToCloud;
pGSCSI->m_flProgress = 0.0f;
return true;
}
else
{
return false;
}
case PHASE_AWAITING_SERVER_LIST:
pGSCSI->m_bUploadingToCloud = gscsi.m_bUploadingToCloud;
pGSCSI->m_flProgress = 0.1f;
return true;
case PHASE_AWAITING_VALIDATION:
pGSCSI->m_bUploadingToCloud = gscsi.m_bUploadingToCloud;
pGSCSI->m_flProgress = 0.98f;
return true;
case PHASE_WORK:
case PHASE_AWAITING_WORK_CALLBACK:
case PHASE_NEXT_WORK_ITEM:
// 0.1 - 1.0f distributed among m_arrCloudWorkItems.Count()
pGSCSI->m_flProgress = 0.1f + ( MAX( m_idxCloudWorkItem + 1, 1 ) ) * 1.0f /( m_arrCloudWorkItems.Count() + 1 );
pGSCSI->m_flProgress = MIN( pGSCSI->m_flProgress, 0.98f );
if ( ( m_idxCloudWorkItem >= 0 ) && ( m_idxCloudWorkItem < m_arrCloudWorkItems.Count() ) )
{
switch ( m_arrCloudWorkItems[m_idxCloudWorkItem].m_eWork )
{
case DELETE_FROM_CONTAINER:
case STORE_INTO_CONTAINER:
case DOWNLOAD_FROM_CLOUD:
pGSCSI->m_bUploadingToCloud = false;
break;
case DELETE_FROM_CLOUD:
case EXTRACT_FROM_CONTAINER:
case UPLOAD_INTO_CLOUD:
pGSCSI->m_bUploadingToCloud = true;
break;
default:
pGSCSI->m_bUploadingToCloud = gscsi.m_bUploadingToCloud;
break;
}
}
else
{
pGSCSI->m_bUploadingToCloud = gscsi.m_bUploadingToCloud;
}
gscsi.m_bUploadingToCloud = pGSCSI->m_bUploadingToCloud;
return true;
}
return false;
}
void CGameSteamCloudSync::GetPreferences( GameSteamCloudPreferences_t &gscp )
{
gscp = m_gscp;
}
void CGameSteamCloudSync::OnEvent( KeyValues *pEvent )
{
char const *szEvent = pEvent->GetName();
if ( !Q_stricmp( "OnProfileDataLoaded", szEvent ) )
{
// See what the current setting is in the profile
if ( !g_pMatchFramework )
return;
IPlayerLocal *pPlayer = g_pMatchFramework->GetMatchSystem()->GetPlayerManager()->GetLocalPlayer( XBX_GetPrimaryUserId() );
if ( !pPlayer )
return;
TitleData3 *pTitleData3 = ( TitleData3 * ) pPlayer->GetPlayerTitleData( TitleDataFieldsDescription_t::DB_TD3 );
SetNumSaveGamesToSync( pTitleData3->cvSystem.cloud_saves );
}
}
bool CGameSteamCloudSync::IsFileInCloud( char const *szInternalName )
{
for ( int k = 0; k < m_arrCloudInfo.Count(); ++ k )
{
if ( V_stricmp( m_arrCloudInfo[k].m_chSave, szInternalName ) )
continue;
return m_arrCloudInfo[k].m_bInCloud;
}
return false;
}
void CGameSteamCloudSync::Steam_OnServersConnected( SteamServersConnected_t *pParam )
{
if ( !steamapicontext->SteamUser()->BLoggedOn() )
return;
CSteamID sID = steamapicontext->SteamUser()->GetSteamID();
if ( !sID.IsValid() )
return;
if ( !sID.ConvertToUint64() )
return;
m_bLoggedOn = true;
m_flTimeStamp = Plat_FloatTime(); // let Steam do its work before we load it with cloud work
CloudMsg( "Steam servers connected @%.3f\n", Plat_FloatTime() );
static uint64 s_cryptokey = 0ull;
if ( !s_cryptokey )
{
CloudMsg( "Setting cloud crypto key to: 0x%016llX\n", sID.ConvertToUint64() );
ps3saveuiapi->SetCloudFileCryptoKey( s_cryptokey = sID.ConvertToUint64() );
}
else
{
#ifndef _CERT
if ( s_cryptokey != sID.ConvertToUint64() )
Error( "Steam Cloud Crypto Key mismatch!\n" );
#endif
}
}
void CGameSteamCloudSync::Steam_OnServersDisconnected( SteamServersDisconnected_t *pParam )
{
CloudMsg( "Steam servers disconnected (phase=%d) @%.3f\n", m_ePhase, Plat_FloatTime() );
m_bLoggedOn = false;
AbortImpl( true );
}
//////////////////////////////////////////////////////////////////////////
//
// Run every frame
//
void CGameSteamCloudSync::RunFrame()
{
switch ( m_ePhase )
{
case PHASE_LIST_SERVER:
if ( !CanStartNewRequest( true ) )
return;
if ( !ui_steam_cloud_enabled.GetBool() )
return;
RequestCloudListFromCloudServer();
m_ePhase = PHASE_AWAITING_SERVER_LIST;
return;
case PHASE_WORK:
if ( ( m_idxCloudWorkItem < 0 ) || ( m_idxCloudWorkItem >= m_arrCloudWorkItems.Count() ) )
{
CloudMsg( "WORK FINISHED, reconciling all storage...\n" );
m_flTimeStamp = Plat_FloatTime();
if ( m_numErrorPasses <= 0 )
{
RequestCloudListFromCloudServer();
m_ePhase = PHASE_AWAITING_VALIDATION;
}
else
{
m_ePhase = PHASE_LIST_SERVER;
}
return;
}
switch ( m_arrCloudWorkItems[m_idxCloudWorkItem].m_eWork )
{
case DELETE_FROM_CONTAINER:
RunFrame_DELETE_FROM_CONTAINER();
return;
case EXTRACT_FROM_CONTAINER:
RunFrame_EXTRACT_FROM_CONTAINER();
return;
case STORE_INTO_CONTAINER:
RunFrame_STORE_INTO_CONTAINER();
return;
case DELETE_FROM_HDD:
#ifndef _CERT
if ( ui_steam_cloud_enabled.GetInt() < 10 ) // in non-cert builds allow files to linger for inspection
#endif
g_pFullFileSystem->RemoveFile( CloudHddName( "", m_arrCloudInfo[ m_arrCloudWorkItems[m_idxCloudWorkItem].m_idxCloudFile ].m_chName ) );
m_arrCloudWorkItems[m_idxCloudWorkItem].m_eStateFlags |= WORK_SUCCEEDED;
m_arrSyncedToHdd.FindAndFastRemove( m_arrCloudInfo[ m_arrCloudWorkItems[m_idxCloudWorkItem].m_idxCloudFile ].m_timeModification );
m_ePhase = PHASE_NEXT_WORK_ITEM;
return;
case DELETE_FROM_CLOUD:
if ( !CanStartNewRequest() )
return;
m_CallbackOnRemoteStorageAppSyncedServer.Register( this, &CGameSteamCloudSync::Steam_OnRemoteStorageAppSyncedServer );
steamapicontext->SteamRemoteStorage()->ResetFileRequestState();
steamapicontext->SteamRemoteStorage()->FileForget( m_arrCloudInfo[ m_arrCloudWorkItems[m_idxCloudWorkItem].m_idxCloudFile ].m_chName );
m_arrCloudInfo[ m_arrCloudWorkItems[m_idxCloudWorkItem].m_idxCloudFile ].m_bInCloud = false;
steamapicontext->SteamRemoteStorage()->SynchronizeToServer();
m_ePhase = PHASE_AWAITING_WORK_CALLBACK;
return;
case DOWNLOAD_FROM_CLOUD:
if ( !CanStartNewRequest() )
return;
m_CallbackOnRemoteStorageAppSyncedClient.Register( this, &CGameSteamCloudSync::Steam_OnRemoteStorageAppSyncedClient );
steamapicontext->SteamRemoteStorage()->ResetFileRequestState();
steamapicontext->SteamRemoteStorage()->FileFetch( m_arrCloudInfo[ m_arrCloudWorkItems[m_idxCloudWorkItem].m_idxCloudFile ].m_chName );
steamapicontext->SteamRemoteStorage()->SynchronizeToClient();
m_ePhase = PHASE_AWAITING_WORK_CALLBACK;
return;
case UPLOAD_INTO_CLOUD:
if ( !CanStartNewRequest() )
return;
m_CallbackOnRemoteStorageAppSyncedServer.Register( this, &CGameSteamCloudSync::Steam_OnRemoteStorageAppSyncedServer );
steamapicontext->SteamRemoteStorage()->ResetFileRequestState();
steamapicontext->SteamRemoteStorage()->FilePersist( m_arrCloudInfo[ m_arrCloudWorkItems[m_idxCloudWorkItem].m_idxCloudFile ].m_chName );
steamapicontext->SteamRemoteStorage()->SetSyncPlatforms( m_arrCloudInfo[ m_arrCloudWorkItems[m_idxCloudWorkItem].m_idxCloudFile ].m_chName, k_ERemoteStoragePlatformPS3 );
m_arrCloudInfo[ m_arrCloudWorkItems[m_idxCloudWorkItem].m_idxCloudFile ].m_bInCloud = true;
steamapicontext->SteamRemoteStorage()->SynchronizeToServer();
m_ePhase = PHASE_AWAITING_WORK_CALLBACK;
return;
}
return;
case PHASE_NEXT_WORK_ITEM:
if ( !( m_arrCloudWorkItems[m_idxCloudWorkItem].m_eStateFlags & ( WORK_FAILED | WORK_SUCCEEDED ) ) )
{
CloudMsg( "WARNING: work%02d didn't set state, assuming failed!\n", m_idxCloudWorkItem + 1 );
m_arrCloudWorkItems[m_idxCloudWorkItem].m_eStateFlags |= WORK_FAILED;
}
if ( m_arrCloudWorkItems[m_idxCloudWorkItem].m_eStateFlags & WORK_FAILED )
{
if ( WORK_ABORT_ALL_ON_FAIL & m_arrCloudWorkItems[m_idxCloudWorkItem].m_eStateFlags )
{
CloudMsg( "WORK FAILED, ABORTING ALL WORKLOAD!\n" );
m_ePhase = PHASE_LIST_SERVER;
m_numErrorPasses += BACK_OFF_CBCK_FAIL;
return;
}
++ m_idxCloudWorkItem;
if ( ( m_idxCloudWorkItem < m_arrCloudWorkItems.Count() ) &&
( m_arrCloudWorkItems[m_idxCloudWorkItem].m_eStateFlags & WORK_DEPENDS_ON_PREV ) )
{
m_arrCloudWorkItems[m_idxCloudWorkItem].m_eStateFlags |= WORK_FAILED;
return;
}
}
else
{
++ m_idxCloudWorkItem;
}
if ( !m_bLoggedOn )
{
m_numErrorPasses = 0;
m_ePhase = PHASE_LIST_SERVER;
}
else
{
CloudMsg( " **** WORK[%02d]\n", m_idxCloudWorkItem + 1 );
m_ePhase = PHASE_WORK;
}
return;
case PHASE_IDLE:
if ( !ui_steam_cloud_enabled.GetBool() ||
( m_uiSaveContainerVersion != ps3saveuiapi->GetContainerModificationVersion() ) ||
( m_gscp.m_numSaveGamesToSync != m_gscpInternal.m_numSaveGamesToSync ) )
{
m_numErrorPasses = 0;
m_ePhase = PHASE_LIST_SERVER;
m_flTimeStamp = Plat_FloatTime();
}
return;
}
}
//////////////////////////////////////////////////////////////////////////
//
// Abort implementation
//
void CGameSteamCloudSync::AbortImpl( bool bSteamServersDisconnected )
{
if ( !bSteamServersDisconnected )
return;
m_CallbackOnRemoteStorageAppSyncStatusCheck.Unregister();
m_CallbackOnRemoteStorageAppSyncedClient.Unregister();
m_CallbackOnRemoteStorageAppSyncedServer.Unregister();
switch ( m_ePhase )
{
case PHASE_AWAITING_SERVER_LIST:
case PHASE_AWAITING_VALIDATION:
case PHASE_AWAITING_WORK_CALLBACK:
m_numErrorPasses = 0;
m_ePhase = PHASE_LIST_SERVER;
break;
}
}
//////////////////////////////////////////////////////////////////////////
//
// Get file list from server
//
void CGameSteamCloudSync::RequestCloudListFromCloudServer()
{
CloudMsg( "RequestCloudListFromCloudServer @%.3f...\n", Plat_FloatTime() );
m_CallbackOnRemoteStorageAppSyncStatusCheck.Register( this, &CGameSteamCloudSync::Steam_OnRemoteStorageAppSyncStatusCheck );
steamapicontext->SteamRemoteStorage()->ResetFileRequestState();
steamapicontext->SteamRemoteStorage()->GetFileListFromServer();
m_uiSaveContainerVersion = ps3saveuiapi->GetContainerModificationVersion();
}
//////////////////////////////////////////////////////////////////////////
//
// Awaiting RemoteStorageAppSyncStatusCheck_t
//
void CGameSteamCloudSync::Steam_OnRemoteStorageAppSyncStatusCheck( RemoteStorageAppSyncStatusCheck_t *pParam )
{
m_CallbackOnRemoteStorageAppSyncStatusCheck.Unregister();
CloudMsg( "Steam_OnRemoteStorageAppSyncStatusCheck( %d )\n", pParam->m_eResult );
if ( pParam->m_eResult == k_EResultOK )
{
m_numErrorPasses = MAX( 0, m_numErrorPasses - BACK_OFF_SUCCESS );
UpdateSteamCloudTOC();
if ( m_arrCloudWorkItems.Count() > 0 )
{
m_idxCloudWorkItem = 0;
m_ePhase = PHASE_WORK;
CloudMsg( " **** WORK[%02d]\n", m_idxCloudWorkItem + 1 );
}
else
{
g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( new KeyValues( "OnSteamCloudStorageUpdated", "reason", "idle" ) );
m_ePhase = PHASE_IDLE;
}
}
else
{
m_numErrorPasses += BACK_OFF_LIST_FAIL;
m_ePhase = PHASE_LIST_SERVER;
}
}
//////////////////////////////////////////////////////////////////////////
//
// Container operations
//
void CGameSteamCloudSync::RunFrame_DELETE_FROM_CONTAINER()
{
CloudWorkItem_t &cwi = m_arrCloudWorkItems[m_idxCloudWorkItem];
switch ( cwi.m_iProgress )
{
case 0:
if ( !CanStartNewRequest() )
return;
ps3saveuiapi->Delete( &m_ps3saveStatus, m_arrCloudInfo[cwi.m_idxCloudFile].m_chSave );
cwi.m_iProgress = 1;
return;
case 1:
if ( !m_ps3saveStatus.m_bDone )
return;
if ( m_ps3saveStatus.GetSonyReturnValue() < 0 )
{
CloudMsg( "DELETE_FROM_CONTAINER failed (error=%d) @%.3f...\n", m_ps3saveStatus.GetSonyReturnValue(), Plat_FloatTime() );
cwi.m_eStateFlags |= WORK_FAILED;
}
else
{
g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( new KeyValues( "OnSteamCloudStorageUpdated", "reason", "delete" ) );
m_arrCloudInfo[cwi.m_idxCloudFile].m_bInSave = false;
cwi.m_eStateFlags |= WORK_SUCCEEDED;
}
// fall through
default:
m_ePhase = PHASE_NEXT_WORK_ITEM;
return;
}
}
void CGameSteamCloudSync::RunFrame_EXTRACT_FROM_CONTAINER()
{
CloudWorkItem_t &cwi = m_arrCloudWorkItems[m_idxCloudWorkItem];
switch ( cwi.m_iProgress )
{
case 0:
if ( !CanStartNewRequest() )
return;
ps3saveuiapi->Load( &m_ps3saveStatus, m_arrCloudInfo[cwi.m_idxCloudFile].m_chSave,
CloudHddName( "@", m_arrCloudInfo[cwi.m_idxCloudFile].m_chName ) );
cwi.m_iProgress = 1;
return;
case 1:
if ( !m_ps3saveStatus.m_bDone )
return;
if ( m_ps3saveStatus.GetSonyReturnValue() < 0 )
{
CloudMsg( "EXTRACT_FROM_CONTAINER failed (error=%d) @%.3f...\n", m_ps3saveStatus.GetSonyReturnValue(), Plat_FloatTime() );
cwi.m_eStateFlags |= WORK_FAILED;
}
else
{
NoteFileSyncedToCloudHdd( m_arrCloudInfo[cwi.m_idxCloudFile].m_timeModification );
cwi.m_eStateFlags |= WORK_SUCCEEDED;
}
// fall through
default:
m_ePhase = PHASE_NEXT_WORK_ITEM;
return;
}
}
void CGameSteamCloudSync::RunFrame_STORE_INTO_CONTAINER()
{
CloudWorkItem_t &cwi = m_arrCloudWorkItems[m_idxCloudWorkItem];
switch ( cwi.m_iProgress )
{
case 0:
if ( !CanStartNewRequest() )
return;
ps3saveuiapi->WriteCloudFile( &m_ps3saveStatus, CloudHddName( "", m_arrCloudInfo[cwi.m_idxCloudFile].m_chName ),
m_gscpInternal.m_numSaveGamesToSync );
cwi.m_iProgress = 1;
return;
case 1:
if ( !m_ps3saveStatus.m_bDone )
return;
if ( m_ps3saveStatus.GetSonyReturnValue() < 0 )
{
CloudMsg( "STORE_INTO_CONTAINER failed (error=%d) @%.3f...\n", m_ps3saveStatus.GetSonyReturnValue(), Plat_FloatTime() );
cwi.m_eStateFlags |= WORK_FAILED;
}
else
{
g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( new KeyValues( "OnSteamCloudStorageUpdated", "reason", "store" ) );
m_arrCloudInfo[cwi.m_idxCloudFile].m_bInSave = true;
cwi.m_eStateFlags |= WORK_SUCCEEDED;
}
// fall through
default:
m_ePhase = PHASE_NEXT_WORK_ITEM;
return;
}
}
//////////////////////////////////////////////////////////////////////////
//
// Awaiting RemoteStorageAppSyncedClient_t
//
void CGameSteamCloudSync::Steam_OnRemoteStorageAppSyncedClient( RemoteStorageAppSyncedClient_t *pParam )
{
m_CallbackOnRemoteStorageAppSyncedClient.Unregister();
CloudMsg( "Steam_OnRemoteStorageAppSyncedClient( %d )\n", pParam->m_eResult );
CloudWorkItem_t &cwi = m_arrCloudWorkItems[m_idxCloudWorkItem];
if ( pParam->m_eResult == k_EResultOK )
{
NoteFileSyncedToCloudHdd( m_arrCloudInfo[cwi.m_idxCloudFile].m_timeModification );
cwi.m_eStateFlags |= WORK_SUCCEEDED;
}
else
{
m_numErrorPasses += BACK_OFF_CBCK_FAIL;
cwi.m_eStateFlags |= WORK_FAILED;
}
m_ePhase = PHASE_NEXT_WORK_ITEM;
}
//////////////////////////////////////////////////////////////////////////
//
// Awaiting RemoteStorageAppSyncedServer_t
//
void CGameSteamCloudSync::Steam_OnRemoteStorageAppSyncedServer( RemoteStorageAppSyncedServer_t *pParam )
{
m_CallbackOnRemoteStorageAppSyncedServer.Unregister();
CloudMsg( "Steam_OnRemoteStorageAppSyncedServer( %d )\n", pParam->m_eResult );
CloudWorkItem_t &cwi = m_arrCloudWorkItems[m_idxCloudWorkItem];
if ( pParam->m_eResult == k_EResultOK )
{
cwi.m_eStateFlags |= WORK_SUCCEEDED;
g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( new KeyValues( "OnSteamCloudStorageUpdated", "reason", "cloud" ) );
}
else
{
m_numErrorPasses += BACK_OFF_CBCK_FAIL;
cwi.m_eStateFlags |= WORK_FAILED;
}
m_ePhase = PHASE_NEXT_WORK_ITEM;
}
//////////////////////////////////////////////////////////////////////////
static int SortSteamCloudInfos( CGameSteamCloudSync::CloudFile_t const *a, CGameSteamCloudSync::CloudFile_t const *b )
{
if ( a->m_timeModification != b->m_timeModification )
return ( a->m_timeModification > b->m_timeModification ) ? -1 : 1;
else
return 0;
}
void CGameSteamCloudSync::UpdateSteamCloudTOC()
{
ISteamRemoteStorage *rs = steamapicontext->SteamRemoteStorage();
m_arrCloudInfo.RemoveAll();
CUtlVector< IPS3SaveRestoreToUI::PS3SaveGameInfo_t > arrSaveContainerFiles;
ps3saveuiapi->GetFileInfoSync( arrSaveContainerFiles, true );
int32 numFiles = rs->GetFileCount();
for ( int k = 0; k < numFiles; ++ k )
{
int32 nFileSize = 0;
char const *szFileName = rs->GetFileNameAndSize( k, &nFileSize );
if ( !szFileName || !*szFileName )
continue;
ERemoteStoragePlatform ePlatforms = rs->GetSyncPlatforms( szFileName );
bool bPS3platform = ( ePlatforms == k_ERemoteStoragePlatformPS3 );
CloudMsg( "%02d/%02d: %s = %d bytes (%s)\n", k + 1, numFiles, szFileName, nFileSize, bPS3platform?"ps3":"ignored" );
if ( !bPS3platform )
continue;
time_t tNameId;
if ( 1 != sscanf( szFileName, CloudTimePrintf, &tNameId ) )
continue;
// Reconcile cloud information
CloudFile_t cf = {0};
V_strncpy( cf.m_chName, szFileName, sizeof( cf.m_chName ) );
cf.m_timeModification = tNameId;
cf.m_bInCloud = true;
m_arrCloudInfo.AddToTail( cf );
}
CloudMsg( "Steam cloud TOC updated\n" );
ReconcileSteamCloudAndSaveContainer();
}
void CGameSteamCloudSync::ReconcileSteamCloudAndSaveContainer()
{
CUtlVector< IPS3SaveRestoreToUI::PS3SaveGameInfo_t > arrSaveContainerFiles;
ps3saveuiapi->GetFileInfoSync( arrSaveContainerFiles, true );
for ( int icf = 0; icf < m_arrCloudInfo.Count(); ++ icf )
{
CloudFile_t &cf = m_arrCloudInfo[icf];
for ( int k = 0; k < arrSaveContainerFiles.Count(); ++ k )
{
if ( cf.m_timeModification == arrSaveContainerFiles[k].m_nFileTime )
{
cf.m_bInSave = true;
V_strncpy( cf.m_chSave, arrSaveContainerFiles[k].m_InternalName.Get(), sizeof( cf.m_chSave ) );
cf.m_bCloudSave = V_stristr( arrSaveContainerFiles[k].m_Filename.Get(), "cloudsave" );
break;
}
}
cf.m_bOnHdd = ( m_arrSyncedToHdd.Find( cf.m_timeModification ) != m_arrSyncedToHdd.InvalidIndex() );
}
for ( int k = 0; k < arrSaveContainerFiles.Count(); ++ k )
{
bool bClouded = false;
for ( int icf = 0; icf < m_arrCloudInfo.Count(); ++ icf )
{
if ( m_arrCloudInfo[icf].m_timeModification == arrSaveContainerFiles[k].m_nFileTime )
{
bClouded = true;
break;
}
}
if ( bClouded )
continue;
CloudFile_t cf = {0};
V_snprintf( cf.m_chName, sizeof( cf.m_chName ), CloudTimePrintf, arrSaveContainerFiles[k].m_nFileTime );
V_strncpy( cf.m_chSave, arrSaveContainerFiles[k].m_InternalName.Get(), sizeof( cf.m_chSave ) );
cf.m_timeModification = arrSaveContainerFiles[k].m_nFileTime;
cf.m_bInSave = true;
cf.m_bCloudSave = V_stristr( arrSaveContainerFiles[k].m_Filename.Get(), "cloudsave" );
cf.m_bOnHdd = ( m_arrSyncedToHdd.Find( cf.m_timeModification ) != m_arrSyncedToHdd.InvalidIndex() );
m_arrCloudInfo.AddToTail( cf );
}
m_arrCloudInfo.Sort( SortSteamCloudInfos );
m_gscpInternal = m_gscp;
CloudMsg( "---CLOUD+LOCAL---\n" );
CloudMsg( "Cloud setting: numSaves = %d\n", m_gscpInternal.m_numSaveGamesToSync );
for ( int k = 0; k < m_arrCloudInfo.Count(); ++ k )
{
CloudMsg( " %02d/%02d: %016llX%s%s%s [^%s] [*%s]\n",
k+1, m_arrCloudInfo.Count(),
m_arrCloudInfo[k].m_timeModification,
m_arrCloudInfo[k].m_bInCloud ? " cloud" : "",
m_arrCloudInfo[k].m_bInSave ? " local" : "",
m_arrCloudInfo[k].m_bOnHdd ? " hdd" : "",
m_arrCloudInfo[k].m_chName,
m_arrCloudInfo[k].m_chSave );
}
for ( int k = m_arrCloudInfo.Count(); k --> m_gscp.m_numSaveGamesToSync; )
{
if ( m_arrCloudInfo[k].m_bInCloud )
continue;
if ( m_arrCloudInfo[k].m_bCloudSave )
continue;
m_arrCloudInfo.Remove( k );
}
CloudMsg( "-----------------\n" );
PrepareWorkList();
}
void CGameSteamCloudSync::PrepareWorkList()
{
m_arrCloudWorkItems.RemoveAll();
CloudMsg( "-------- PREPARING WORK LIST -----------\n" );
// Delete items from save container
for ( int k = m_arrCloudInfo.Count(); k --> m_gscpInternal.m_numSaveGamesToSync; )
{
if ( m_arrCloudInfo[k].m_bCloudSave )
{
CloudMsg( " %02d. Delete from container '%02d:%s'\n", m_arrCloudWorkItems.Count() + 1, k + 1, m_arrCloudInfo[k].m_chSave );
CloudWorkItem_t cwi = { DELETE_FROM_CONTAINER, k, WORK_ABORT_ALL_ON_FAIL };
m_arrCloudWorkItems.AddToTail( cwi );
}
}
// Download from cloud and store into container
for ( int k = 0; ( k < m_arrCloudInfo.Count() ) && ( k < m_gscpInternal.m_numSaveGamesToSync ); ++ k )
{
if ( !m_arrCloudInfo[k].m_bInSave )
{
uint32 uiFlags = 0;
if ( !m_arrCloudInfo[k].m_bOnHdd )
{
CloudMsg( " %02d. Download from cloud to hdd '%02d:%s'\n", m_arrCloudWorkItems.Count() + 1, k + 1, m_arrCloudInfo[k].m_chName );
CloudWorkItem_t cwi = { DOWNLOAD_FROM_CLOUD, k };
m_arrCloudWorkItems.AddToTail( cwi );
uiFlags |= WORK_DEPENDS_ON_PREV;
}
{
CloudMsg( " %02d. Store into container '%02d:%s'\n", m_arrCloudWorkItems.Count() + 1, k + 1, m_arrCloudInfo[k].m_chName );
CloudWorkItem_t cwi = { STORE_INTO_CONTAINER, k, uiFlags };
m_arrCloudWorkItems.AddToTail( cwi );
}
{
CloudMsg( " %02d. Delete from hdd cache '%02d:%s'\n", m_arrCloudWorkItems.Count() + 1, k + 1, m_arrCloudInfo[k].m_chName );
CloudWorkItem_t cwi = { DELETE_FROM_HDD, k, WORK_DEPENDS_ON_PREV };
m_arrCloudWorkItems.AddToTail( cwi );
}
}
}
// Delete aged cloud items
for ( int k = m_arrCloudInfo.Count(); k --> m_gscpInternal.m_numSaveGamesToSync; )
{
if ( m_arrCloudInfo[k].m_bInCloud )
{
CloudMsg( " %02d. Delete from cloud '%02d:%s'\n", m_arrCloudWorkItems.Count() + 1, k + 1, m_arrCloudInfo[k].m_chName );
CloudWorkItem_t cwi = { DELETE_FROM_CLOUD, k, WORK_ABORT_ALL_ON_FAIL };
m_arrCloudWorkItems.AddToTail( cwi );
}
}
// Extract from container and upload into cloud
for ( int k = 0; ( k < m_arrCloudInfo.Count() ) && ( k < m_gscpInternal.m_numSaveGamesToSync ); ++ k )
{
if ( !m_arrCloudInfo[k].m_bInCloud )
{
uint32 uiFlags = 0;
if ( !m_arrCloudInfo[k].m_bOnHdd )
{
CloudMsg( " %02d. Extract from container to hdd '%02d:%s'\n", m_arrCloudWorkItems.Count() + 1, k + 1, m_arrCloudInfo[k].m_chSave );
CloudWorkItem_t cwi = { EXTRACT_FROM_CONTAINER, k };
m_arrCloudWorkItems.AddToTail( cwi );
uiFlags |= WORK_DEPENDS_ON_PREV;
}
{
CloudMsg( " %02d. Upload into cloud '%02d:%s'\n", m_arrCloudWorkItems.Count() + 1, k + 1, m_arrCloudInfo[k].m_chSave );
CloudWorkItem_t cwi = { UPLOAD_INTO_CLOUD, k, uiFlags };
m_arrCloudWorkItems.AddToTail( cwi );
}
{
CloudMsg( " %02d. Delete from hdd cache '%02d:%s'\n", m_arrCloudWorkItems.Count() + 1, k + 1, m_arrCloudInfo[k].m_chName );
CloudWorkItem_t cwi = { DELETE_FROM_HDD, k, WORK_DEPENDS_ON_PREV };
m_arrCloudWorkItems.AddToTail( cwi );
}
}
}
CloudMsg( "-------- READY TO WORK -----------\n" );
}
void CGameSteamCloudSync::NoteFileSyncedToCloudHdd( time_t tFile )
{
m_arrSyncedToHdd.EnsureCapacity( ui_steam_cloud_maxcount.GetInt()*2 );
if ( m_arrSyncedToHdd.Count() >= ui_steam_cloud_maxcount.GetInt()*2 )
m_arrSyncedToHdd.SetCountNonDestructively( ui_steam_cloud_maxcount.GetInt()*2 - 1 );
m_arrSyncedToHdd.AddToHead( tFile );
}
void CGameSteamCloudSync::SetNumSaveGamesToSync( int numSaveGames )
{
m_gscp.m_numSaveGamesToSync = numSaveGames;
if ( !m_gscp.m_numSaveGamesToSync )
m_gscp.m_numSaveGamesToSync = 3;
else
-- m_gscp.m_numSaveGamesToSync;
m_gscp.m_numSaveGamesToSync = MAX( 0, m_gscp.m_numSaveGamesToSync );
m_gscp.m_numSaveGamesToSync = MIN( 7, m_gscp.m_numSaveGamesToSync );
}
#endif // GAME_STEAM_CLOUD_SYNC_SUPPORTED

View File

@@ -0,0 +1,51 @@
//========= Copyright <20> 1996-2011, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef __STEAMCLOUDSYNC_H__
#define __STEAMCLOUDSYNC_H__
struct GameSteamCloudSyncInfo_t
{
bool m_bUploadingToCloud;
wchar_t m_wszDescription[256];
float m_flProgress;
};
struct GameSteamCloudPreferences_t
{
uint8 m_numSaveGamesToSync;
};
class IGameSteamCloudSync
{
public:
enum Sync_t
{
SYNC_DEFAULT,
SYNC_GAMEBOOTREADY
};
public:
virtual void Sync( Sync_t eSyncReason = SYNC_DEFAULT ) = 0;
virtual void AbortAll() = 0;
virtual void RunFrame() = 0;
virtual bool IsSyncInProgress( GameSteamCloudSyncInfo_t *pGSCSI ) = 0;
virtual void GetPreferences( GameSteamCloudPreferences_t &gscp ) = 0;
virtual void OnEvent( KeyValues *pEvent ) = 0;
virtual bool IsFileInCloud( char const *szInternalName ) = 0;
};
#if defined( _PS3 ) && !defined( NO_STEAM )
#define GAME_STEAM_CLOUD_SYNC_SUPPORTED
extern IGameSteamCloudSync *g_pGameSteamCloudSync;
#else
#define g_pGameSteamCloudSync ( ( IGameSteamCloudSync * ) NULL )
#endif
#endif

View File

@@ -0,0 +1,21 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
#ifndef ISTEAMOVERLAYMGR_H
#define ISTEAMOVERLAYMGR_H
abstract_class ISteamOverlayManager
{
public:
virtual void Create( vgui::VPANEL parent ) = 0;
virtual void GameBootReady() = 0;
virtual void SetEnhancedOverlayInput( bool bEnable ) = 0;
virtual void Destroy( void ) = 0;
};
#ifdef _PS3
extern ISteamOverlayManager *g_pISteamOverlayMgr;
#else
#define g_pISteamOverlayMgr ( ( ISteamOverlayManager * ) 0 )
#endif
#endif // ISTEAMOVERLAYMGR_H

View File

@@ -0,0 +1,256 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
#include "cbase.h"
#include "isteamoverlaymgr.h"
#include <vgui_controls/Panel.h>
#include "view.h"
#include <vgui/IVGui.h>
#include "vguimatsurface/imatsystemsurface.h"
#include <vgui_controls/Controls.h>
#include <vgui/ISurface.h>
#include <vgui/IScheme.h>
#include <vgui/IPanel.h>
#include "materialsystem/imaterialsystemhardwareconfig.h"
#include "filesystem.h"
#include "../common/xbox/xboxstubs.h"
#include "steam/steam_api.h"
#include "cdll_int.h"
#include "eiface.h"
#include "matchmaking/imatchframework.h"
#include "inputsystem/iinputsystem.h"
#include "steam/steam_platform_ps3/isteamps3overlayrenderer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern ISteamPS3OverlayRenderHost *g_SteamOverlayPanel_RenderHostImplementation;
vgui::IScheme *g_SteamOverlayPanel_Scheme;
IMatSystemSurface *g_SteamOverlayPanel_Surface;
#ifndef NO_STEAM
static bool g_bRealEnhancedOverlayInputModeSetting = false;
static bool BCellPadDataHook( CellPadData &data )
{
if ( !SteamPS3OverlayRender() )
return false;
return SteamPS3OverlayRender()->BHandleCellPadData( data )
|| g_bRealEnhancedOverlayInputModeSetting;
}
static bool BCellPadNoDataHook()
{
if ( !SteamPS3OverlayRender() )
return false;
return SteamPS3OverlayRender()->BResetInputState();
}
#endif // NO_STEAM
class CSteamOverlayPanel : public vgui::Panel
{
DECLARE_CLASS_SIMPLE( CSteamOverlayPanel, vgui::Panel );
public:
CSteamOverlayPanel( vgui::VPANEL parent );
virtual ~CSteamOverlayPanel( void );
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
virtual void Paint() {}
virtual void PaintBackground();
protected:
bool m_bInitializedRenderInterface;
};
CSteamOverlayPanel::CSteamOverlayPanel( vgui::VPANEL parent ) : BaseClass( NULL, "SteamOverlayPanel" )
{
SetParent( parent );
SetVisible( true );
SetCursor( null );
int w, h;
materials->GetBackBufferDimensions( w, h );
SetPos( 0, 0 );
SetSize( w, h );
DevMsg( "CSteamOverlayPanel created (%d x %d)\n", w, h );
SetFgColor( Color( 0, 0, 0, 255 ) );
SetPaintBackgroundEnabled( true );
m_bInitializedRenderInterface = false;
}
CSteamOverlayPanel::~CSteamOverlayPanel()
{
m_bInitializedRenderInterface = false;
}
void CSteamOverlayPanel::ApplySchemeSettings(vgui::IScheme *pScheme)
{
g_SteamOverlayPanel_Scheme = pScheme;
BaseClass::ApplySchemeSettings(pScheme);
}
static bool g_bGameBootReadyForSteamOverlay = false;
static bool g_bEnhancedOverlayInputMode = false;
class CSteamOverlayMgr : public ISteamOverlayManager
{
public:
CSteamOverlayPanel *m_pPanel;
public:
CSteamOverlayMgr( void )
{
m_pPanel = NULL;
}
void Create( vgui::VPANEL parent )
{
m_pPanel = new CSteamOverlayPanel( parent );
}
void GameBootReady()
{
g_bGameBootReadyForSteamOverlay = true;
}
void SetEnhancedOverlayInput( bool bEnable )
{
g_bEnhancedOverlayInputMode = bEnable;
}
void Destroy( void )
{
if ( m_pPanel )
{
m_pPanel->SetParent( (vgui::Panel *)NULL );
delete m_pPanel;
m_pPanel = NULL;
}
}
};
static CSteamOverlayMgr g_SteamOverlayMgr;
ISteamOverlayManager *g_pISteamOverlayMgr = &g_SteamOverlayMgr;
void CSteamOverlayPanel::PaintBackground()
{
g_pMatSystemSurface->SetClipRect( 0, 0, 10000, 10000 );
g_SteamOverlayPanel_Surface = g_pMatSystemSurface;
if ( !m_bInitializedRenderInterface && g_bGameBootReadyForSteamOverlay )
{
m_bInitializedRenderInterface = true;
int wide, tall;
materials->GetBackBufferDimensions( wide, tall );
#ifndef NO_STEAM
// Setup overlay render interface for PS3 Steam overlay
SteamPS3OverlayRender()->BHostInitialize( wide, tall, 60, g_SteamOverlayPanel_RenderHostImplementation, materials->PS3GetFontLibPtr() );
g_pInputSystem->SetPS3CellPadDataHook( &BCellPadDataHook );
g_pInputSystem->SetPS3CellPadNoDataHook( &BCellPadNoDataHook );
#endif
}
if ( m_bInitializedRenderInterface )
{
#ifndef NO_STEAM
if ( g_bRealEnhancedOverlayInputModeSetting != g_bEnhancedOverlayInputMode )
{
g_pInputSystem->ResetInputState();
g_bRealEnhancedOverlayInputModeSetting = g_bEnhancedOverlayInputMode;
}
if ( g_bRealEnhancedOverlayInputModeSetting )
{
g_pInputSystem->PollInputState();
}
SteamPS3OverlayRender()->Render();
#endif
}
}
class CSteamOverlayRenderHost : public ISteamPS3OverlayRenderHost
{
private:
CUtlMap< int32, int > m_mapSteamToVGUITextureIDs;
static void ConvertColorFromSRGBToGamma( Color &color )
{
color.SetColor(
clamp( static_cast< int >( .5f + 255.0f * LinearToGammaFullRange( SrgbGammaToLinear( color.r() * 1.0f/255.0f ) ) ), 0, 255 ),
clamp( static_cast< int >( .5f + 255.0f * LinearToGammaFullRange( SrgbGammaToLinear( color.g() * 1.0f/255.0f ) ) ), 0, 255 ),
clamp( static_cast< int >( .5f + 255.0f * LinearToGammaFullRange( SrgbGammaToLinear( color.b() * 1.0f/255.0f ) ) ), 0, 255 ),
color.a() );
}
public:
CSteamOverlayRenderHost()
{
m_mapSteamToVGUITextureIDs.SetLessFunc( DefLessFunc( int32 ) );
}
virtual void DrawTexturedRect( int x0, int y0, int x1, int y1, float u0, float v0, float u1, float v1, int32 iTextureID, DWORD colorStart, DWORD colorEnd, EOverlayGradientDirection eDirection )
{
unsigned short iMap = m_mapSteamToVGUITextureIDs.Find( iTextureID );
if ( iMap != m_mapSteamToVGUITextureIDs.InvalidIndex() )
{
Color colStart( STEAM_COLOR_RED( colorStart ), STEAM_COLOR_GREEN( colorStart ), STEAM_COLOR_BLUE( colorStart ), STEAM_COLOR_ALPHA( colorStart ) );
Color colEnd( STEAM_COLOR_RED( colorEnd ), STEAM_COLOR_GREEN( colorEnd ), STEAM_COLOR_BLUE( colorEnd ), STEAM_COLOR_ALPHA( colorEnd ) );
// The input colors are in sRGB space, but IMatSystemSurface's draw helpers are expecting the colors in gamma space (because they ultimately
// use the vertexlit_and_unlit_generic vertex shader (NOT unlit_generic, which is actually no longer used), which converts the vertex colors from gamma to linear).
ConvertColorFromSRGBToGamma( colStart );
ConvertColorFromSRGBToGamma( colEnd );
g_SteamOverlayPanel_Surface->DrawSetTexture( m_mapSteamToVGUITextureIDs[iMap] );
g_SteamOverlayPanel_Surface->DrawTexturedSubRectGradient( x0, y0, x1, y1, u0, v0, u1, v1, colStart, colEnd, eDirection == k_EOverlayGradientHorizontal ? true : false );
}
}
virtual void LoadOrUpdateTexture( int32 iTextureID, bool bIsFullTexture, int x0, int y0, uint32 uWidth, uint32 uHeight, int32 iBytes, char *pData )
{
if ( !bIsFullTexture )
{
unsigned short iMap = m_mapSteamToVGUITextureIDs.Find( iTextureID );
if ( iMap != m_mapSteamToVGUITextureIDs.InvalidIndex() )
{
g_SteamOverlayPanel_Surface->DrawSetSubTextureRGBA( m_mapSteamToVGUITextureIDs[iMap], x0, y0, (unsigned char*)pData, uWidth, uHeight );
}
}
else
{
int iVGUITexture = g_SteamOverlayPanel_Surface->CreateNewTextureID( true );
g_SteamOverlayPanel_Surface->DrawSetTextureRGBALinear( iVGUITexture, (unsigned char *)pData, uWidth, uHeight );
m_mapSteamToVGUITextureIDs.InsertOrReplace( iTextureID, iVGUITexture );
}
}
virtual void DeleteTexture( int32 iTextureID )
{
unsigned short iMap = m_mapSteamToVGUITextureIDs.Find( iTextureID );
if ( iMap != m_mapSteamToVGUITextureIDs.InvalidIndex() )
{
g_SteamOverlayPanel_Surface->DestroyTextureID( m_mapSteamToVGUITextureIDs[iMap] );
m_mapSteamToVGUITextureIDs.RemoveAt( iMap );
}
}
virtual void DeleteAllTextures()
{
FOR_EACH_MAP( m_mapSteamToVGUITextureIDs, iMap )
{
g_SteamOverlayPanel_Surface->DestroyTextureID( m_mapSteamToVGUITextureIDs[iMap] );
}
m_mapSteamToVGUITextureIDs.Purge();
}
};
static CSteamOverlayRenderHost g_SteamOverlayPanel_RenderHostInstance;
ISteamPS3OverlayRenderHost *g_SteamOverlayPanel_RenderHostImplementation = &g_SteamOverlayPanel_RenderHostInstance;

View File

@@ -0,0 +1,16 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
#ifndef SOUIRENDER_PCH_H
#define SOUIRENDER_PCH_H
#include "cbase.h"
#include "steam/steam_api.h"
#include "cdll_int.h"
#include "eiface.h"
#include "matchmaking/imatchframework.h"
#include "tier1/fmtstr.h"
#include "vgui/ILocalize.h"
#include "steam/steam_platform_ps3/isteamps3overlayrenderer.h"
#endif // SOUIRENDER_PCH_H

View File

@@ -0,0 +1,8 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
#ifndef SOUIRENDER_PCHEND_H
#define SOUIRENDER_PCHEND_H
#include "memdbgon.h"
#endif // SOUIRENDER_PCHEND_H

View File

@@ -0,0 +1,793 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "transitionpanel.h"
#include "vgui/IPanel.h"
#include "vgui/ISurface.h"
#include "vgui/ilocalize.h"
#include "vgui/iinput.h"
#include "ienginevgui.h"
#include "tier1/fmtstr.h"
#include "materialsystem/IMesh.h"
#include "shaderapi/ishaderapi.h"
#include "gameconsole.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace BaseModUI;
using namespace vgui;
ConVar ui_transition_debug( "ui_transition_debug", "0", FCVAR_DEVELOPMENTONLY, "" );
ConVar ui_transition_time( "ui_transition_time", IsGameConsole() ? "0.25" : "0.20", FCVAR_DEVELOPMENTONLY, "" );
ConVar ui_transition_delay( "ui_transition_delay", "0.3", FCVAR_DEVELOPMENTONLY, "" );
ConVar ui_transition_effect( "ui_transition_effect", "1", FCVAR_DEVELOPMENTONLY, "" );
#define TILE_NEAR_PLANE 1.0f
#define TILE_FAR_PLANE 257.0f
#define TILE_Z ( -128.0f )
#define GRID_WIDTH_WC ( 2.0f * -TILE_Z )
#define HALF_GRID_WIDTH_WC ( -TILE_Z )
CBaseModTransitionPanel::CBaseModTransitionPanel( const char *pPanelName ) :
BaseClass( NULL, pPanelName )
{
SetScheme( GAMEUI_BASEMODPANEL_SCHEME );
SetPostChildPaintEnabled( true );
m_pFromScreenRT = NULL;
m_pCurrentScreenRT = NULL;
// needs to start at some number >1
m_nFrameCount = 100;
m_nNumTransitions = 0;
m_bTransitionActive = false;
m_bAllowTransitions = false;
m_bQuietTransitions = false;
m_pFromScreenMaterial = materials->FindMaterial( "console/rt_background", TEXTURE_GROUP_OTHER, true );
m_pFromScreenMaterial->IncrementReferenceCount();
m_pFromScreenMaterial->GetMappingWidth();
m_pCurrentScreenMaterial = materials->FindMaterial( "console/rt_foreground", TEXTURE_GROUP_OTHER, true );
m_pCurrentScreenMaterial->IncrementReferenceCount();
m_pCurrentScreenMaterial->GetMappingWidth();
m_pFromScreenRT = materials->FindTexture( "_rt_FullFrameFB", TEXTURE_GROUP_RENDER_TARGET );
m_pCurrentScreenRT = materials->FindTexture( "_rt_DepthDoubler", TEXTURE_GROUP_RENDER_TARGET );
m_bForwardHint = true;
m_WindowTypeHint = WT_NONE;
m_PreviousWindowTypeHint = WT_NONE;
m_flDirection = 1.0f;
}
CBaseModTransitionPanel::~CBaseModTransitionPanel()
{
}
void CBaseModTransitionPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_nTileWidth = vgui::scheme()->GetProportionalScaledValue( atoi( pScheme->GetResourceString( "Dialog.TileWidth" ) ) );
m_nTileHeight = vgui::scheme()->GetProportionalScaledValue( atoi( pScheme->GetResourceString( "Dialog.TileHeight" ) ) );
m_nPinFromBottom = vgui::scheme()->GetProportionalScaledValue( atoi( pScheme->GetResourceString( "Dialog.PinFromBottom" ) ) );
m_nPinFromLeft = vgui::scheme()->GetProportionalScaledValue( atoi( pScheme->GetResourceString( "Dialog.PinFromLeft" ) ) );
BuildTiles();
int screenWide, screenTall;
surface()->GetScreenSize( screenWide, screenTall );
SetPos( 0, 0 );
SetSize( screenWide, screenTall );
}
void CBaseModTransitionPanel::OnKeyCodePressed( KeyCode keycode )
{
}
void CBaseModTransitionPanel::BuildTiles()
{
int screenWide, screenTall;
surface()->GetScreenSize( screenWide, screenTall );
const AspectRatioInfo_t &aspectRatioInfo = materials->GetAspectRatioInfo();
float flInverseAspect = 1.0f/aspectRatioInfo.m_flFrameBufferAspectRatio;
m_nNumColumns = ( screenWide + m_nTileWidth - 1 ) / m_nTileWidth;
m_nNumRows = ( screenTall + m_nTileHeight - 1 ) / m_nTileHeight;
m_nXOffset = m_nPinFromLeft % m_nTileWidth;
if ( m_nXOffset )
{
m_nXOffset -= m_nTileWidth;
m_nNumColumns++;
}
m_nYOffset = ( screenTall - m_nPinFromBottom ) % m_nTileHeight;
if ( m_nYOffset )
{
m_nYOffset -= m_nTileHeight;
m_nNumRows++;
}
m_Tiles.SetCount( m_nNumRows * m_nNumColumns );
float flTileWidth = ( (float)m_nTileWidth/(float)screenWide ) * GRID_WIDTH_WC;
float flTileHeight = ( (float)m_nTileHeight/(float)screenTall ) * GRID_WIDTH_WC;
int nIndex = 0;
int y = m_nYOffset;
for ( int row = 0; row < m_nNumRows; row++ )
{
int x = m_nXOffset;
for ( int col = 0; col < m_nNumColumns; col++ )
{
float flx = (float)(GRID_WIDTH_WC * x)/(float)screenWide - HALF_GRID_WIDTH_WC;
float fly = HALF_GRID_WIDTH_WC - (float)(GRID_WIDTH_WC * y)/(float)screenTall;
if ( IsX360() || IsPlatformWindowsPC() )
{
// need to do 1/2 pixel push due to dx9 pixel centers
flx -= 0.5f/(float)screenWide * GRID_WIDTH_WC;
fly += 0.5f/(float)screenTall * GRID_WIDTH_WC;
}
float s0 = (float)x / (float)screenWide;
float s1 = (float)(x + m_nTileWidth) / (float)screenWide;
float t0 = (float)y / (float)screenTall;
float t1 = (float)(y + m_nTileHeight) / (float)screenTall;
// clockwise winding from ul,ur,lr,ll
m_Tiles[nIndex].m_RectParms.m_Position0.x = flx;
m_Tiles[nIndex].m_RectParms.m_Position0.y = fly * flInverseAspect;
m_Tiles[nIndex].m_RectParms.m_Position0.z = TILE_Z;
m_Tiles[nIndex].m_RectParms.m_TexCoord0.x = s0;
m_Tiles[nIndex].m_RectParms.m_TexCoord0.y = t0;
m_Tiles[nIndex].m_RectParms.m_Position1.x = flx + flTileWidth;
m_Tiles[nIndex].m_RectParms.m_Position1.y = fly * flInverseAspect;
m_Tiles[nIndex].m_RectParms.m_Position1.z = TILE_Z;
m_Tiles[nIndex].m_RectParms.m_TexCoord1.x = s1;
m_Tiles[nIndex].m_RectParms.m_TexCoord1.y = t0;
m_Tiles[nIndex].m_RectParms.m_Position2.x = flx + flTileWidth;
m_Tiles[nIndex].m_RectParms.m_Position2.y = ( fly - flTileHeight ) * flInverseAspect;
m_Tiles[nIndex].m_RectParms.m_Position2.z = TILE_Z;
m_Tiles[nIndex].m_RectParms.m_TexCoord2.x = s1;
m_Tiles[nIndex].m_RectParms.m_TexCoord2.y = t1;
m_Tiles[nIndex].m_RectParms.m_Position3.x = flx;
m_Tiles[nIndex].m_RectParms.m_Position3.y = ( fly - flTileHeight ) * flInverseAspect;
m_Tiles[nIndex].m_RectParms.m_Position3.z = TILE_Z;
m_Tiles[nIndex].m_RectParms.m_TexCoord3.x = s0;
m_Tiles[nIndex].m_RectParms.m_TexCoord3.y = t1;
m_Tiles[nIndex].m_RectParms.m_Center = ( m_Tiles[nIndex].m_RectParms.m_Position0 + m_Tiles[nIndex].m_RectParms.m_Position2 ) / 2.0f;
x += m_nTileWidth;
nIndex++;
}
y += m_nTileHeight;
}
}
void CBaseModTransitionPanel::SetExpectedDirection( bool bForward, WINDOW_TYPE wt )
{
// direction can only be determined by taking hints from the caller
// at the moment the transition is triggered, we have to trust this
m_bForwardHint = bForward;
// can't rely on this going backwards where the nav gets subverted
// this is used to isolate some edge states for windows that aren't tile based
// attract and mainmenu don't have tiles but still need to drive transitioning TO tile based screens
if ( m_PreviousWindowTypeHint != m_WindowTypeHint )
{
m_PreviousWindowTypeHint = m_WindowTypeHint;
}
m_WindowTypeHint = wt;
}
int CBaseModTransitionPanel::GetTileIndex( int x, int y )
{
int nTile = ( y - m_nYOffset ) / m_nTileHeight * m_nNumColumns + ( x - m_nXOffset ) / m_nTileWidth;
if ( !m_Tiles.IsValidIndex( nTile ) )
return -1;
return nTile;
}
void CBaseModTransitionPanel::TouchTile( int nTile, WINDOW_TYPE wt, bool bForce )
{
if ( !m_Tiles.IsValidIndex( nTile ) )
return;
// touch tile
m_Tiles[nTile].m_nCurrentWindow = wt;
m_Tiles[nTile].m_nFrameCount = m_nFrameCount;
if ( !m_nNumTransitions && wt == WT_MAINMENU )
{
// A special case due to mainmenu not being tile based, but floating text,
// so prevent the main menu from doing the effect on its first entrance after a cleared state.
// i.e. The main menu should not be the first transition from an unexpected previous state. An unknown
// previous state would be exiting the game, the screen that we transition from is likely blending the movie in,
// not known or guaranteed to get a stable snap. The main menu transition (as the first transition) would look
// "wrong" because the screen snap would be a frame of unintended graphics.
//
// EXCEPT...
// There could have been a confirmation window that was opened before the gameui gets activated, which gives us a known frame to transition from.
// This is valid and occurs at least with a disconnect, where the confirmation is opened, but the ui is about to be activated.
// The gameui gets activated, which clears the transition state (as expected), and the UI immediately shows the confirmation.
// In this case, as the confirmation is dismissed, and the main menu is activated, we want the flip to occur.
// AND...
// Going from an 'initial state' from the attract screen, we allow the main menu to do a transition, because the attract screen
// provided a known stable previous state.
//
bool bPreventTransition = ( m_Tiles[nTile].m_nPreviousWindow == WT_NONE )
&& !( m_bForwardHint && m_PreviousWindowTypeHint == WT_ATTRACTSCREEN );
#if defined( PORTAL2_PUZZLEMAKER )
// FIXME: Hack for weird menu glitch leaving the editor in certain cases
bPreventTransition = bPreventTransition && ( m_PreviousWindowTypeHint != WT_EDITORMAINMENU );
#endif
if ( bPreventTransition )
{
// inhibit the transition by avoiding the dirty state
m_Tiles[nTile].m_nPreviousWindow = m_Tiles[nTile].m_nCurrentWindow;
}
}
if ( wt == WT_NONE || bForce )
{
// special behavior to force flip a tile to the background
// fiddle with the frame count so logic treats this as not-the-current-dialog's tile (same as dialog shrinking)
// due to NONE, the tile will flip and clear itself
m_Tiles[nTile].m_nFrameCount--;
}
}
void CBaseModTransitionPanel::MarkTile( int x, int y, WINDOW_TYPE wt, bool bForce )
{
if ( !IsEffectEnabled() )
return;
TouchTile( GetTileIndex( x, y ), wt, bForce );
}
void CBaseModTransitionPanel::MarkTilesInRect( int x, int y, int wide, int tall, WINDOW_TYPE wt, bool bForce )
{
if ( !IsEffectEnabled() )
return;
if ( wide == -1 && tall == -1 )
{
// hint to use screen extents
int screenWide, screenTall;
surface()->GetScreenSize( screenWide, screenTall );
wide = screenWide;
tall = screenTall;
}
int nRowStartTile = GetTileIndex( x, y );
int nRowEndTile = GetTileIndex( x + wide, y );
int nEndTile = GetTileIndex( x + wide, y + tall );
int nTile = nRowStartTile;
do
{
for ( int i = 0; i <= nRowEndTile - nRowStartTile; i++ )
{
TouchTile( nTile + i, wt, bForce );
}
nTile += m_nNumColumns;
}
while ( nTile < nEndTile );
}
void CBaseModTransitionPanel::PreventTransitions( bool bPrevent )
{
if ( bPrevent )
{
m_bAllowTransitions = false;
}
else if ( !m_bAllowTransitions )
{
// only reset if we were disabled
SetInitialState();
}
}
void CBaseModTransitionPanel::SuspendTransitions( bool bSuspend )
{
// quiet transitions still maintain state, but do no graphical effect
// but can continue the graphical effect as needed
m_bQuietTransitions = bSuspend;
}
void CBaseModTransitionPanel::TerminateEffect()
{
if ( !m_bTransitionActive )
return;
m_bTransitionActive = false;
for ( int i = m_Tiles.Count() - 1; i >= 0; i-- )
{
// only stopping the effect, the window type states MUST stay preserved
m_Tiles[i].m_bDirty = false;
m_Tiles[i].m_flStartTime = 0;
m_Tiles[i].m_flEndTime = 0;
}
m_Sounds.Purge();
if ( GetVPanel() == vgui::input()->GetModalSubTree() )
{
vgui::input()->ReleaseModalSubTree();
}
}
void CBaseModTransitionPanel::SetInitialState()
{
m_bAllowTransitions = true;
m_bQuietTransitions = false;
m_bForwardHint = true;
m_WindowTypeHint = WT_NONE;
m_PreviousWindowTypeHint = WT_NONE;
m_Sounds.Purge();
for ( int i = m_Tiles.Count() - 1; i >= 0; i-- )
{
m_Tiles[i].m_bDirty = false;
m_Tiles[i].m_flStartTime = 0;
m_Tiles[i].m_flEndTime = 0;
m_Tiles[i].m_nCurrentWindow = WT_NONE;
m_Tiles[i].m_nPreviousWindow = WT_NONE;
m_Tiles[i].m_nFrameCount = 0;
}
m_nNumTransitions = 0;
}
void CBaseModTransitionPanel::ScanTilesForTransition()
{
// track incoming state needed for edge-triggers
bool bTransitionActive = m_bTransitionActive;
// scan to start effect
for ( int i = m_Tiles.Count() - 1; i >= 0; i-- )
{
if ( m_Tiles[i].m_nPreviousWindow != m_Tiles[i].m_nCurrentWindow )
{
if ( !m_Tiles[i].m_bDirty || m_Tiles[i].m_nFrameCount == m_nFrameCount )
{
// the window changed marks a tile going to a new tile
m_Tiles[i].m_nPreviousWindow = m_Tiles[i].m_nCurrentWindow;
if ( m_Tiles[i].m_nCurrentWindow == WT_NONE )
{
m_Tiles[i].m_nFrameCount = 0;
}
if ( !m_bQuietTransitions )
{
m_Tiles[i].m_bDirty = true;
m_bTransitionActive = true;
}
}
}
else if ( !m_Tiles[i].m_bDirty && m_Tiles[i].m_nFrameCount && m_Tiles[i].m_nFrameCount != m_nFrameCount )
{
// a stale frame count denotes a tile returning to the background
m_Tiles[i].m_nPreviousWindow = WT_NONE;
m_Tiles[i].m_nCurrentWindow = WT_NONE;
m_Tiles[i].m_nFrameCount = 0;
if ( !m_bQuietTransitions )
{
m_Tiles[i].m_bDirty = true;
m_bTransitionActive = true;
}
}
}
if ( !bTransitionActive )
{
m_nFrameCount++;
}
bool bOverlayActive = ( CUIGameData::Get() && ( CUIGameData::Get()->IsXUIOpen() || CUIGameData::Get()->IsSteamOverlayActive() ) ) ||
CBaseModPanel::GetSingleton().IsOpaqueOverlayActive();
if ( m_bTransitionActive && ( bOverlayActive || !m_bAllowTransitions ) )
{
// when the overlay is active, abort the starting the starting effect
// this is done to ensure the states are tracked, but the effect is prevented
// this is due to windows changing behind the overlay, due to sign outs, etc
// the window states are still tracked, so when the overlay goes away, no effect gets triggered
TerminateEffect();
}
if ( m_bTransitionActive )
{
if ( !bTransitionActive )
{
m_nNumTransitions++;
vgui::input()->SetModalSubTree( GetVPanel(), GetVPanel(), true );
vgui::input()->SetModalSubTreeShowMouse( true );
// snap off the current expected direction
m_flDirection = m_bForwardHint ? 1.0f : -1.0f;
}
// seed the tiles
// wanted a forward marching of tiles top to bottom
float flEffectTime = Plat_FloatTime();
float flOffsetTime = ui_transition_delay.GetFloat() * ui_transition_time.GetFloat();
float flNextTime = 0;
float flRowTime = 0;
for ( int nRow = 0; nRow < m_nNumRows; nRow++ )
{
bool bRowHasDirtyTile = false;
int nCol = ( m_flDirection > 0 ) ? 0 : m_nNumColumns - 1;
int nColEnd = ( m_flDirection > 0 ) ? m_nNumColumns : -1;
int nColStep = ( m_flDirection > 0 ) ? 1 : -1;
while ( nCol != nColEnd )
{
int nIndex = nRow * m_nNumColumns + nCol;
if ( !m_Tiles[nIndex].m_flStartTime && m_Tiles[nIndex].m_bDirty )
{
m_Tiles[nIndex].m_flStartTime = flEffectTime + flNextTime;
m_Tiles[nIndex].m_flEndTime = m_Tiles[nIndex].m_flStartTime + ui_transition_time.GetFloat();
flNextTime += flOffsetTime;
bRowHasDirtyTile = true;
m_Sounds.AddToTail( nIndex );
}
nCol += nColStep;
}
if ( bRowHasDirtyTile )
{
flRowTime += flOffsetTime;
flNextTime = flRowTime;
}
}
}
}
bool CBaseModTransitionPanel::IsEffectEnabled()
{
if ( !m_bAllowTransitions ||
!ui_transition_effect.GetBool() ||
!enginevgui->IsGameUIVisible() ||
GameUI().IsInLevel() ||
engine->IsConnected() ||
CBaseModPanel::GetSingleton().IsLevelLoading() ||
( !IsGameConsole() && GameConsole().IsConsoleVisible() ) ||
materials->IsStereoActiveThisFrame() ) // Disable effect when in nvidia's stereo mode
{
// effect not allowed in game or loading into game
if ( m_bTransitionActive )
{
// one-time clean up if some other state changed us immediately
TerminateEffect();
}
return false;
}
return true;
}
bool CBaseModTransitionPanel::IsEffectActive()
{
return m_bTransitionActive;
}
void CBaseModTransitionPanel::SaveCurrentScreen( ITexture *pRenderTarget )
{
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->CopyRenderTargetToTextureEx( pRenderTarget, 0, NULL, NULL );
pRenderContext->SetFrameBufferCopyTexture( pRenderTarget, 0 );
}
void CBaseModTransitionPanel::DrawEffect()
{
float flEffectTime = Plat_FloatTime();
bool bFinished = true;
for ( int i = 0; i < m_Tiles.Count(); i++ )
{
if ( m_Tiles[i].m_bDirty )
{
float flLerp = RemapValClamped( flEffectTime, m_Tiles[i].m_flStartTime, m_Tiles[i].m_flEndTime, 0, 1.0f );
m_Tiles[i].m_RectParms.m_flLerp = flLerp;
if ( flLerp != 1.0f )
{
bFinished = false;
}
else
{
m_Tiles[i].m_bDirty = false;
m_Tiles[i].m_flStartTime = 0;
m_Tiles[i].m_flEndTime = 0;
}
}
}
// scan to start any sounds
if ( !bFinished )
{
for ( int i = m_Sounds.Count() - 1; i >= 0 ; i-- )
{
int nTileIndex = m_Sounds[i];
if ( !m_Tiles.IsValidIndex( nTileIndex ) )
continue;
if ( flEffectTime < m_Tiles[nTileIndex].m_flStartTime )
{
// not ready to start
continue;
}
if ( m_Tiles[nTileIndex].m_flStartTime && flEffectTime >= m_Tiles[nTileIndex].m_flStartTime )
{
// trigger sound
UISound_t uiSound = ( rand() % 2 ) ? UISOUND_TILE_CLICK1 : UISOUND_TILE_CLICK2;
CBaseModPanel::GetSingleton().PlayUISound( uiSound );
}
// this tile's sound only gets triggered once
m_Sounds.FastRemove( i );
}
}
int screenWide, screenTall;
GetSize( screenWide, screenTall );
surface()->DrawSetColor( 0, 0, 0, 255 );
surface()->DrawFilledRect( 0, 0, screenWide, screenTall );
StartPaint3D();
DrawTiles3D();
EndPaint3D();
if ( bFinished )
{
// effect over
m_bTransitionActive = false;
m_Sounds.Purge();
if ( GetVPanel() == vgui::input()->GetModalSubTree() )
{
vgui::input()->ReleaseModalSubTree();
}
}
}
void CBaseModTransitionPanel::Paint()
{
ScanTilesForTransition();
if ( m_bTransitionActive )
{
SaveCurrentScreen( m_pCurrentScreenRT );
DrawEffect();
}
}
void CBaseModTransitionPanel::PostChildPaint()
{
if ( !m_bTransitionActive )
{
// keep saving the current frame buffer to use as the 'from'
SaveCurrentScreen( m_pFromScreenRT );
}
}
void CBaseModTransitionPanel::StartPaint3D()
{
// Save off the matrices in case the painting method changes them.
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
const AspectRatioInfo_t &aspectRatioInfo = materials->GetAspectRatioInfo();
pRenderContext->PerspectiveX( 90, aspectRatioInfo.m_flFrameBufferAspectRatio, TILE_NEAR_PLANE, TILE_FAR_PLANE );
pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
// Don't draw the 3D scene w/ stencil
ShaderStencilState_t state;
state.m_bEnable = false;
pRenderContext->SetStencilState( state );
pRenderContext->ClearBuffers( false, true, true );
pRenderContext->OverrideDepthEnable( true, true, true );
}
void CBaseModTransitionPanel::EndPaint3D()
{
// Reset stencil to set stencil everywhere we draw
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
if ( !IsGameConsole() )
{
pRenderContext->OverrideDepthEnable( false, true, true );
}
ShaderStencilState_t state;
state.m_bEnable = true;
state.m_FailOp = SHADER_STENCILOP_KEEP;
state.m_ZFailOp = SHADER_STENCILOP_KEEP;
state.m_PassOp = SHADER_STENCILOP_SET_TO_REFERENCE;
state.m_CompareFunc = SHADER_STENCILFUNC_GEQUAL;
state.m_nReferenceValue = 0;
state.m_nTestMask = 0xFFFFFFFF;
state.m_nWriteMask = 0xFFFFFFFF;
pRenderContext->SetStencilState( state );
// Restore the matrices
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PopMatrix();
pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
surface()->DrawSetTexture( -1 );
}
void CBaseModTransitionPanel::DrawTiles3D()
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
for ( int i = 0; i < m_Tiles.Count(); i++ )
{
// draw the tile using the current material
// dirty tile's will alter as needed
IMaterial *pMaterial = m_pCurrentScreenMaterial;
Vector4D vecPrimaryColor = Vector4D( 1, 1, 1, 1 );
if ( ui_transition_debug.GetBool() )
{
vecPrimaryColor = Vector4D( 0.8, 0.8, 1, 1 );
}
Vector4D vecBrighterEdgeColor = vecPrimaryColor;
Vector4D vecDarkerEdgeColor = vecPrimaryColor;
bool bLeftEdgeIsBrighter = true;
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->LoadIdentity();
if ( m_Tiles[i].m_bDirty )
{
float flLerp = m_Tiles[i].m_RectParms.m_flLerp;
float flAngle = RemapValClamped( flLerp, 0, 1.0f, 0, m_flDirection * 180.0f );
// rotate the tile's normal (pointing toward viewer) to determine front/back visibility
Vector vecNormal = Vector( 0, 0, 1 );
QAngle angleRotation = QAngle( flAngle, 0, 0 );
Vector vecOutNormal;
VectorRotate( vecNormal, angleRotation, vecOutNormal );
// dot with essentially the eye vector (which is at 0,0,0)
float flDot = -DotProduct( vecOutNormal, m_Tiles[i].m_RectParms.m_Center.Normalized() );
if ( flDot < 0 )
{
// backside is visible, flip to keep the texcoords in CW screenspace order
flAngle += 180.0f;
}
// rotate the tile
pRenderContext->Translate( m_Tiles[i].m_RectParms.m_Center.x, m_Tiles[i].m_RectParms.m_Center.y, m_Tiles[i].m_RectParms.m_Center.z );
pRenderContext->Rotate( flAngle, 0, 1, 0 );
pRenderContext->Translate( -m_Tiles[i].m_RectParms.m_Center.x, -m_Tiles[i].m_RectParms.m_Center.y, -m_Tiles[i].m_RectParms.m_Center.z );
if ( flDot >= 0 )
{
pMaterial = m_pFromScreenMaterial;
if ( ui_transition_debug.GetBool() )
{
vecPrimaryColor = Vector4D( 1, 0.8, 0.8, 1 );
}
}
// do a cheap lighting occlusion by simply darkening the interior edge
float flColorLerp;
if ( flLerp < 0.5f )
{
flColorLerp = RemapValClamped( flLerp, 0, 0.5f, 1.0f, 0 );
}
else
{
flColorLerp = RemapValClamped( flLerp, 0.5f, 1.0, 0, 1.0f );
}
vecBrighterEdgeColor = vecPrimaryColor;
vecDarkerEdgeColor.x = vecBrighterEdgeColor.x * flColorLerp;
vecDarkerEdgeColor.y = vecBrighterEdgeColor.y * flColorLerp;
vecDarkerEdgeColor.z = vecBrighterEdgeColor.z * flColorLerp;
vecDarkerEdgeColor.w = vecBrighterEdgeColor.w;
// classify the interior edge
if ( m_flDirection == 1.0f )
{
bLeftEdgeIsBrighter = ( flDot > 0 );
}
else
{
bLeftEdgeIsBrighter = ( flDot <= 0 );
}
}
IMesh* pMesh = pRenderContext->GetDynamicMesh( false, NULL, NULL, pMaterial );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
meshBuilder.Position3fv( m_Tiles[i].m_RectParms.m_Position0.Base() );
meshBuilder.Color4fv( bLeftEdgeIsBrighter ? vecBrighterEdgeColor.Base() : vecDarkerEdgeColor.Base() );
meshBuilder.TexCoord2fv( 0, m_Tiles[i].m_RectParms.m_TexCoord0.Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( m_Tiles[i].m_RectParms.m_Position1.Base() );
meshBuilder.Color4fv( !bLeftEdgeIsBrighter ? vecBrighterEdgeColor.Base() : vecDarkerEdgeColor.Base() );
meshBuilder.TexCoord2fv( 0, m_Tiles[i].m_RectParms.m_TexCoord1.Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( m_Tiles[i].m_RectParms.m_Position2.Base() );
meshBuilder.Color4fv( !bLeftEdgeIsBrighter ? vecBrighterEdgeColor.Base() : vecDarkerEdgeColor.Base() );
meshBuilder.TexCoord2fv( 0, m_Tiles[i].m_RectParms.m_TexCoord2.Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( m_Tiles[i].m_RectParms.m_Position3.Base() );
meshBuilder.Color4fv( bLeftEdgeIsBrighter ? vecBrighterEdgeColor.Base() : vecDarkerEdgeColor.Base() );
meshBuilder.TexCoord2fv( 0, m_Tiles[i].m_RectParms.m_TexCoord3.Base() );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
}

View File

@@ -0,0 +1,148 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef __TRANSITIONPANEL_H__
#define __TRANSITIONPANEL_H__
#include "basemodui.h"
#include "vgui/ISurface.h"
namespace BaseModUI
{
struct RectParms_t
{
RectParms_t()
{
m_flLerp = 0;
}
Vector m_Position0;
Vector2D m_TexCoord0;
Vector m_Position1;
Vector2D m_TexCoord1;
Vector m_Position2;
Vector2D m_TexCoord2;
Vector m_Position3;
Vector2D m_TexCoord3;
Vector m_Center;
float m_flLerp;
};
struct TileQuad_t
{
TileQuad_t()
{
m_flStartTime = 0;
m_flEndTime = 0;
m_bDirty = false;
m_nCurrentWindow = WT_NONE;
m_nPreviousWindow = WT_NONE;
m_nFrameCount = 0;
}
RectParms_t m_RectParms;
float m_flStartTime;
float m_flEndTime;
bool m_bDirty;
WINDOW_TYPE m_nCurrentWindow;
WINDOW_TYPE m_nPreviousWindow;
int m_nFrameCount;
};
class CBaseModTransitionPanel : public vgui::EditablePanel
{
public:
DECLARE_CLASS_SIMPLE( CBaseModTransitionPanel, vgui::EditablePanel );
CBaseModTransitionPanel( const char *pPanelName );
~CBaseModTransitionPanel();
bool IsEffectEnabled();
bool IsEffectActive();
void MarkTile( int x, int y, WINDOW_TYPE wt, bool bForce = false );
void MarkTilesInRect( int x, int y, int wide, int tall, WINDOW_TYPE wt, bool bForce = false );
void TerminateEffect();
// instantly stop any transitions, restore performs a reset
// used for very harsh context switching (i.e. exiting the main menu) where screen stability is not possible
void PreventTransitions( bool bPrevent );
// temporarily inhibit transitions that can be safely resumed
// used for a known context that need to fix the startup auto dialogs that clock through messages and then go away
// these need to either maintain their layout size or suspend as the transition logic by design cannot do
// a transition that happens during a transition
void SuspendTransitions( bool bSuspend );
void SetInitialState();
void SetExpectedDirection( bool bForward, WINDOW_TYPE wt );
protected:
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void Paint();
virtual void PostChildPaint();
virtual void OnKeyCodePressed( vgui::KeyCode code );
private:
int GetTileIndex( int x, int y );
void TouchTile( int nTile, WINDOW_TYPE wt, bool bForce );
void SaveCurrentScreen( ITexture *pRenderTarget );
void BuildTiles();
void DrawEffect();
void ScanTilesForTransition();
void StartPaint3D();
void EndPaint3D();
void DrawBackground3D();
void DrawTiles3D();
void ShortenEffectDuration();
ITexture *m_pFromScreenRT;
ITexture *m_pCurrentScreenRT;
int m_nFrameCount;
int m_nNumTransitions;
IMaterial *m_pFromScreenMaterial;
IMaterial *m_pCurrentScreenMaterial;
int m_nPinFromBottom;
int m_nPinFromLeft;
int m_nTileWidth;
int m_nTileHeight;
int m_nNumRows;
int m_nNumColumns;
int m_nXOffset;
int m_nYOffset;
bool m_bTransitionActive;
bool m_bForwardHint;
bool m_bAllowTransitions;
bool m_bQuietTransitions;
WINDOW_TYPE m_WindowTypeHint;
WINDOW_TYPE m_PreviousWindowTypeHint;
CUtlVector< TileQuad_t > m_Tiles;
CUtlVector< int > m_Sounds;
float m_flDirection;
};
};
#endif

View File

@@ -0,0 +1,267 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "UIGameData.h"
#include "UIAvatarImage.h"
#include "EngineInterface.h"
#include "vgui/ISurface.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CGameUiAvatarImage::CGameUiAvatarImage( void )
{
m_bValid = false;
m_flFetchedTime = 0.0f;
m_flPaintedTime = 0.0f;
m_iTextureID = ( -1 );
m_nRefcount = 0;
m_nAvatarSize = MEDIUM;
#ifdef _X360
m_eAsyncState = STATE_DEFAULT;
Q_memset( &m_xOverlapped, 0, sizeof( m_xOverlapped ) );
m_xXUID = 0;
#endif
}
CGameUiAvatarImage::~CGameUiAvatarImage( void )
{
if ( vgui::surface() && m_iTextureID != -1 )
{
vgui::surface()->DestroyTextureID( m_iTextureID );
m_iTextureID = -1;
}
}
void CGameUiAvatarImage::ClearAvatarXUID( void )
{
m_bValid = false;
m_flFetchedTime = 0.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CGameUiAvatarImage::SetAvatarXUID( XUID xuid, AvatarSize_t nSize /*= MEDIUM*/ )
{
ClearAvatarXUID();
#ifndef NO_STEAM
if ( steamapicontext->SteamFriends() && steamapicontext->SteamUtils() )
{
m_nAvatarSize = nSize;
int iAvatar;
if ( nSize == SMALL )
{
iAvatar = steamapicontext->SteamFriends()->GetSmallFriendAvatar( xuid );
}
else if ( nSize == MEDIUM )
{
iAvatar = steamapicontext->SteamFriends()->GetMediumFriendAvatar( xuid );
}
else // nSize == LARGE
{
iAvatar = steamapicontext->SteamFriends()->GetLargeFriendAvatar( xuid );
}
/*
// See if it's in our list already
*/
uint32 wide, tall;
if ( steamapicontext->SteamUtils()->GetImageSize( iAvatar, &wide, &tall ) )
{
bool bUseSteamImage = true;
if ( wide == 0 || tall == 0 )
{
// attempt to handle rare data integrity issue, avatar got lost
bUseSteamImage = false;
// mock up solid white as 64x64
wide = tall = 64;
}
int cubImage = wide * tall * 4;
m_bufRgbaBuffer.EnsureCapacity( cubImage );
memset( m_bufRgbaBuffer.Base(), 0xFF, cubImage );
if ( bUseSteamImage )
{
steamapicontext->SteamUtils()->GetImageRGBA( iAvatar, (byte*)m_bufRgbaBuffer.Base(), cubImage );
}
InitFromRGBA( (byte*)m_bufRgbaBuffer.Base(), wide, tall );
}
}
#elif defined( _X360 )
X360_ResetAsyncImageState();
m_xXUID = xuid;
return true;
#endif
return m_bValid;
}
void CGameUiAvatarImage::OnFinalRelease()
{
#ifdef _X360
X360_ResetAsyncImageState();
#endif
if ( vgui::surface() && m_iTextureID != -1 )
{
vgui::surface()->DestroyTextureID( m_iTextureID );
m_iTextureID = -1;
}
delete this;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGameUiAvatarImage::InitFromRGBA( const byte *rgba, int width, int height )
{
// Texture size may be changing, so re-create
if ( m_iTextureID != -1 )
{
vgui::surface()->DestroyTextureID( m_iTextureID );
m_iTextureID = -1;
}
m_iTextureID = vgui::surface()->CreateNewTextureID( true );
if ( rgba )
vgui::surface()->DrawSetTextureRGBA( m_iTextureID, rgba, width, height );
else
vgui::surface()->DrawSetTextureFile( m_iTextureID, "icon_lobby", true, false );
int screenWide, screenTall;
vgui::surface()->GetScreenSize( screenWide, screenTall );
m_nWide = width * ( ( (float) screenWide ) / 640.0f );
m_nTall = height * ( ( (float) screenTall ) / 480.0f );
m_Color = Color( 255, 255, 255, 255 );
m_bValid = true;
m_flFetchedTime = Plat_FloatTime();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGameUiAvatarImage::Paint( void )
{
m_flPaintedTime = Plat_FloatTime();
#ifdef _X360
X360_UpdateImageState();
#endif
if ( m_bValid )
{
vgui::surface()->DrawSetColor( m_Color );
vgui::surface()->DrawSetTexture( m_iTextureID );
vgui::surface()->DrawTexturedRect( m_nX, m_nY, m_nX + m_nWide, m_nY + m_nTall );
}
}
#ifdef _X360
void CGameUiAvatarImage::X360_ResetAsyncImageState()
{
switch ( m_eAsyncState )
{
case STATE_AWAITING_KEY:
case STATE_AWAITING_RGBA:
if ( !XHasOverlappedIoCompleted( &m_xOverlapped ) )
XCancelOverlapped( &m_xOverlapped );
Q_memset( &m_xOverlapped, 0, sizeof( m_xOverlapped ) );
break;
}
m_eAsyncState = STATE_DEFAULT;
}
void CGameUiAvatarImage::X360_UpdateImageState()
{
if ( !ThreadInMainThread() )
return;
switch ( m_eAsyncState )
{
case STATE_DEFAULT:
{
m_xSetting = XPROFILE_GAMERCARD_PICTURE_KEY;
m_xCbResult = 0;
DWORD ret = xonline->XUserReadProfileSettingsByXuid( 0, XBX_GetPrimaryUserId(), 1, &m_xXUID, 1, &m_xSetting, &m_xCbResult, NULL, NULL );
if ( ret == ERROR_INSUFFICIENT_BUFFER )
{
m_xBufKey.EnsureCapacity( m_xCbResult );
XUSER_READ_PROFILE_SETTING_RESULT *pSetting = ( XUSER_READ_PROFILE_SETTING_RESULT * ) m_xBufKey.Base();
Q_memset( &m_xOverlapped, 0, sizeof( m_xOverlapped ) );
ret = xonline->XUserReadProfileSettingsByXuid( 0, XBX_GetPrimaryUserId(), 1, &m_xXUID, 1, &m_xSetting, &m_xCbResult, pSetting, &m_xOverlapped );
if ( ( ret == ERROR_SUCCESS ) || ( ret == ERROR_IO_PENDING ) )
m_eAsyncState = STATE_AWAITING_KEY;
}
}
break;
case STATE_AWAITING_KEY:
if ( XHasOverlappedIoCompleted( &m_xOverlapped ) )
{
DWORD dwResult = 0;
if ( ( ERROR_SUCCESS != XGetOverlappedResult( &m_xOverlapped, &dwResult, false ) ) ||
( ERROR_SUCCESS != dwResult ) )
{
m_eAsyncState = STATE_DEFAULT;
return;
}
XUSER_READ_PROFILE_SETTING_RESULT *pSetting = ( XUSER_READ_PROFILE_SETTING_RESULT * ) m_xBufKey.Base();
if ( pSetting->dwSettingsLen && pSetting->pSettings )
{
int cubImage = 64 * 64 * 4;
m_bufRgbaBuffer.EnsureCapacity( cubImage );
memset( m_bufRgbaBuffer.Base(), 0xFF, cubImage );
DWORD ret = XUserReadGamerPictureByKey( &pSetting->pSettings[0].data, 0, (byte*)m_bufRgbaBuffer.Base(), 64*4, 64,
NULL ); // sync read
// &m_xOverlapped );
if ( ( ret == ERROR_SUCCESS ) || ( ret == ERROR_IO_PENDING ) )
{
m_eAsyncState = STATE_AWAITING_RGBA;
goto state_rgba_ready;
}
else
m_eAsyncState = STATE_DEFAULT;
}
}
break;
case STATE_AWAITING_RGBA:
state_rgba_ready:
if ( XHasOverlappedIoCompleted( &m_xOverlapped ) )
{
DWORD dwResult = 0;
if ( ( ERROR_SUCCESS != XGetOverlappedResult( &m_xOverlapped, &dwResult, false ) ) ||
( ERROR_SUCCESS != dwResult ) )
{
m_eAsyncState = STATE_DEFAULT;
return;
}
// Image returned is ARGB, need to swap
int cubImage = 64 * 64 * 4;
for ( byte *pSwap = (byte*)m_bufRgbaBuffer.Base(), *pSwapEnd = pSwap + cubImage; pSwap < pSwapEnd; pSwap += 4 )
{
byte saveA = pSwap[0];
pSwap[0] = pSwap[1];
pSwap[1] = pSwap[2];
pSwap[2] = pSwap[3];
pSwap[3] = saveA;
}
InitFromRGBA( (byte*)m_bufRgbaBuffer.Base(), 64, 64 );
m_eAsyncState = STATE_COMPLETE;
}
break;
case STATE_COMPLETE:
break;
}
}
#endif

View File

@@ -0,0 +1,135 @@
//========= Copyright <20> 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef __UIAVATARIMAGE_H__
#define __UIAVATARIMAGE_H__
#include "vgui/IImage.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CGameUiAvatarImage : public vgui::IImage
{
public:
CGameUiAvatarImage( void );
virtual ~CGameUiAvatarImage( void );
enum AvatarSize_t
{
SMALL = 0,
MEDIUM,
LARGE
};
// Call this to set the steam ID associated with the avatar
bool SetAvatarXUID( XUID xuid, AvatarSize_t nSize = MEDIUM );
void ClearAvatarXUID( void );
AvatarSize_t GetAvatarSize( void ) const { return m_nAvatarSize; }
// Call to Paint the image
// Image will draw within the current panel context at the specified position
virtual void Paint( void );
// Set the position of the image
virtual void SetPos(int x, int y)
{
m_nX = x;
m_nY = y;
}
// Gets the size of the content
virtual void GetContentSize(int &wide, int &tall)
{
wide = m_nWide;
tall = m_nTall;
}
// Get the size the image will actually draw in (usually defaults to the content size)
virtual void GetSize(int &wide, int &tall)
{
GetContentSize( wide, tall );
}
// Sets the size of the image
virtual void SetSize(int wide, int tall)
{
m_nWide = wide;
m_nTall = tall;
}
// Set the draw color
virtual void SetColor(Color col)
{
m_Color = col;
}
virtual void SetRotation( int )
{
( void ) 0; // Not implemented
}
virtual bool Evict() { return false; }
virtual int GetNumFrames() { return 0; }
virtual void SetFrame( int nFrame ) {}
virtual vgui::HTexture GetID() { return m_iTextureID; }
bool IsValid( void ) { return m_bValid; }
float GetFetchedTime() const { return m_flFetchedTime; }
int AdjustRefCount( int nAdjustment )
{
m_nRefcount += nAdjustment;
int nReturnValue = m_nRefcount;
if ( nReturnValue <= 0 )
OnFinalRelease();
return nReturnValue;
}
virtual void OnFinalRelease();
protected:
void InitFromRGBA( const byte *rgba, int width, int height );
private:
Color m_Color;
int m_iTextureID;
int m_nX, m_nY, m_nWide, m_nTall;
bool m_bValid;
float m_flFetchedTime;
float m_flPaintedTime;
int m_nRefcount;
CUtlBuffer m_bufRgbaBuffer;
AvatarSize_t m_nAvatarSize;
#ifdef _X360
enum AsyncState_t
{
STATE_DEFAULT,
STATE_AWAITING_KEY,
STATE_AWAITING_RGBA,
STATE_COMPLETE
}
m_eAsyncState;
XOVERLAPPED m_xOverlapped;
CUtlBuffer m_xBufKey;
XUID m_xXUID;
DWORD m_xSetting;
DWORD m_xCbResult;
void X360_UpdateImageState();
void X360_ResetAsyncImageState();
#endif
};
#endif // __UIAVATARIMAGE_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,381 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef __UIGAMEDATA_H__
#define __UIGAMEDATA_H__
#include "vgui_controls/Panel.h"
#include "vgui_controls/Frame.h"
#include "vgui_controls/Button.h"
#include "tier1/utllinkedlist.h"
#include "tier1/UtlMap.h"
#include "tier1/keyvalues.h"
#include "tier1/fmtstr.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif // NO_STEAM
#include "matchmaking/imatchframework.h"
#include "matchmaking/imatchsystem.h"
#include "matchmaking/iplayer.h"
#include "matchmaking/iplayermanager.h"
#include "matchmaking/iservermanager.h"
#include "ixboxsystem.h"
#include "basemodpanel.h"
#include "basemodframe.h"
#include "UIAvatarImage.h"
#include "tokenset.h"
#include "EngineInterface.h"
#include "matchmaking/mm_helpers.h"
#ifdef PORTAL2
#include "matchmaking/portal2/imatchext_portal2.h"
#endif
namespace BaseModUI {
class CAsyncCtxUIOnDeviceAttached;
extern const tokenset_t< const char * > s_characterPortraits[];
enum SelectStorageDevicePolicy_t
{
STORAGE_DEVICE_ASYNC = ( 1 << 0 ),
STORAGE_DEVICE_NEED_ATTRACT = ( 1 << 1 ),
STORAGE_DEVICE_NEED_INVITE = ( 1 << 2 ),
};
//=============================================================================
//
//=============================================================================
//
// ISelectStorageDeviceClient
//
// Client interface for device selector:
// async flow is as follows:
// client calls into SelectStorageDevice with its parameters established:
// GetCtrlrIndex, ForceSelector, AllowDeclined
// XUI blade shows up (or implicitly determines which device should be picked based on settings).
// if OnSelectError callback fires, then the process failed.
// if OnDeviceNotSelected fires, then the process is over, device not picked
// if OnDeviceFull fires, then device has insufficient capacity and cannot be used
// if OnDeviceSelected fires, then device has been picked and async operations on containers started
// should wait for AfterDeviceMounted callback
// when AfterDeviceMounted callback fires the device is fully mounted and ready
//
class ISelectStorageDeviceClient
{
public:
virtual int GetCtrlrIndex() = 0; // Controller index (0, 1, 2 or 3)
virtual bool ForceSelector() = 0; // Whether device selector should be forcefully shown
virtual bool AllowDeclined() = 0; // Whether declining storage device is allowed
virtual bool AllowAnyController() = 0; // Whether any connected controller can be selecting storage or only game-committed
enum FailReason_t
{
FAIL_ERROR,
FAIL_NOT_SELECTED,
FAIL_FULL,
FAIL_CORRUPT
};
virtual void OnDeviceFail( FailReason_t eReason ) = 0; // Storage device has not been set
virtual void OnDeviceSelected() = 0; // After device has been picked in XUI blade, but before mounting symbolic roots and opening containers
virtual void AfterDeviceMounted() = 0; // After device has been successfully mounted, configs processed, etc.
};
//
// CChangeStorageDevice
//
// Should be used when user wants to change storage device
//
class CChangeStorageDevice : public ISelectStorageDeviceClient
{
public:
explicit CChangeStorageDevice( int iCtrlr );
virtual ~CChangeStorageDevice() {}
public:
virtual int GetCtrlrIndex() { return m_iCtrlr; }
virtual bool ForceSelector() { return m_bForce; }
virtual bool AllowDeclined() { return m_bAllowDeclined; }
virtual bool AllowAnyController() { return m_bAnyController; }
virtual void OnDeviceFail( FailReason_t eReason ); // Storage device has not been set
virtual void OnDeviceSelected(); // After device has been picked in XUI blade, but before mounting symbolic roots and opening containers
virtual void AfterDeviceMounted(); // After device has been successfully mounted, configs processed, etc.
public:
// Fired as a follow-up after all async operations finish and
// all confirmation boxes are closed down by user
virtual void DeviceChangeCompleted( bool bChanged );
public:
int m_iCtrlr;
bool m_bForce;
bool m_bAllowDeclined;
bool m_bAnyController;
int m_nConfirmationData;
};
//
// UI game data
//
class CUIGameData : public IMatchEventsSink
{
public:
CUIGameData();
~CUIGameData();
static CUIGameData* Get();
static void Shutdown();
void RunFrame();
void RunFrame_Storage();
void RunFrame_Invite();
void Invite_Confirm();
bool Invite_Connecting();
bool Invite_IsStorageDeviceValid();
void Invite_Approved();
void Invite_Declined();
void OnGameUIPostInit();
bool CanPlayer2Join();
void OpenFriendRequestPanel(int index, uint64 playerXuid);
void OpenInviteUI( char const *szInviteUiType );
void ExecuteOverlayCommand( char const *szCommand, char const *szErrorText = NULL );
// Listening for match events
virtual void OnEvent( KeyValues *pEvent );
bool IsNetworkCableConnected();
bool SignedInToLive();
bool AnyUserSignedInToLiveWithMultiplayerDisabled();
bool IsUserLIVEEnabled( int nController );
bool AnyUserConnectedToLIVE(); // One of the players has a connection to LIVE... this doesn't mean they're allowed to play multiplayer!
bool IsGuestOrOfflinePlayerWhenSomePlayersAreOnline( int nSlot );
bool CheckAndDisplayErrorIfNotSignedInToLive( CBaseModFrame *pCallerFrame );
bool CheckAndDisplayErrorIfOffline( CBaseModFrame *pCallerFrame, char const *szMsg );
bool CanSendLiveGameInviteToUser( XUID xuid );
void DisplayOkOnlyMsgBox( CBaseModFrame *pCallerFrame, const char *szTitle, const char *szMsg );
CBaseModFrame * GetParentWindowForSystemMessageBox();
const char *GetLocalPlayerName( int iController );
bool SelectStorageDevice( ISelectStorageDeviceClient *pSelectClient );
void OnDeviceAttached();
void OnCompletedAsyncDeviceAttached( CAsyncCtxUIOnDeviceAttached * job );
uint32 SelectStorageDevicePolicy();
void OnGameUIHidden();
void SetLookSensitivity(float sensitivity);
float GetLookSensitivity();
bool IsXUIOpen();
bool IsSteamOverlayActive();
bool OpenWaitScreen( const char * messageText, float minDisplayTime = 3.0f, KeyValues *pSettings = NULL );
void UpdateWaitPanel( const char * messageText, float minDisplayTime = 3.0f );
void UpdateWaitPanel( const wchar_t * messageText, float minDisplayTime = 3.0f );
#if defined( PORTAL2_PUZZLEMAKER )
void UpdateWaitPanel( UGCHandle_t hFileHandle, float flCustomProgress = -1.f );
#endif // PORTAL2_PUZZLEMAKER
bool CloseWaitScreen( vgui::Panel * callbackPanel, const char * messageName );
void NeedConnectionProblemWaitScreen( void );
void ShowPasswordUI( char const *pchCurrentPW );
void FinishPasswordUI( bool bOk );
void GetDownloadableContent( char const *szContent );
enum UiAvatarImageAccessType_t
{
kAvatarImageNull,
kAvatarImageRequest,
kAvatarImageRelease
};
vgui::IImage * AccessAvatarImage( XUID playerID, UiAvatarImageAccessType_t eAccess, CGameUiAvatarImage::AvatarSize_t nAvatarSize = CGameUiAvatarImage::MEDIUM );
char const * GetPlayerName( XUID playerID, char const *szPlayerNameSpeculative );
#if !defined( NO_STEAM )
STEAM_CALLBACK( CUIGameData, Steam_OnGameOverlayActivated, GameOverlayActivated_t, m_CallbackGameOverlayActivated );
STEAM_CALLBACK( CUIGameData, Steam_OnPersonaStateChanged, PersonaStateChange_t, m_CallbackPersonaStateChanged );
STEAM_CALLBACK( CUIGameData, Steam_OnAvatarImageLoaded, AvatarImageLoaded_t, m_CallbackAvatarImageLoaded );
STEAM_CALLBACK( CUIGameData, Steam_OnUserStatsReceived, UserStatsReceived_t, m_CallbackUserStatsReceived );
STEAM_CALLBACK( CUIGameData, Steam_OnUserStatsStored, UserStatsStored_t, m_CallbackUserStatsStored );
bool CanInitiateConnectionToSteam();
bool InitiateConnectionToSteam( char const *szUserName = NULL, char const *szPwd = NULL );
void SetConnectionToSteamReason( char const *szReason = NULL, char const *szGameMode = NULL );
#endif
int GetNumOnlineFriends() const { return m_numOnlineFriends; }
void InitiateOnlineCoopPlay( CBaseModFrame *pCaller, char const *szType, char const *szGameMode, char const *szMapName = NULL );
void InitiateSplitscreenPartnerDetection( const char* szGameMode, char const *szMapName = NULL );
bool AllowSplitscreenMainMenu();
void InitiateSinglePlayerPlay( const char *pMapName, const char *pSaveName, const char *szPlayType );
void InitiateSplitscreenPlay();
void ReloadScheme();
//
// Implementation of async jobs
// An async job is enqueued by calling "ExecuteAsync" with the proper job context.
// Job's function "ExecuteAsync" is called on a separate thread.
// After the job finishes the "Completed" function is called on the
// main thread.
//
class CAsyncJobContext
{
public:
CAsyncJobContext( float flLeastExecuteTime = 0.0f ) : m_flLeastExecuteTime( flLeastExecuteTime ), m_hThreadHandle( NULL ) {}
virtual ~CAsyncJobContext() {}
virtual void ExecuteAsync() = 0; // Executed on the secondary thread
virtual void Completed() = 0; // Executed on the main thread
public:
void * volatile m_hThreadHandle; // Handle to an async job thread waiting for
float m_flLeastExecuteTime; // Least amount of time this job should keep executing
};
CAsyncJobContext *m_pAsyncJob;
void ExecuteAsync( CAsyncJobContext *pAsync );
//
// Gamestats
//
void GameStats_ReportAction( char const *szReportAction, char const *szMapName, uint64 uiFlags );
private:
bool IsActiveSplitScreenPlayerSpectating( void );
protected:
static CUIGameData* m_Instance;
static bool m_bModuleShutDown;
bool m_CGameUIPostInit;
int m_numOnlineFriends;
float m_LookSensitivity;
float m_flShowConnectionProblemTimer;
float m_flTimeLastFrame;
bool m_bShowConnectionProblemActive;
bool m_bNeedUpdateMatchMutelist;
CUtlMap< XUID, CGameUiAvatarImage * > m_mapUserXuidToAvatar;
CUtlMap< XUID, CUtlString > m_mapUserXuidToName;
//XUI info
bool m_bXUIOpen, m_bSteamOverlayActive;
char m_chNotificationMode[128];
bool m_bPendingMapVoteRequest;
//storage device info
bool m_bWaitingForStorageDeviceHandle;
AsyncHandle_t m_hStorageDeviceChangeHandle;
uint m_iStorageID;
int m_iStorageController;
ISelectStorageDeviceClient *m_pSelectStorageClient;
void OnSetStorageDeviceId( int iController, uint nDeviceId );
};
}
extern ConVar demo_ui_enable;
extern ConVar demo_connect_string;
bool GameModeHasDifficulty( char const *szGameMode );
bool GameModeHasRoundLimit( char const *szGameMode );
bool GameModeIsSingleChapter( char const *szGameMode );
char const * GameModeGetDefaultDifficulty( char const *szGameMode );
#ifdef _PS3
class IPS3SaveSteamInfoProviderUiGameData : public IPS3SaveSteamInfoProvider
{
public:
virtual void RunFrame() = 0;
virtual void WriteSteamStats() = 0;
};
IPS3SaveSteamInfoProviderUiGameData * GetPs3SaveSteamInfoProvider();
#endif
//
// RemapText_t arrText[] = {
// { "", "#SessionError_Unknown", RemapText_t::MATCH_FULL },
// { "n/a", "#SessionError_NotAvailable", RemapText_t::MATCH_FULL },
// { "create", "#SessionError_Create", RemapText_t::MATCH_FULL },
// { "connect", "#SessionError_Connect", RemapText_t::MATCH_FULL },
// { "full", "#SessionError_Full", RemapText_t::MATCH_FULL },
// { "lock", "#SessionError_Lock", RemapText_t::MATCH_FULL },
// { "kicked", "#SessionError_Kicked", RemapText_t::MATCH_FULL },
// { "migrate", "#SessionError_Migrate", RemapText_t::MATCH_FULL },
// { "SteamServersDisconnected", "#SessionError_SteamServersDisconnected", RemapText_t::MATCH_FULL },
// { NULL, NULL, RemapText_t::MATCH_FULL }
// };
// szReason = RemapText_t::RemapRawText( arrText, szReason );
//
struct RemapText_t
{
char const *m_szRawText;
char const *m_szRemapText;
enum MatchPolicy_t
{
MATCH_FULL,
MATCH_SUBSTR,
MATCH_START
};
MatchPolicy_t m_eMatchPolicy;
inline bool Match( char const *szRawText )
{
switch( m_eMatchPolicy )
{
case MATCH_FULL:
return !Q_stricmp( szRawText, m_szRawText );
case MATCH_SUBSTR:
return Q_stristr( szRawText, m_szRawText ) != NULL;
case MATCH_START:
return StringHasPrefix( szRawText, m_szRawText );
default:
return false;
}
}
inline static char const * RemapRawText( RemapText_t *pRemapTable, char const *szRawText )
{
for ( ; pRemapTable && pRemapTable->m_szRawText; ++ pRemapTable )
{
if ( pRemapTable->Match( szRawText ) )
{
return pRemapTable->m_szRemapText;
}
}
return szRawText;
}
};
#endif // __UIGAMEDATA_H__

View File

@@ -0,0 +1,335 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "basemodpanel.h"
#include "basemodframe.h"
#include "UIGameData.h"
#include "VGenericConfirmation.h"
#include "VAttractScreen.h"
// vgui controls
#include "vgui/ILocalize.h"
// matchsystem
#include "matchmaking/imatchframework.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
#if defined (PORTAL2_PUZZLEMAKER)
#include "puzzlemaker/puzzlemaker.h"
#include "vpuzzlemakerexitconfirmation.h"
#include "vpuzzlemakersavedialog.h"
extern void ExitPuzzleMaker();
#endif
#include "cbase.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace BaseModUI;
using namespace vgui;
//
// Invite approval
//
static int s_nInviteApprovalConf = 0;
static float s_flAbandonedTimeout = 0.f;
static ISelectStorageDeviceClient *s_pPendingInviteStorageSelector = NULL;
enum InviteUserMapping_t
{
INVITE_USER_BLOCK_INPUT,
INVITE_USER_ALLOW_INPUT
};
static void Invite_MapUserForUiInput( InviteUserMapping_t eUi )
{
// Check invited user if it was the active user
#ifdef _GAMECONSOLE
if ( XBX_GetInvitedUserId() == XBX_INVALID_USER_ID )
return;
for ( DWORD k = 0; k < XBX_GetNumGameUsers(); ++ k )
{
if ( XBX_GetInvitedUserId() == (DWORD) XBX_GetUserId( k ) )
return;
}
// Invited user artificial mapping
switch ( eUi )
{
case INVITE_USER_BLOCK_INPUT:
XBX_ClearUserId( XBX_GetInvitedUserId() );
break;
case INVITE_USER_ALLOW_INPUT:
XBX_SetUserId( XBX_GetNumGameUsers(), XBX_GetInvitedUserId() );
break;
}
#endif
}
static void Invite_NotifyAction( char const *szNotifyAction )
{
s_nInviteApprovalConf = 0;
Invite_MapUserForUiInput( INVITE_USER_BLOCK_INPUT );
g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( new KeyValues(
"OnInvite", "action", szNotifyAction ) );
}
void CUIGameData::Invite_Approved()
{
if ( Invite_Connecting() )
{
Invite_NotifyAction( "join" );
}
else
{
s_nInviteApprovalConf = 0;
}
}
void CUIGameData::Invite_Declined()
{
Invite_NotifyAction( "deny" );
}
void CUIGameData::RunFrame_Invite()
{
if ( s_nInviteApprovalConf )
{
bool bInviteAbandoned = true;
// Check that the confirmation wasn't dismissed without notifying the invite system
GenericConfirmation* confirmation =
static_cast<GenericConfirmation*>( CBaseModPanel::GetSingleton().GetWindow( WT_GENERICCONFIRMATION ) );
bInviteAbandoned &= !confirmation || confirmation->GetUsageId() != s_nInviteApprovalConf;
#if defined (PORTAL2_PUZZLEMAKER)
CPuzzleMakerExitConfirmation* pSaveConfirmation =
static_cast<CPuzzleMakerExitConfirmation*>( CBaseModPanel::GetSingleton().GetWindow( WT_PUZZLEMAKEREXITCONRFIRMATION ) );
bInviteAbandoned &= !pSaveConfirmation;
CPuzzleMakerSaveDialog* pSaveDialog =
static_cast<CPuzzleMakerSaveDialog*>( CBaseModPanel::GetSingleton().GetWindow( WT_PUZZLEMAKERSAVEDIALOG ) );
bInviteAbandoned &= !pSaveDialog;
#endif
// If none of the right dialogs are up and we still have a conf number then the user must have dismissed these dialogs.
// Now we need to start timing out. We dont want to immediately decline the invite because there's a tiny gap between
// when the approval confirmation gets approved and the save confirmation pops up.
if ( bInviteAbandoned )
{
if( s_flAbandonedTimeout == 0.f )
{
s_flAbandonedTimeout = gpGlobals->realtime;
}
// Longer than 1 second, we'll assume they dismissed the prompts
else if( (gpGlobals->realtime - s_flAbandonedTimeout) > 5.f )
{
// Well, pretend like user declined the prompt
Invite_Declined();
s_flAbandonedTimeout = 0.f;
}
}
}
else
{
s_flAbandonedTimeout = 0.f;
}
if ( s_pPendingInviteStorageSelector && !IsXUIOpen() )
{
SelectStorageDevice( s_pPendingInviteStorageSelector );
s_pPendingInviteStorageSelector = NULL;
}
}
//=============================================================================
#ifdef _GAMECONSOLE
class CInviteSelectStorageDevice : public CChangeStorageDevice
{
public:
explicit CInviteSelectStorageDevice();
public:
virtual void DeviceChangeCompleted( bool bChanged );
};
CInviteSelectStorageDevice::CInviteSelectStorageDevice() :
CChangeStorageDevice( XBX_GetInvitedUserId() )
{
// Get UI panel
CBaseModPanel &ui = CBaseModPanel::GetSingleton();
ui.OnGameUIActivated();
// Allow non-involved controller
m_bAnyController = true;
// Don't force to re-select, just reload configs
m_bForce = false;
Invite_MapUserForUiInput( INVITE_USER_ALLOW_INPUT );
}
void CInviteSelectStorageDevice::DeviceChangeCompleted( bool bChanged )
{
CChangeStorageDevice::DeviceChangeCompleted( bChanged );
// Proceed with joining the invite session
Invite_NotifyAction( "join" );
}
#endif
//=============================================================================
bool CUIGameData::Invite_IsStorageDeviceValid()
{
#ifdef _GAMECONSOLE
//
// Note: the only code path that should lead to this routine is
// from invite accepting code.
// XBX_GetInvitedUserId() is set to the user id of who accepted the invite
// For that user the storage device has to be validated.
//
// If this function returns "true" it means that the user has a valid device
// selected and it is safe to proceed with the invite.
//
// If this function returns "false" it will send the "join" action OnInvite event
// after storage device selection process is over.
//
int iCtrlr = XBX_GetInvitedUserId();
if ( iCtrlr < 0 || iCtrlr >= XUSER_MAX_COUNT )
return true;
// Check what device the guy currently has mapped
DWORD dwDevice = XBX_GetStorageDeviceId( iCtrlr );
if ( XBX_DescribeStorageDevice( dwDevice ) ||
XBX_STORAGE_DECLINED == dwDevice )
// The guy has a valid device selected
// or allow the guy to play because we already
// told him earlier that his settings will not
// be saved
return true;
//
// Need to show device selector
//
s_pPendingInviteStorageSelector = new CInviteSelectStorageDevice;
return false;
#endif
return true;
}
static void Invite_Approved()
{
CUIGameData::Get()->Invite_Approved();
}
static void Invite_Approved_Do_Save_Check()
{
#if defined ( PORTAL2_PUZZLEMAKER )
if( g_pPuzzleMaker->GetActive() )
{
// Check if we're clear to exit. If not, this function will open up the prompt for
// the user to save their puzzle before leaving the puzzle maker
if( !g_pPuzzleMaker->RequestQuitGame( PUZZLEMAKER_QUIT_TO_ACCEPT_COOP_INVITE ) )
{
return;
}
// Close out the puzzle maker
ExitPuzzleMaker();
}
#endif
CUIGameData::Get()->Invite_Approved();
}
static void Invite_Declined()
{
CUIGameData::Get()->Invite_Declined();
}
void CUIGameData::Invite_Confirm()
{
// Activate game ui
CBaseModPanel &ui = CBaseModPanel::GetSingleton();
if ( !ui.IsVisible() )
{
// Activate game ui to see the dialog
engine->ExecuteClientCmd( "gameui_activate" );
}
// Get current window
CBaseModFrame *pFrame = NULL;
WINDOW_TYPE wt = ui.GetActiveWindowType();
if ( wt != WT_NONE &&
wt != WT_GENERICCONFIRMATION )
pFrame = ui.GetWindow( wt );
// Show a prompt
GenericConfirmation* confirmation =
static_cast<GenericConfirmation*>( ui.
OpenWindow( WT_GENERICCONFIRMATION, pFrame, false ) );
GenericConfirmation::Data_t data;
data.pWindowTitle = "#L4D360UI_LeaveInviteConf";
data.pMessageText =
#if defined (PORTAL2_PUZZLEMAKER)
g_pPuzzleMaker->GetActive() ? "#PORTAL2_LeavePuzzleInviteConfTxt" :
#endif
"#L4D360UI_LeaveInviteConfTxt";
data.bOkButtonEnabled = true;
data.bCancelButtonEnabled = true;
data.pfnOkCallback = ::Invite_Approved_Do_Save_Check;
data.pfnCancelCallback = ::Invite_Declined;
s_flAbandonedTimeout = 0.f;
s_nInviteApprovalConf = confirmation->SetUsageData(data);
Invite_MapUserForUiInput( INVITE_USER_ALLOW_INPUT );
}
bool CUIGameData::Invite_Connecting()
{
// Close any session that we might have outstanding
g_pMatchFramework->CloseSession();
#ifdef _PS3
if ( CAttractScreen *pAttract = ( CAttractScreen * ) CBaseModPanel::GetSingleton().GetWindow( WT_ATTRACTSCREEN ) )
{
if ( !pAttract->IsGameBootReady() )
return false; // PS3: eating the invite until game boot sequence completed, will check the lobby ID after SteamGameBootMsg check
}
#endif
// Navigate to attract screen which might take a frame
CBaseModPanel::GetSingleton().CloseAllWindows( CBaseModPanel::CLOSE_POLICY_EVEN_MSGS );
CAttractScreen::SetAttractMode( CAttractScreen::ATTRACT_ACCEPTINVITE );
CBaseModPanel::GetSingleton().OpenWindow( WT_ATTRACTSCREEN, NULL, true );
#if defined( _PS3 ) && !defined( NO_STEAM )
return steamapicontext->SteamUser()->BLoggedOn();
#else
return true;
#endif
}

View File

@@ -0,0 +1,987 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "basemodpanel.h"
#include "basemodframe.h"
#include "UIGameData.h"
#include "EngineInterface.h"
#include "VGenericConfirmation.h"
#include "vgui/ILocalize.h"
#include "matchmaking/imatchframework.h"
#include "filesystem.h"
#include "fmtstr.h"
#include "c_portal_gamestats.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
#include "vattractscreen.h"
#include "steamcloudsync.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace BaseModUI;
using namespace vgui;
#ifndef ERROR_SUCCESS
#define ERROR_SUCCESS 0
#endif
#ifndef ERROR_IO_INCOMPLETE
#define ERROR_IO_INCOMPLETE 996L
#endif
//
// Storage device selection
//
//-----------------------------------------------------------------------------
// Purpose: A storage device has been connected, update our settings and anything else
//-----------------------------------------------------------------------------
namespace BaseModUI {
class CAsyncCtxUIOnDeviceAttached : public CUIGameData::CAsyncJobContext
{
public:
explicit CAsyncCtxUIOnDeviceAttached( int iController );
~CAsyncCtxUIOnDeviceAttached();
virtual void ExecuteAsync();
virtual void Completed();
uint GetContainerOpenResult( void ) { return m_ContainerOpenResult; }
int GetController() const { return m_iController; }
private:
uint m_ContainerOpenResult;
int m_iController;
};
CAsyncCtxUIOnDeviceAttached::CAsyncCtxUIOnDeviceAttached( int iController ) :
CUIGameData::CAsyncJobContext( 3.0f ), // Storage device info for at least 3 seconds
m_ContainerOpenResult( ERROR_SUCCESS ),
m_iController( iController )
{
//CUIGameData::Get()->ShowMessageDialog( MD_CHECKING_STORAGE_DEVICE );
}
CAsyncCtxUIOnDeviceAttached::~CAsyncCtxUIOnDeviceAttached()
{
//CUIGameData::Get()->CloseMessageDialog( 0 );
}
void CAsyncCtxUIOnDeviceAttached::ExecuteAsync()
{
// Asynchronously do the tasks that don't interact with the command buffer
// g_pFullFileSystem->DiscoverDLC( GetController() ); - don't call DiscoverDLC here
// Open user settings and save game container here
m_ContainerOpenResult = engine->OnStorageDeviceAttached( GetController() );
if ( m_ContainerOpenResult != ERROR_SUCCESS )
return;
}
ConVar ui_start_dlc_time_pump( "ui_start_dlc_time_pump", "30" );
ConVar ui_start_dlc_time_loaded( "ui_start_dlc_time_loaded", "150" );
ConVar ui_start_dlc_time_corrupt( "ui_start_dlc_time_corrupt", "300" );
CON_COMMAND_F( ui_pump_dlc_mount_corrupt, "", FCVAR_DEVELOPMENTONLY )
{
int nStage = -1;
if ( args.ArgC() > 1 )
{
nStage = Q_atoi( args.Arg( 1 ) );
}
DevMsg( 2, "ui_pump_dlc_mount_corrupt %d\n", nStage );
int nCorruptDLCs = g_pFullFileSystem->IsAnyCorruptDLC();
while ( nStage >= 0 && nStage < nCorruptDLCs )
{
static wchar_t wszDlcInfo[ 3 * MAX_PATH ] = {0};
if ( !g_pFullFileSystem->GetAnyCorruptDLCInfo( nStage, wszDlcInfo, sizeof( wszDlcInfo ) ) )
{
++ nStage;
continue;
}
// information text
if ( wchar_t *wszExplanation = g_pVGuiLocalize->Find( "#L4D360UI_MsgBx_DlcCorruptTxt" ) )
{
int wlen = Q_wcslen( wszDlcInfo );
Q_wcsncpy( wszDlcInfo + wlen, wszExplanation, sizeof( wszDlcInfo ) - 2 * wlen );
}
// We've got a corrupt DLC, put it up on the spinner
CUIGameData::Get()->UpdateWaitPanel( wszDlcInfo, 0.0f );
engine->ClientCmd( CFmtStr( "echo corruptdlc%d; wait %d; ui_pump_dlc_mount_corrupt %d;",
nStage + 1, ui_start_dlc_time_corrupt.GetInt(), nStage + 1 ) );
return;
}
// end of dlc mounting phases
CUIGameData::Get()->OnCompletedAsyncDeviceAttached( NULL );
}
CON_COMMAND_F( ui_pump_dlc_mount_content, "", FCVAR_DEVELOPMENTONLY )
{
int nStage = -1;
if ( args.ArgC() > 1 )
{
nStage = Q_atoi( args.Arg( 1 ) );
}
DevMsg( 2, "ui_pump_dlc_mount_content %d\n", nStage );
bool bSearchPathMounted = false;
int numDlcsContent = g_pFullFileSystem->IsAnyDLCPresent( &bSearchPathMounted );
while ( nStage >= 0 && nStage < numDlcsContent )
{
static wchar_t wszDlcInfo[ 3 * MAX_PATH ] = {0};
unsigned int ulMask;
if ( !g_pFullFileSystem->GetAnyDLCInfo( nStage, &ulMask, wszDlcInfo, sizeof( wszDlcInfo ) ) )
{
++ nStage;
continue;
}
// set the installed DLC key values resolution key
if ( int iDlcNumber = DLC_LICENSE_ID( ulMask ) )
{
CFmtStr sDlc( "DLC%u_INSTALLED", iDlcNumber );
KeyValuesSystem()->SetKeyValuesExpressionSymbol( sDlc, 1 );
}
// information text
if ( wchar_t *wszExplanation = g_pVGuiLocalize->Find( "#L4D360UI_MsgBx_DlcMountedTxt" ) )
{
int wlen = Q_wcslen( wszDlcInfo );
Q_wcsncpy( wszDlcInfo + wlen, wszExplanation, sizeof( wszDlcInfo ) - 2 * wlen );
}
// We've got a corrupt DLC, put it up on the spinner
CUIGameData::Get()->UpdateWaitPanel( wszDlcInfo, 0.0f );
engine->ClientCmd( CFmtStr( "echo mounteddlc%d (0x%08X); wait %d; ui_pump_dlc_mount_content %d;",
nStage + 1, ulMask, ui_start_dlc_time_loaded.GetInt(), nStage + 1 ) );
return;
}
// Done displaying found content, show corrupt
engine->ClientCmd( "ui_pump_dlc_mount_corrupt 0" );
}
CON_COMMAND_F( ui_pump_dlc_mount_stage, "", FCVAR_DEVELOPMENTONLY )
{
// execute in order
int nStage = -1;
if ( args.ArgC() > 1 )
{
nStage = Q_atoi( args.Arg( 1 ) );
}
DevMsg( 2, "ui_pump_dlc_mount_stage %d\n", nStage );
static char const *s_arrClientCmdsDlcMount[] =
{
"net_reloadgameevents",
"hud_reloadscheme",
"gameinstructor_reload_lessons",
"scenefilecache_reload",
"cc_reload",
"rr_reloadresponsesystems",
"cl_soundemitter_reload",
"sv_soundemitter_reload",
"cl_modemanager_reload",
"sv_reload_node_position_keys"
};
if ( nStage >= 0 && nStage < ARRAYSIZE( s_arrClientCmdsDlcMount ) )
{
// execute in phases, each command deferred occurs on main thread as required
// adding a wait <frames> to let spinner clock a little
// no way to solve any one phase that blocks for too long...this is good enough
engine->ClientCmd( CFmtStr( "wait %d; %s; ui_pump_dlc_mount_stage %d;",
ui_start_dlc_time_pump.GetInt(),
s_arrClientCmdsDlcMount[ nStage ],
nStage + 1 ) );
return;
}
// Done mounting
engine->ClientCmd( "ui_pump_dlc_mount_content 0" );
}
void CAsyncCtxUIOnDeviceAttached::Completed()
{
bool bDLCSearchPathMounted = false;
if ( GetContainerOpenResult() == ERROR_SUCCESS &&
g_pFullFileSystem->IsAnyDLCPresent( &bDLCSearchPathMounted ) )
{
if ( !( CUIGameData::Get()->SelectStorageDevicePolicy() & STORAGE_DEVICE_ASYNC ) )
{
Warning( "<vitaliy> DLC discovered during sync storage mount (not mounted)!\n" );
goto completed_done;
}
if ( !bDLCSearchPathMounted )
{
// add the DLC search paths if they exist
// this must be done on the main thread
// the DLC search path mount will incur a quick synchronous hit due to zip mounting
g_pFullFileSystem->AddDLCSearchPaths();
// new DLC data may trump prior data, so need to signal isolated system reloads
engine->ClientCmd( "ui_pump_dlc_mount_stage 0" );
return;
}
}
// No valid DLC was discovered, check if we discovered some corrupt DLC
if ( g_pFullFileSystem->IsAnyCorruptDLC() )
{
if ( !( CUIGameData::Get()->SelectStorageDevicePolicy() & STORAGE_DEVICE_ASYNC ) )
{
Warning( "<vitaliy> DLC discovered during sync storage mount (corrupt)!\n" );
goto completed_done;
}
// need to show just corrupt DLC information
engine->ClientCmd( CFmtStr( "ui_pump_dlc_mount_corrupt %d", 0 ) );
return;
}
// Otherwise we are done attaching storage right now
completed_done:
CUIGameData::Get()->OnCompletedAsyncDeviceAttached( this );
}
}
//
// CChangeStorageDevice
//
// Should be used when user wants to change storage device
//
static CChangeStorageDevice *s_pChangeStorageDeviceCallback = NULL;
static void CChangeStorageDevice_Continue()
{
s_pChangeStorageDeviceCallback->DeviceChangeCompleted( true );
delete s_pChangeStorageDeviceCallback;
s_pChangeStorageDeviceCallback = NULL;
}
static void CChangeStorageDevice_SelectAgain()
{
CUIGameData::Get()->SelectStorageDevice( s_pChangeStorageDeviceCallback );
s_pChangeStorageDeviceCallback = NULL;
}
CChangeStorageDevice::CChangeStorageDevice( int iCtrlr ) :
m_iCtrlr( iCtrlr ),
m_bAllowDeclined( true ),
m_bForce( true ),
m_nConfirmationData( 0 )
{
// Just in case clean up (if dialogs were cancelled due to user sign out or such)
delete s_pChangeStorageDeviceCallback;
s_pChangeStorageDeviceCallback = NULL;
}
void CChangeStorageDevice::OnDeviceFail( FailReason_t eReason )
{
// Depending if the user had storage device by this moment
// or not we will take different actions:
DWORD dwDevice = XBX_GetStorageDeviceId( GetCtrlrIndex() );
switch ( eReason )
{
case FAIL_ERROR:
case FAIL_NOT_SELECTED:
if ( XBX_DescribeStorageDevice( dwDevice ) )
{
// That's fine user has a valid storage device, didn't want to change
DeviceChangeCompleted( false );
delete this;
return;
}
// otherwise, proceed with the ui msg
}
XBX_SetStorageDeviceId( GetCtrlrIndex(), XBX_STORAGE_DECLINED );
// We don't want to fire notification because there might be unsaved
// preferences changes that were done without a storage device
// no: g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( new KeyValues( "OnProfileStorageAvailable", "iController", GetCtrlrIndex() ) );
m_bAllowDeclined = false;
GenericConfirmation* confirmation =
static_cast<GenericConfirmation*>( CBaseModPanel::GetSingleton().
OpenWindow( WT_GENERICCONFIRMATION, CUIGameData::Get()->GetParentWindowForSystemMessageBox(), false ) );
GenericConfirmation::Data_t data;
switch ( eReason )
{
case FAIL_ERROR:
case FAIL_NOT_SELECTED:
data.pWindowTitle = "#L4D360UI_MsgBx_AttractDeviceNoneC";
data.pMessageText = "#L4D360UI_MsgBx_AttractDeviceNoneTxt";
break;
case FAIL_FULL:
data.pWindowTitle = "#L4D360UI_MsgBx_AttractDeviceFullC";
data.pMessageText = "#L4D360UI_MsgBx_AttractDeviceFullTxt";
break;
case FAIL_CORRUPT:
default:
data.pWindowTitle = "#L4D360UI_MsgBx_AttractDeviceCorruptC";
data.pMessageText = "#L4D360UI_MsgBx_AttractDeviceCorruptTxt";
break;
}
data.bOkButtonEnabled = true;
data.bCancelButtonEnabled = true;
s_pChangeStorageDeviceCallback = this;
data.pfnOkCallback = CChangeStorageDevice_Continue;
data.pfnCancelCallback = CChangeStorageDevice_SelectAgain;
// WARNING! WARNING! WARNING!
// The nature of Generic Confirmation is that it will be silently replaced
// with another Generic Confirmation if a system event occurs
// e.g. user unplugs controller, user changes storage device, etc.
// If that happens neither OK nor CANCEL callbacks WILL NOT BE CALLED
// The state machine cannot depend on either callback advancing the
// state because in some situations neither callback can fire and the
// confirmation dismissed/closed/replaced.
// State machine must implement OnThink and check if the required
// confirmation box is still present!
// This code implements some sort of fallback - it deletes the static
// confirmation data when a new storage device change is requested.
// Vitaliy -- 9/26/2009
//
m_nConfirmationData = confirmation->SetUsageData(data);
}
void CChangeStorageDevice::OnDeviceSelected()
{
if ( UI_IsDebug() )
{
Msg( "[GAMEUI] CChangeStorageDevice::OnDeviceSelected( 0x%08X )\n",
XBX_GetStorageDeviceId( GetCtrlrIndex() ) );
}
CUIGameData::Get()->UpdateWaitPanel( "#L4D360UI_WaitScreen_SignOnSucceded" );
}
void CChangeStorageDevice::AfterDeviceMounted()
{
DeviceChangeCompleted( true );
g_pMatchFramework->GetEventsSubscription()->BroadcastEvent( new KeyValues( "OnProfileStorageAvailable", "iController", GetCtrlrIndex() ) );
delete this;
}
void CChangeStorageDevice::DeviceChangeCompleted( bool bChanged )
{
if ( bChanged )
{
Msg( "CChangeStorageDevice::DeviceChangeCompleted for ctrlr%d device 0x%08X\n",
GetCtrlrIndex(), XBX_GetStorageDeviceId( GetCtrlrIndex() ) );
}
else
{
Msg( "CChangeStorageDevice::DeviceChangeCompleted - ctrlr%d is keeping device 0x%08X\n",
GetCtrlrIndex(), XBX_GetStorageDeviceId( GetCtrlrIndex() ) );
}
}
//=============================================================================
//
//=============================================================================
class CChangeStorageDeviceChained : public CChangeStorageDevice
{
public:
typedef CChangeStorageDevice BaseClass;
explicit CChangeStorageDeviceChained( int iCtrlrs[2] ) :
BaseClass( iCtrlrs[0] ), m_nChainCtrlr( iCtrlrs[1] ) {}
virtual void DeviceChangeCompleted( bool bChanged )
{
// Defer to the base class
BaseClass::DeviceChangeCompleted( bChanged );
// If we have a chain target, then call this off again
if ( m_nChainCtrlr >= 0 )
{
CUIGameData::Get()->SelectStorageDevice( new CChangeStorageDevice( m_nChainCtrlr ) );
}
}
private:
int m_nChainCtrlr;
};
void OnStorageDevicesChangedSelectNewDevice()
{
#ifdef _GAMECONSOLE
int numChangedCtrlrs = 0;
int nChangedCtrlrs[2] = { -1, -1 }; // We can only have two users (split-screen)
for ( DWORD i = 0; i < XBX_GetNumGameUsers(); ++ i )
{
int iController = XBX_GetUserId( i );
// Guests can't choose a storage device!
if ( XBX_GetUserIsGuest( i ) )
continue;
int nStorageID = XBX_GetStorageDeviceId( iController );
if ( nStorageID == XBX_INVALID_STORAGE_ID )
{
// A controller's device has changed, and we'll need to prompt them to replace it
nChangedCtrlrs[numChangedCtrlrs] = iController;
numChangedCtrlrs++;
}
}
// If a controller changed, then start off our device change dialogs
if ( numChangedCtrlrs )
{
CUIGameData::Get()->SelectStorageDevice( new CChangeStorageDeviceChained( nChangedCtrlrs ) );
}
#endif // _GAMECONSOLE
}
void CUIGameData::RunFrame_Storage()
{
// Check to see if a pending async task has already finished
if ( m_pAsyncJob && !m_pAsyncJob->m_hThreadHandle )
{
m_pAsyncJob->Completed();
delete m_pAsyncJob;
m_pAsyncJob = NULL;
}
if( m_bWaitingForStorageDeviceHandle )
{
//the select device blade just closed, get the selected device
DWORD ret = xboxsystem->GetOverlappedResult( m_hStorageDeviceChangeHandle, NULL, true );
if ( ret != ERROR_IO_INCOMPLETE )
{
// Done waiting
xboxsystem->ReleaseAsyncHandle( m_hStorageDeviceChangeHandle );
m_bWaitingForStorageDeviceHandle = false;
// If we selected something, validate it
if ( m_iStorageID != XBX_INVALID_STORAGE_ID )
{
OnSetStorageDeviceId( m_iStorageController, m_iStorageID );
}
else
{
CloseWaitScreen( NULL, "ReportNoDeviceSelected" );
if ( m_pSelectStorageClient )
{
m_pSelectStorageClient->OnDeviceFail( ISelectStorageDeviceClient::FAIL_NOT_SELECTED );
m_pSelectStorageClient = NULL;
}
}
}
}
#ifdef _PS3
GetPs3SaveSteamInfoProvider()->RunFrame();
#endif
if ( g_pGameSteamCloudSync )
g_pGameSteamCloudSync->RunFrame();
}
void StorageDevice_SelectAllNow()
{
#ifdef _GAMECONSOLE
int numChangedCtrlrs = 0;
int nChangedCtrlrs[2] = { -1, -1 }; // We can only have two users (split-screen)
for ( DWORD i = 0; i < XBX_GetNumGameUsers(); ++ i )
{
int iController = XBX_GetUserId( i );
// Guests can't choose a storage device!
if ( XBX_GetUserIsGuest( i ) )
continue;
int nStorageID = XBX_GetStorageDeviceId( iController );
if ( nStorageID == XBX_INVALID_STORAGE_ID )
{
// A controller's device has changed, and we'll need to prompt them to replace it
nChangedCtrlrs[numChangedCtrlrs] = iController;
numChangedCtrlrs++;
}
}
// If a controller changed, then start off our device change dialogs
if ( numChangedCtrlrs )
{
CUIGameData::Get()->SelectStorageDevice( new CChangeStorageDeviceChained( nChangedCtrlrs ) );
}
#endif // _GAMECONSOLE
}
//=============================================================================
//This is where we open the XUI pannel to let the user select the current storage device.
bool CUIGameData::SelectStorageDevice( ISelectStorageDeviceClient *pSelectClient )
{
#ifdef _GAMECONSOLE
if ( !pSelectClient )
return false;
int iController = pSelectClient->GetCtrlrIndex();
bool bAllowDeclined = pSelectClient->AllowDeclined();
bool bForceDisplay = pSelectClient->ForceSelector();
bool bCheckCtrlr = !pSelectClient->AllowAnyController();
if ( UI_IsDebug() )
{
Msg( "[GAMEUI] SelectStorageDevice( ctrlr=%d; %d, %d ), waiting=%d\n",
iController, bAllowDeclined, bForceDisplay, m_bWaitingForStorageDeviceHandle );
}
if ( bCheckCtrlr )
{
// Check if the game is in guest mode
if ( XBX_GetPrimaryUserIsGuest() )
{
Warning( "[GAMEUI] SelectStorageDevice for guest!\n" );
pSelectClient->OnDeviceFail( ISelectStorageDeviceClient::FAIL_ERROR );
return false; // go away, no storage for guests
}
int nSlot = -1;
for ( DWORD k = 0; k < XBX_GetNumGameUsers(); ++ k )
{
int iCtrlr = XBX_GetUserId( k );
if ( iCtrlr != iController )
continue;
else if ( XBX_GetUserIsGuest( k ) )
{
Warning( "[GAMEUI] SelectStorageDevice for guest!\n" );
pSelectClient->OnDeviceFail( ISelectStorageDeviceClient::FAIL_ERROR );
return false; // go away, game thinks you are a guest
}
else
nSlot = k;
}
if ( nSlot < 0 )
{
Warning( "[GAMEUI] SelectStorageDevice for not active ctrlr!\n" );
pSelectClient->OnDeviceFail( ISelectStorageDeviceClient::FAIL_ERROR );
return false; // this controller is not involved in the game, go away
}
}
#ifdef _X360
// Is the controller signed in?
if( XUserGetSigninState( iController ) == eXUserSigninState_NotSignedIn )
{
Warning( "[GAMEUI] SelectStorageDevice for not signed in user!\n" );
pSelectClient->OnDeviceFail( ISelectStorageDeviceClient::FAIL_ERROR );
return false; // not signed in, no device selector
}
// Maybe a guest buddy?
XUSER_SIGNIN_INFO xsi;
if ( ERROR_SUCCESS == XUserGetSigninInfo( iController, XUSER_GET_SIGNIN_INFO_ONLINE_XUID_ONLY, &xsi ) &&
(xsi.dwInfoFlags & XUSER_INFO_FLAG_GUEST) != 0 )
{
Warning( "[GAMEUI] SelectStorageDevice for LIVE-guest!\n" );
pSelectClient->OnDeviceFail( ISelectStorageDeviceClient::FAIL_ERROR );
return false; // guests don't have device selectors, go away
}
if ( ERROR_SUCCESS != XUserGetSigninInfo( iController, XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY, &xsi ) )
{
Warning( "[GAMEUI] SelectStorageDevice failed to obtain XUID!\n" );
pSelectClient->OnDeviceFail( ISelectStorageDeviceClient::FAIL_ERROR );
return false; // failed to obtain XUID?
}
#endif
//
// Prevent reentry
//
if( m_bWaitingForStorageDeviceHandle )
{
Warning( "[GAMEUI] SelectStorageDevice is already busy selecting storage device! Cannot re-enter!\n" );
pSelectClient->OnDeviceFail( ISelectStorageDeviceClient::FAIL_ERROR );
return false; // Somebody already selecting a device
}
#if defined( _DEMO ) && defined( _GAMECONSOLE )
// Demo mode cannot have access to storage devices anyway
if ( IsGameConsole() )
{
m_iStorageID = XBX_STORAGE_DECLINED;
m_iStorageController = iController;
m_pSelectStorageClient = pSelectClient;
m_pSelectStorageClient->OnDeviceSelected();
OnCompletedAsyncDeviceAttached( NULL );
return true;
}
#endif
if ( IsPS3() )
{
// PS3 will have only two storage partitions: primary and secondary
if ( iController == (int) XBX_GetPrimaryUserId() )
XBX_SetStorageDeviceId( iController, 1 );
else
XBX_SetStorageDeviceId( iController, 2 );
bForceDisplay = false; // PS3 doesn't display anything, so don't force it
}
// Check if we already have a valid storage device
if ( XBX_GetStorageDeviceId( iController ) != XBX_INVALID_STORAGE_ID &&
( bAllowDeclined || XBX_GetStorageDeviceId( iController ) != XBX_STORAGE_DECLINED ) &&
! bForceDisplay )
{
if ( UI_IsDebug() )
{
Msg( "[GAMEUI] SelectStorageDevice - storage id = 0x%08X\n",
XBX_GetStorageDeviceId( iController ) );
}
// Put up a progress that we are loading profile...
if ( SelectStorageDevicePolicy() & STORAGE_DEVICE_ASYNC )
OpenWaitScreen( "#L4D360UI_WaitScreen_SigningOn" );
m_iStorageID = XBX_GetStorageDeviceId( iController );
m_iStorageController = iController;
m_pSelectStorageClient = pSelectClient;
OnSetStorageDeviceId( iController, XBX_GetStorageDeviceId( iController ) );
// Already have a storage device
return true;
}
// Put up a progress that we are loading profile...
OpenWaitScreen( "#L4D360UI_WaitScreen_SigningOn", 0.0f );
// NOTE: this shouldn't have a 3 sec time-out as a new wait message is taking over
// the progress when container starts mounting
//open the dialog
m_bWaitingForStorageDeviceHandle = true;
m_hStorageDeviceChangeHandle = xboxsystem->CreateAsyncHandle();
m_iStorageID = XBX_INVALID_STORAGE_ID;
m_iStorageController = iController;
m_pSelectStorageClient = pSelectClient;
xboxsystem->ShowDeviceSelector( iController, bForceDisplay, &m_iStorageID, &m_hStorageDeviceChangeHandle );
#endif
return false;
}
uint32 CUIGameData::SelectStorageDevicePolicy()
{
return
( IsX360() ? STORAGE_DEVICE_ASYNC : 0 )
;
}
//=============================================================================
void CUIGameData::OnDeviceAttached()
{
//This is straight from CBasePanel
ExecuteAsync( new CAsyncCtxUIOnDeviceAttached( m_iStorageController ) );
}
//=============================================================================
void CUIGameData::OnCompletedAsyncDeviceAttached( CAsyncCtxUIOnDeviceAttached * job )
{
ISelectStorageDeviceClient *pStorageDeviceClient = m_pSelectStorageClient;
m_pSelectStorageClient = NULL;
uint nRet = job ? job->GetContainerOpenResult() : ERROR_SUCCESS;
if ( nRet != ERROR_SUCCESS )
{
if ( SelectStorageDevicePolicy() & STORAGE_DEVICE_ASYNC )
CloseWaitScreen( NULL, "ReportDeviceCorrupt" );
pStorageDeviceClient->OnDeviceFail( ISelectStorageDeviceClient::FAIL_CORRUPT );
}
else
{
// Notify that data has loaded
pStorageDeviceClient->AfterDeviceMounted();
// Check for opening a new storage device immediately
if ( m_pSelectStorageClient == NULL )
{
// Close down the waiting screen
if ( SelectStorageDevicePolicy() & STORAGE_DEVICE_ASYNC )
CloseWaitScreen( NULL, "OnCompletedAsyncDeviceAttached" );
}
}
}
#ifdef _WIN32
//-------------------------
// Purpose: Job wrapper
//-------------------------
static unsigned UIGameDataJobWrapperFn( void *pvContext )
{
CUIGameData::CAsyncJobContext *pAsync = reinterpret_cast< CUIGameData::CAsyncJobContext * >( pvContext );
float const flTimeStart = Plat_FloatTime();
pAsync->ExecuteAsync();
float const flElapsedTime = Plat_FloatTime() - flTimeStart;
if ( flElapsedTime < pAsync->m_flLeastExecuteTime )
{
ThreadSleep( ( pAsync->m_flLeastExecuteTime - flElapsedTime ) * 1000 );
}
ReleaseThreadHandle( ( ThreadHandle_t ) pAsync->m_hThreadHandle );
pAsync->m_hThreadHandle = NULL;
return 0;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Enqueues a job function to be called on a separate thread
//-----------------------------------------------------------------------------
void CUIGameData::ExecuteAsync( CAsyncJobContext *pAsync )
{
Assert( !m_pAsyncJob );
Assert( pAsync && !pAsync->m_hThreadHandle );
m_pAsyncJob = pAsync;
#ifdef _WIN32
ThreadHandle_t hHandle = CreateSimpleThread( UIGameDataJobWrapperFn, reinterpret_cast< void * >( pAsync ) );
pAsync->m_hThreadHandle = hHandle;
#ifdef _X360
ThreadSetAffinity( hHandle, XBOX_PROCESSOR_3 );
#endif
#else
// Since we are not running on a separate thread, just fire it all here
m_pAsyncJob = NULL;
pAsync->ExecuteAsync();
pAsync->Completed();
delete pAsync;
#endif
}
//////////////////////////////////////////////////////////////////////////
//
// Gamestats reporting
//
static int GameStats_GetActionIndex( char const *szReportAction )
{
char const * arrActions[] =
{
"", "newgame", "commentary",
"load", "loadlast",
"continuenew", "continueload",
"saveover", "savenew", "savedel",
"changelevel", "changelevelcomm",
"bonusmap",
"challenge_continue", "challenge_retry", "challenge_quit", "challenge_hub"
};
for ( int k = 0; k < ARRAYSIZE( arrActions ); ++ k )
{
if ( !V_stricmp( arrActions[k], szReportAction ) )
return k + 1;
}
return 0;
}
static int GameStats_GetReportMapNameIndex( char const *szMapName )
{
int nCounter = 1000; // resolve it as single player map
#define CFG( spmap, ... ) ++ nCounter; if ( !V_stricmp( szMapName, #spmap ) ) return nCounter;
#include "xlast_portal2/inc_sp_maps.inc"
#undef CFG
nCounter = 0; // resolve it as coop map
#define CFG( mpcoopmap, ... ) ++ nCounter; if ( !V_stricmp( szMapName, #mpcoopmap ) ) return nCounter;
#include "xlast_portal2/inc_coop_maps.inc"
#undef CFG
return 0;
}
void CUIGameData::GameStats_ReportAction( char const *szReportAction, char const *szMapName, uint64 uiFlags )
{
KeyValues *kv = new KeyValues( "gamestat_action" );
KeyValues::AutoDelete autodelete_kv( kv );
kv->SetInt( "version", 1 );
uint64 xuid = 0ull;
if ( IPlayerLocal *pPlayerLocal = g_pMatchFramework->GetMatchSystem()->GetPlayerManager()->GetLocalPlayer( 0 ) )
{
xuid = pPlayerLocal->GetXUID();
}
kv->SetUint64( "xuid", xuid );
kv->SetUint64( "*mac", 0ull ); // this will be filled out with console MAC-address
kv->SetInt( "game_action", GameStats_GetActionIndex( szReportAction ) );
kv->SetInt( "game_mapid", GameStats_GetReportMapNameIndex( szMapName ) );
kv->SetUint64( "game_flags", uiFlags );
IDatacenterCmdBatch *pBatch = g_pMatchFramework->GetMatchSystem()->GetDatacenter()->CreateCmdBatch();
pBatch->SetDestroyWhenFinished( true );
pBatch->SetRetryCmdTimeout( 30.0f );
pBatch->AddCommand( kv );
#if !defined( _GAMECONSOLE ) && !defined( NO_STEAM )
// Send these stats to OGS
g_PortalGameStats.Event_UIEvent( xuid, szReportAction, uiFlags, szMapName );
#endif //!defined( _GAMECONSOLE )
}
#ifdef _PS3
//////////////////////////////////////////////////////////////////////////
//
// Steam info provider implementation
//
//////////////////////////////////////////////////////////////////////////
class CPS3SaveSteamInfoProvider : public IPS3SaveSteamInfoProviderUiGameData
{
public:
virtual CUtlBuffer * GetInitialLoadBuffer()
{
GetBufferForSaveUtil().EnsureCapacity( 512*1024 - 128 );
return &GetBufferForSaveUtil();
}
virtual CUtlBuffer * GetSaveBufferForCommit()
{
// called inside the saveutil callback (cannot cause allocations)
return &GetBufferForSaveUtil();
}
virtual CUtlBuffer * PrepareSaveBufferForCommit()
{
// called on the main thread
if ( !FillSteamBuffer() )
{
m_uiState &=~ ( STATE_DIRTY | STATE_INITIATED | STATE_COMMITTING );
return NULL;
}
m_uiState |= STATE_COMMITTING; // flipping the committing flag early
++ m_idxSaveUtilOwned; // now saveutil owns the buffer we were writing into
m_uiState &=~ STATE_DIRTY; // mark the steam data buffer as not yet dirty
return &GetBufferForSaveUtil();
}
virtual void RunFrame();
virtual void WriteSteamStats();
protected:
CUtlBuffer m_arrBuffers[2];
int m_idxSaveUtilOwned;
inline CUtlBuffer& GetBufferForSaveUtil() { return m_arrBuffers[ m_idxSaveUtilOwned%2 ]; }
inline CUtlBuffer& GetBufferForSteamData() { return m_arrBuffers[ !(m_idxSaveUtilOwned%2) ]; }
bool FillSteamBuffer();
CPS3SaveRestoreAsyncStatus m_ps3AsyncSaveStatus;
enum AsyncSaveState_t
{
STATE_DEFAULT = 0x00, // default state, no save data ready, no save pending
STATE_DIRTY = 0x01, // save data ready, will trigger saveutil when possible
STATE_INITIATED = 0x10, // saveutil triggered, can still slipstream updated data
STATE_COMMITTING = 0x20, // saveutil committing data, new updates must wait
};
uint32 m_uiState;
uint32 m_numDirtyFrames;
}
g_ps3saveSteamInfoProvider;
IPS3SaveSteamInfoProviderUiGameData * GetPs3SaveSteamInfoProvider()
{
return &g_ps3saveSteamInfoProvider;
}
bool CPS3SaveSteamInfoProvider::FillSteamBuffer()
{
// Write the data into save buffer
CUtlBuffer &buf = GetBufferForSteamData();
#ifndef NO_STEAM
uint32 uiSizeRequired = buf.Size();
bool bResult = steamapicontext->SteamUserStats()->GetUserStatsData( buf.Base(), buf.Size(), &uiSizeRequired );
if ( !bResult && uiSizeRequired > buf.Size() )
{
buf.EnsureCapacity( uiSizeRequired );
bResult = steamapicontext->SteamUserStats()->GetUserStatsData( buf.Base(), buf.Size(), &uiSizeRequired );
}
if ( !bResult )
{
buf.Purge();
return false;
}
else
{
buf.SeekPut( CUtlBuffer::SEEK_HEAD, uiSizeRequired );
return true;
}
#else
buf.Purge();
return true;
#endif
}
void CPS3SaveSteamInfoProvider::RunFrame()
{
// if save has been initiated, see if it has completed already
if ( m_uiState & STATE_INITIATED )
{
if ( m_ps3AsyncSaveStatus.JobDone() )
{
m_uiState &=~( STATE_INITIATED | STATE_COMMITTING );
Msg( "%.3f CPS3SaveSteamInfoProvider::WriteSteamStats completed!\n", Plat_FloatTime() );
GetBufferForSaveUtil().Purge();
}
}
// if we have some new dirty data, then see if we can kick off a save
if ( ( m_uiState & STATE_DIRTY ) && !( m_uiState & STATE_INITIATED ) )
{
if ( m_numDirtyFrames )
-- m_numDirtyFrames;
if ( ps3saveuiapi && !ps3saveuiapi->IsSaveUtilBusy() &&
!m_numDirtyFrames &&
( !CBaseModPanel::GetSingleton().GetWindow( WT_ATTRACTSCREEN ) ||
( ( CAttractScreen * ) CBaseModPanel::GetSingleton().GetWindow( WT_ATTRACTSCREEN ) )->IsGameBootReady() ) )
{
m_ps3AsyncSaveStatus.m_nCurrentOperationTag = kSAVE_TAG_WRITE_STEAMINFO;
ps3saveuiapi->WriteSteamInfo( &m_ps3AsyncSaveStatus );
Msg( "%.3f CPS3SaveSteamInfoProvider::WriteSteamStats kicked off saveutil work\n", Plat_FloatTime() );
m_uiState |= STATE_INITIATED; // we kicked off a save operation successfully
}
}
}
void CPS3SaveSteamInfoProvider::WriteSteamStats()
{
Msg( "%.3f CPS3SaveSteamInfoProvider::WriteSteamStats prepared data\n", Plat_FloatTime() );
m_uiState |= STATE_DIRTY;
m_numDirtyFrames = 3;
}
#endif

View File

@@ -0,0 +1,788 @@
//========= Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "EngineInterface.h"
#include "VGenericPanelList.h"
#include "KeyValues.h"
#include "VFooterPanel.h"
#include "fmtstr.h"
#include "vgui/IBorder.h"
#include "vgui_controls/Label.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/Divider.h"
#include "vgui_controls/CheckButton.h"
#include "vgui_controls/ImagePanel.h"
#include "vgui_controls/ProgressBar.h"
#include "vgui_controls/Label.h"
#include "vgui_controls/TextImage.h"
#include "FileSystem.h"
#include "VAchievements.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// TODO: this is a temporary merge workaround until achievment interfaces get merged properly
// REMOVE THIS BLOCK AFTER ACHIEVEMENTS GET MERGED
#define IAchievementMgr IAchievementMgr_TempMerge_CrashCrash
#define achievementmgr ( ( IAchievementMgr_TempMerge_CrashCrash * ) NULL )
#define ACHIEVEMENT_LOCALIZED_NAME( ach ) g_pVGuiLocalize->Find( CFmtStr( "#%s_T", ach->GetName() ) )
#define ACHIEVEMENT_LOCALIZED_DESC( ach ) g_pVGuiLocalize->Find( CFmtStr( "#%s_D", ach->GetName() ) )
// -- END TODO
using namespace vgui;
using namespace BaseModUI;
KeyValues *g_pPreloadedAchievementListItemLayout = NULL;
#pragma warning( disable : 4800 ) // warning C4800: 'uint64' : forcing value to bool 'true' or 'false' (performance warning)
AchievementListItem::AchievementListItem( IAchievement *pAchievement ) : BaseClass( NULL, "AchievementListItem" )
{
SetProportional( true );
m_LblName = new Label( this, "LblName", "" );
m_LblProgress = new Label( this, "LblProgress", "Progress" );
m_DivTitleDivider = new Divider( this, "DivTitleDivider" );
m_ImgAchievementIcon = new ImagePanel( this, "ImgAchievementIcon" );
m_LblHowTo = new Label( this, "LblHowTo", "" );
m_PrgProgress = new ContinuousProgressBar(this, "PrgProgress" );
m_LblCurrProgress = new Label( this, "LblCurrProgress", "0" );
m_LblGamerscore = new Label( this, "LblGamerScore", "" );
m_pAchievement = NULL;
m_bShowingDetails = false;
SetAchievement( pAchievement );
SetAchievementName( ACHIEVEMENT_LOCALIZED_NAME( pAchievement ) );
SetAchievementHowTo( ACHIEVEMENT_LOCALIZED_DESC( pAchievement ) );
SetAchievementIcon( pAchievement->GetIconPath() );
SetAchievementGoal( pAchievement->GetGoal() );
SetGamerScore( pAchievement->GetPointValue() );
SetAchievementProgress( pAchievement->GetGoal() );
}
//=============================================================================
void AchievementListItem::SetAchievement( IAchievement *pAchievement )
{
if ( !pAchievement )
return;
m_pAchievement = pAchievement;
InvalidateLayout();
}
//=============================================================================
void AchievementListItem::SetAchievementName( const wchar_t* name )
{
m_LblName->SetText(name);
}
//=============================================================================
void AchievementListItem::SetAchievementHowTo( const wchar_t* howTo )
{
m_LblHowTo->SetText(howTo);
}
//=============================================================================
void AchievementListItem::SetAchievementIcon(const char* iconName)
{
m_ImgAchievementIcon->SetShouldScaleImage(true);
m_ImgAchievementIcon->SetImage(iconName);
m_ImgAchievementIcon->SetVisible(true);
}
//=============================================================================
void AchievementListItem::SetAchievementProgress(int progress)
{
m_AchievementProgress = progress;
float fProgress = static_cast<float>(progress) / static_cast<float>(m_AchievementGoal);
char buffer[64];
Q_snprintf(buffer, 63, "%d / %d", m_AchievementProgress, m_AchievementGoal);
m_LblCurrProgress->SetText(buffer);
m_PrgProgress->SetProgress(fProgress);
if(fProgress < 1.0f)
{
fProgress *= 100.0f;
char buffer[8];
Q_snprintf(buffer, 7, "%2.0f%%", fProgress);
}
// For achievements that don't have multiple steps do not display progress bar or progress label
m_PrgProgress->SetVisible( m_AchievementGoal > 1 );
m_LblCurrProgress->SetVisible( m_AchievementGoal > 1 );
InvalidateLayout();
}
//=============================================================================
void AchievementListItem::SetAchievementGoal( int goal )
{
m_AchievementGoal = goal;
// reset the achievement progress to refresh the labels
SetAchievementProgress( m_AchievementProgress );
}
//=============================================================================
void AchievementListItem::SetGamerScore(int score)
{
m_GamerScore = score;
wchar_t buffer[10];
wchar_t num[5];
V_snwprintf( num, ARRAYSIZE(num), L"%d", m_GamerScore );
g_pVGuiLocalize->ConstructString( buffer, sizeof( buffer ), g_pVGuiLocalize->FindSafe( "#L4D360UI_Gamerscore_Progress" ), 1, num );
m_LblGamerscore->SetText( buffer );
m_LblGamerscore->SetVisible( IsX360() && (score>0) );
}
//=============================================================================
int AchievementListItem::GetGoal() const
{
return m_AchievementGoal;
}
//=============================================================================
int AchievementListItem::GetProgress() const
{
return m_AchievementProgress;
}
//=============================================================================
bool AchievementListItem::GetCompleted() const
{
return m_AchievementGoal == m_AchievementProgress;
}
//=============================================================================
int AchievementListItem::GetGamerScore() const
{
return m_GamerScore;
}
//=============================================================================
void AchievementListItem::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
#ifndef _GAMECONSOLE
if ( !m_pAchievement )
return;
if ( !g_pPreloadedAchievementListItemLayout )
{
const char *pszResource = "Resource/UI/BaseModUI/AchievementListItem.res";
g_pPreloadedAchievementListItemLayout = new KeyValues( pszResource );
g_pPreloadedAchievementListItemLayout->LoadFromFile(g_pFullFileSystem, pszResource);
}
LoadControlSettings( "", NULL, g_pPreloadedAchievementListItemLayout );
m_iOriginalTall = GetTall();
SetBgColor(pScheme->GetColor( "Button.BgColor", Color( 32, 32, 32, 255 ) ) );
SetAchievementName( ACHIEVEMENT_LOCALIZED_NAME( m_pAchievement ) );
SetAchievementHowTo( ACHIEVEMENT_LOCALIZED_DESC( m_pAchievement ) );
SetAchievementIcon( m_pAchievement->GetIconPath() );
SetAchievementGoal( m_pAchievement->GetGoal() );
SetGamerScore( m_pAchievement->GetPointValue() );
SetAchievementProgress( m_pAchievement->IsAchieved() ? m_pAchievement->GetGoal() : m_pAchievement->GetCount() );
int iNumComponents = m_pAchievement->GetNumComponents();
if ( iNumComponents > 0 )
{
KeyValues *pLeftTemplate = g_pPreloadedAchievementListItemLayout->FindKey( "ComponentTemplateLeft", true );
KeyValues *pRightTemplate = g_pPreloadedAchievementListItemLayout->FindKey( "ComponentTemplateRight", true );
KeyValues *pLeftCheckmarkTemplate = g_pPreloadedAchievementListItemLayout->FindKey( "CheckmarkTemplateLeft", true );
KeyValues *pRightCheckmarkTemplate = g_pPreloadedAchievementListItemLayout->FindKey( "CheckmarkTemplateRight", true );
uint64 iComponentBits = m_pAchievement->GetComponentBits();
int iNumRows = 0;
for ( int i = 0, iNumComponents = m_pAchievement->GetNumComponents(); i < iNumComponents; i++ )
{
vgui::Label *pLabel = vgui::SETUP_PANEL( new vgui::Label( this, NULL, "" ) );
if ( !pLabel )
continue;
pLabel->ApplySettings( (i%2) == 0 ? pLeftTemplate : pRightTemplate );
pLabel->SetName( CFmtStr( "comp%d", i ) );
pLabel->SetText( g_pVGuiLocalize->FindSafe( m_pAchievement->GetComponentDisplayString(i) ) );
pLabel->SetVisible( false ); //start out hidden
pLabel->SetEnabled( ( iComponentBits & ((uint64) 1 << i) ) );
if ( iComponentBits & ((uint64) 1 << i) )
{
// show a checkmark next to this component
vgui::ImagePanel *pCheckmark = vgui::SETUP_PANEL( new vgui::ImagePanel( this, NULL ) );
if ( pCheckmark )
{
pCheckmark->ApplySettings( (i%2) == 0 ? pLeftCheckmarkTemplate : pRightCheckmarkTemplate );
pCheckmark->SetName( CFmtStr( "check%d", i ) );
pCheckmark->SetVisible( false );
}
}
if ( (i%2) == 0 )
{
iNumRows++;
}
}
if ( iNumRows > 0 )
{
// we have some details, make ourselves tall enough to show the details button
SetTall( m_iOriginalTall + m_flDetailsExtraHeight );
}
vgui::Button *pDetailsButton = dynamic_cast< vgui::Button * >( FindChildByName( "BtnDetails" ) );
if ( pDetailsButton )
{
pDetailsButton->SetVisible( true );
}
vgui::Label *pDetailsLabel = dynamic_cast< vgui::Label * >( FindChildByName( "LblDetails" ) );
if ( pDetailsLabel )
{
pDetailsLabel ->SetVisible( true );
SetControlString( "LblDetails", "#GameUI_ShowDetails" );
}
}
#else
SetBgColor(pScheme->GetColor( "Button.BgColor", Color( 32, 32, 32, 255 ) ) );
#endif
}
//=============================================================================
void AchievementListItem::NavigateTo()
{
BaseClass::NavigateTo();
}
//=============================================================================
void AchievementListItem::PerformLayout( void )
{
BaseClass::PerformLayout();
#ifndef _GAMECONSOLE
uint64 iComponentBits = m_pAchievement->GetComponentBits();
for ( int i=0;i<m_pAchievement->GetNumComponents(); i++ )
{
char buf[120];
Q_snprintf( buf, sizeof(buf), "comp%d", i );
vgui::Label *pLabel = dynamic_cast< vgui::Label * > ( FindChildByName( buf ) );
if ( !pLabel )
continue;
int iRow = i / 2;
int x, y;
pLabel->GetPos( x, y );
y += iRow * pLabel->GetTall();
pLabel->SetPos( x, y );
if ( iComponentBits & ((uint64)1<<i) )
{
// move its associated checkmark next to it
Q_snprintf( buf, sizeof(buf), "check%d", i );
vgui::ImagePanel *pCheckmark = dynamic_cast< vgui::ImagePanel * > ( FindChildByName( buf ) );
if ( pCheckmark )
{
int checkX, checkY;
pCheckmark->GetPos( checkX, checkY );
checkY += iRow * pLabel->GetTall();
pCheckmark->SetPos( checkX, checkY );
}
}
}
#endif
}
//=============================================================================
void AchievementListItem::OnCommand( const char *command )
{
#ifndef _GAMECONSOLE
if ( !Q_strcmp( command, "toggle_details" ) )
{
m_bShowingDetails = !m_bShowingDetails;
uint64 iComponentBits = m_pAchievement->GetComponentBits();
int iNumRows = 0;
for ( int i=0;i<m_pAchievement->GetNumComponents(); i++ )
{
char buf[120];
Q_snprintf( buf, sizeof(buf), "comp%d", i );
vgui::Label *pLabel = dynamic_cast< vgui::Label * > ( FindChildByName( buf ) );
if ( !pLabel )
continue;
pLabel->SetVisible( m_bShowingDetails );
if ( (i%2) == 0 )
{
iNumRows++;
}
if ( iComponentBits & ((uint64)1<<i) )
{
// move its associated checkmark next to it
Q_snprintf( buf, sizeof(buf), "check%d", i );
SetControlVisible( buf, m_bShowingDetails );
}
}
if ( m_bShowingDetails )
{
SetTall( m_iOriginalTall + m_flDetailsExtraHeight + m_flDetailsRowHeight * iNumRows );
SetControlString( "BtnDetails", "-" );
SetControlString( "LblDetails", "#GameUI_HideDetails" );
}
else
{
SetTall( m_iOriginalTall + m_flDetailsExtraHeight );
SetControlString( "BtnDetails", "+" );
SetControlString( "LblDetails", "#GameUI_ShowDetails" );
}
InvalidateLayout();
}
#endif
}
//=============================================================================
void AchievementListItem::OnSizeChanged( int newWide, int newTall )
{
BaseClass::OnSizeChanged( newWide, newTall );
PostActionSignal( new KeyValues( "ChildResized" ) );
}
//=============================================================================
void AchievementListItem::Paint(void)
{
BaseClass::Paint();
}
//=============================================================================
AchievementListItemLabel::AchievementListItemLabel(Panel *parent, const char *panelName):
BaseClass(parent, panelName)
{
SetProportional( true );
m_LblCategory = new Label( this, "LblCategory", "#L4D360UI_Unattained" );
LoadControlSettings("Resource/UI/BaseModUI/AchievementListItemLabel.res");
}
//=============================================================================
AchievementListItemLabel::~AchievementListItemLabel()
{
delete m_LblCategory;
}
//=============================================================================
void AchievementListItemLabel::SetCategory( const wchar_t* category )
{
m_LblCategory->SetText( category );
}
class BaseModUI::AchievementGenericPanelList : public GenericPanelList
{
DECLARE_CLASS_SIMPLE( AchievementGenericPanelList, GenericPanelList );
public:
AchievementGenericPanelList( vgui::Panel *parent, const char *panelName, ITEM_SELECTION_MODE selectionMode, int iControllingSlot ) :
BaseClass( parent, panelName, selectionMode ),
m_iControllingUserSlot( iControllingSlot )
{
}
protected:
void OnKeyCodePressed(KeyCode code)
{
if ( m_iControllingUserSlot != GetJoystickForCode( code ) )
return;
BaseClass::OnKeyCodePressed(code);
}
int m_iControllingUserSlot;
};
//=============================================================================
//
//=============================================================================
Achievements::Achievements(Panel *parent, const char *panelName):
BaseClass(parent, panelName, false, true)
{
// Determine the slot and controller of the player who opened the dialog
m_iStartingUserSlot = CBaseModPanel::GetSingleton().GetLastActiveUserId();
memset( m_wAchievementsTitle, 0, sizeof( m_wAchievementsTitle ) );
if ( IsGameConsole() )
{
// Set the name of the dialog, adding the handle of the initiating user
const wchar_t *pwcTemplate = g_pVGuiLocalize->Find("#L4D360UI_My_Achievements_User");
int iActiveController = XBX_GetUserId( m_iStartingUserSlot );
const char *pszPlayerName = BaseModUI::CUIGameData::Get()->GetLocalPlayerName( iActiveController );
wchar_t wGamerTag[32];
g_pVGuiLocalize->ConvertANSIToUnicode( pszPlayerName, wGamerTag, sizeof( wGamerTag ) );
g_pVGuiLocalize->ConstructString( m_wAchievementsTitle, sizeof( m_wAchievementsTitle ), pwcTemplate, 1, wGamerTag );
}
SetDeleteSelfOnClose(true);
SetProportional( true );
m_LblComplete = new Label(this, "LblComplete", "");
m_LblGamerscore = new Label(this, "LblGamerscore", "");
m_GplAchievements = new AchievementGenericPanelList( this, "GplAchievements", GenericPanelList::ISM_ELEVATOR, m_iStartingUserSlot );
m_GplAchievements->ShowScrollProgress( true );
m_GplAchievements->SetScrollBarVisible( IsPC() );
m_GplAchievements->SetBgColor( Color( 0, 0, 0, 0 ) );
if ( IsGameConsole() )
{
m_GplAwards = new AchievementGenericPanelList( this, "GplAwards", GenericPanelList::ISM_ELEVATOR, m_iStartingUserSlot );
m_GplAwards->ShowScrollProgress( true );
m_GplAwards->SetScrollBarVisible( false );
m_GplAwards->SetBgColor( Color( 0, 0, 0, 0 ) );
}
else
{
m_GplAwards = NULL;
}
m_pProgressBar = new ContinuousProgressBar( this, "ProTotalProgress" );
SetUpperGarnishEnabled(true);
SetFooterEnabled( true );
SetOkButtonEnabled( false );
m_ActiveControl = m_GplAchievements;
LoadControlSettings("Resource/UI/BaseModUI/Achievements.res");
UpdateFooter();
m_bShowingAssets = false;
m_iAwardCompleteCount = 0;
m_iAchCompleteCount = 0;
}
//=============================================================================
Achievements::~Achievements()
{
}
//=============================================================================
void Achievements::Activate()
{
BaseClass::Activate();
// Populate the achievements list.
m_GplAchievements->RemoveAllPanelItems();
if ( !achievementmgr )
return;
m_iAwardCompleteCount = 0;
m_iAchCompleteCount = 0;
int incompleteCount= 0;
int gamerScore = 0;
//
// Add the "Achieved" ones
//
for(int i = 0; i < achievementmgr->GetAchievementCount(); i++)
{
IAchievement* achievement = achievementmgr->GetAchievementByDisplayOrder( i, m_iStartingUserSlot );
if ( achievement && achievement->IsAchieved() )
{
AchievementListItem *panelItem = new AchievementListItem( achievement );
if ( panelItem )
{
m_GplAchievements->AddPanelItem( panelItem, true );
}
gamerScore += achievement->GetPointValue();
++m_iAchCompleteCount;
}
}
//
// Add the "Unattained" ones
//
for(int i = 0; i < achievementmgr->GetAchievementCount(); i++)
{
IAchievement* achievement = achievementmgr->GetAchievementByDisplayOrder( i, m_iStartingUserSlot );
if ( achievement && !achievement->IsAchieved() )
{
AchievementListItem *panelItem = new AchievementListItem( achievement );
if ( panelItem )
{
m_GplAchievements->AddPanelItem( panelItem, true );
}
++incompleteCount;
}
}
// Populate the awards list.
int awardIncompleteCount= 0;
if ( IsGameConsole() )
{
m_GplAwards->RemoveAllPanelItems();
for ( int i = 0; i < achievementmgr->GetAchievementCount( true ); i++ )
{
IAchievement* achievement = achievementmgr->GetAwardByDisplayOrder( i, m_iStartingUserSlot );
if ( achievement && achievement->IsAchieved() )
{
AchievementListItem *panelItem = new AchievementListItem( achievement );
if ( panelItem )
{
m_GplAchievements->AddPanelItem( panelItem, true );
}
gamerScore += achievement->GetPointValue();
++m_iAwardCompleteCount;
}
}
for( int i = 0; i < achievementmgr->GetAchievementCount( true ); i++ )
{
IAchievement* achievement = achievementmgr->GetAwardByDisplayOrder( i, m_iStartingUserSlot );
if ( achievement && !achievement->IsAchieved() )
{
AchievementListItem *panelItem = new AchievementListItem( achievement );
if ( panelItem )
{
m_GplAchievements->AddPanelItem( panelItem, true );
}
++awardIncompleteCount;
}
}
}
if ( m_GplAwards )
{
m_GplAwards->SetVisible( false );
}
//
// Update achievement and gamerscore progress
//
wchar_t localizedGamerscoreProgress[128];
wchar_t wNumAchieved[64];
wchar_t wTotalAchievements[64];
wchar_t wGamerscore[64];
// Construct achievement progress string
Q_snwprintf( wTotalAchievements, sizeof( wTotalAchievements ), L"%d", achievementmgr->GetAchievementCount() );
Q_snwprintf( wNumAchieved, sizeof( wNumAchieved ), L"%d", m_iAchCompleteCount );
g_pVGuiLocalize->ConstructString( m_wAchievementsProgress, sizeof( m_wAchievementsProgress ), g_pVGuiLocalize->Find( "#L4D360UI_Achievement_Progress" ), 2, wNumAchieved, wTotalAchievements );
m_LblComplete->SetText( m_wAchievementsProgress );
// Construct gamerscore progress string
Q_snwprintf( wGamerscore, sizeof( wGamerscore ), L"%d", gamerScore );
g_pVGuiLocalize->ConstructString( localizedGamerscoreProgress, sizeof( localizedGamerscoreProgress ), g_pVGuiLocalize->Find( "#L4D360UI_Gamerscore_Progress" ), 2, wGamerscore );
m_LblGamerscore->SetText( localizedGamerscoreProgress );
// Focus on the first item in the list
m_GplAchievements->NavigateTo();
m_GplAchievements->SelectPanelItem( 0 );
// Set the progress bar
m_flTotalProgress = static_cast<float>(m_iAchCompleteCount) / static_cast<float>(achievementmgr->GetAchievementCount());
UpdateFooter();
ToggleDisplayType( m_bShowingAssets );
}
void Achievements::UpdateFooter()
{
CBaseModFooterPanel *footer = BaseModUI::CBaseModPanel::GetSingleton().GetFooterPanel();
if ( footer )
{
footer->SetButtons( FB_BBUTTON | FB_YBUTTON );
footer->SetButtonText( FB_BBUTTON, "#L4D360UI_Done" );
footer->SetButtonText( FB_YBUTTON, m_bShowingAssets ? "#L4D360UI_ShowAchievements" : "#L4D360UI_ShowUnlockableAwards" );
}
}
//=============================================================================
void Achievements::OnCommand(const char *command)
{
if( V_strcmp( command, "Back" ) == 0 )
{
// Act as though 360 back button was pressed
OnKeyCodePressed( ButtonCodeToJoystickButtonCode( KEY_XBUTTON_B, CBaseModPanel::GetSingleton().GetLastActiveUserId() ) );
m_bShowingAssets = false;
}
else
{
BaseClass::OnCommand( command );
}
}
//=============================================================================
void Achievements::OnKeyCodePressed(KeyCode code)
{
if ( m_iStartingUserSlot != GetJoystickForCode( code ) )
return;
// int iUserSlot = GetJoystickForCode( code );
// CBaseModPanel::GetSingleton().SetLastActiveUserId( iUserSlot );
switch( GetBaseButtonCode( code ) )
{
case KEY_XBUTTON_Y:
ToggleDisplayType( !m_bShowingAssets );
break;
}
BaseClass::OnKeyCodePressed(code);
}
//=============================================================================
void Achievements::ToggleDisplayType( bool bDisplayType )
{
if ( IsPC() )
return;
m_bShowingAssets = bDisplayType;
if ( m_bShowingAssets )
{
m_GplAwards->SetVisible( true );
m_GplAchievements->SetVisible( false );
m_LblGamerscore->SetVisible( false );
m_GplAwards->NavigateTo();
m_GplAwards->SelectPanelItem( 0 );
m_ActiveControl = m_GplAwards;
}
else
{
m_GplAwards->SetVisible( false );
m_GplAchievements->SetVisible( true );
m_LblGamerscore->SetVisible( true );
m_GplAchievements->NavigateTo();
m_GplAchievements->SelectPanelItem( 0 );
m_ActiveControl = m_GplAchievements;
}
m_ActiveControl->SetBgColor( Color( 0, 0, 0, 0 ) );
wchar_t wNumAchieved[64];
wchar_t wTotalAchievements[64];
Q_snwprintf( wTotalAchievements, sizeof( wTotalAchievements ), L"%d", achievementmgr->GetAchievementCount(m_bShowingAssets) );
Q_snwprintf( wNumAchieved, sizeof( wNumAchieved ), L"%d", m_bShowingAssets ? m_iAwardCompleteCount : m_iAchCompleteCount );
g_pVGuiLocalize->ConstructString( m_wAchievementsProgress, sizeof( m_wAchievementsProgress ), g_pVGuiLocalize->Find( "#L4D360UI_Achievement_Progress" ), 2, wNumAchieved, wTotalAchievements );
m_LblComplete->SetText( m_wAchievementsProgress );
m_flTotalProgress = static_cast<float>(m_bShowingAssets ? m_iAwardCompleteCount : m_iAchCompleteCount) / static_cast<float>(achievementmgr->GetAchievementCount(m_bShowingAssets));
m_pProgressBar->SetProgress( m_flTotalProgress );
UpdateFooter();
}
//=============================================================================
void Achievements::ApplySchemeSettings(vgui::IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetPaintBackgroundEnabled( true );
SetupAsDialogStyle();
m_pProgressBar->SetProgress( m_flTotalProgress );
if ( IsGameConsole() )
{
m_pProgressBar->SetVisible( false );
}
}
#ifdef _GAMECONSOLE
void Achievements::NavigateTo()
{
BaseClass::NavigateTo();
if ( m_bShowingAssets )
{
m_GplAwards->NavigateTo();
}
else
{
m_GplAchievements->NavigateTo();
}
}
void Achievements::NavigateFrom()
{
BaseClass::NavigateFrom();
}
#endif // _GAMECONSOLE
//=============================================================================
void Achievements::PaintBackground()
{
if ( IsPC() )
{
BaseClass::DrawDialogBackground( "#L4D360UI_My_Achievements", NULL, "#L4D360UI_My_Achievements_Desc", NULL );
}
else
{
if ( V_wcslen( m_wAchievementsTitle ) > 0 )
{
BaseClass::DrawDialogBackground( NULL, m_wAchievementsTitle, NULL, m_wAchievementsProgress );
}
else
{
BaseClass::DrawDialogBackground( "#L4D360UI_My_Achievements", NULL, NULL, m_wAchievementsProgress );
}
}
}

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