You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
838 lines
22 KiB
838 lines
22 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include "SDKLauncherDialog.h"
|
||
|
#include "configs.h"
|
||
|
|
||
|
#include <vgui_controls/ComboBox.h>
|
||
|
#include <vgui_controls/ListPanel.h>
|
||
|
#include <vgui_controls/ProgressBox.h>
|
||
|
#include <vgui_controls/MessageBox.h>
|
||
|
#include <vgui_controls/HTML.h>
|
||
|
#include <vgui_controls/CheckButton.h>
|
||
|
#include <vgui_controls/Divider.h>
|
||
|
#include <vgui_controls/menu.h>
|
||
|
#include <vgui/ISurface.h>
|
||
|
#include <vgui/ILocalize.h>
|
||
|
#include "vgui_controls/button.h"
|
||
|
#include <vgui/ISystem.h>
|
||
|
#include <vgui/IVGui.h>
|
||
|
#include <vgui/iinput.h>
|
||
|
#include <KeyValues.h>
|
||
|
#include <FileSystem.h>
|
||
|
#include <io.h>
|
||
|
#include "CreateModWizard.h"
|
||
|
#include "filesystem_tools.h"
|
||
|
#include "min_footprint_files.h"
|
||
|
#include "ConfigManager.h"
|
||
|
#include "filesystem_tools.h"
|
||
|
#include <iregistry.h>
|
||
|
|
||
|
#include <sys/stat.h>
|
||
|
#include "sdklauncher_main.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include <tier0/memdbgon.h>
|
||
|
|
||
|
using namespace vgui;
|
||
|
|
||
|
CSDKLauncherDialog *g_pSDKLauncherDialog = NULL;
|
||
|
CGameConfigManager g_ConfigManager;
|
||
|
char g_engineDir[50];
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Retrieves a URL out of the external localization file and opens it in a
|
||
|
// web browser.
|
||
|
// Input : *lpszLocalName - Localized name of the URL to open via shell execution
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void OpenLocalizedURL( const char *lpszLocalName )
|
||
|
{
|
||
|
// Find and convert the localized unicode string
|
||
|
char pURLStr[MAX_PATH];
|
||
|
wchar_t *pURLUni = g_pVGuiLocalize->Find( lpszLocalName );
|
||
|
g_pVGuiLocalize->ConvertUnicodeToANSI( pURLUni, pURLStr, sizeof( pURLStr ) );
|
||
|
|
||
|
// Open the URL through the shell
|
||
|
vgui::system()->ShellExecute( "open", pURLStr );
|
||
|
}
|
||
|
|
||
|
class CResetConfirmationMessageBox : public vgui::Frame
|
||
|
{
|
||
|
public:
|
||
|
typedef vgui::Frame BaseClass;
|
||
|
|
||
|
CResetConfirmationMessageBox( Panel *pParent, const char *pPanelName )
|
||
|
: BaseClass( pParent, pPanelName )
|
||
|
{
|
||
|
SetSize( 200, 200 );
|
||
|
SetMinimumSize( 250, 100 );
|
||
|
SetSizeable( false );
|
||
|
LoadControlSettings( "resetconfirmbox.res" );
|
||
|
}
|
||
|
void OnCommand( const char *command )
|
||
|
{
|
||
|
if ( Q_stricmp( command, "ResetConfigs" ) == 0 )
|
||
|
{
|
||
|
Close();
|
||
|
|
||
|
if ( GetVParent() )
|
||
|
{
|
||
|
PostMessage( GetVParent(), new KeyValues( "Command", "command", "ResetConfigs"));
|
||
|
}
|
||
|
}
|
||
|
else if ( Q_stricmp( command, "MoreInfo" ) == 0 )
|
||
|
{
|
||
|
OpenLocalizedURL( "URL_Reset_Config" );
|
||
|
}
|
||
|
|
||
|
BaseClass::OnCommand( command );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class CConversionInfoMessageBox : public vgui::Frame
|
||
|
{
|
||
|
public:
|
||
|
typedef vgui::Frame BaseClass;
|
||
|
|
||
|
CConversionInfoMessageBox( Panel *pParent, const char *pPanelName )
|
||
|
: BaseClass( pParent, pPanelName )
|
||
|
{
|
||
|
SetSize( 200, 200 );
|
||
|
SetMinimumSize( 250, 100 );
|
||
|
SetSizeable( false );
|
||
|
LoadControlSettings( "convinfobox.res" );
|
||
|
}
|
||
|
|
||
|
virtual void OnCommand( const char *command )
|
||
|
{
|
||
|
BaseClass::OnCommand( command );
|
||
|
|
||
|
// For some weird reason, this dialog can
|
||
|
if ( Q_stricmp( command, "ShowFAQ" ) == 0 )
|
||
|
{
|
||
|
OpenLocalizedURL( "URL_Convert_INI" );
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class CGameInfoMessageBox : public vgui::Frame
|
||
|
{
|
||
|
public:
|
||
|
typedef vgui::Frame BaseClass;
|
||
|
|
||
|
CGameInfoMessageBox( Panel *pParent, const char *pPanelName )
|
||
|
: BaseClass( pParent, pPanelName )
|
||
|
{
|
||
|
SetSize( 200, 200 );
|
||
|
SetMinimumSize( 250, 100 );
|
||
|
|
||
|
LoadControlSettings( "hl2infobox.res" );
|
||
|
}
|
||
|
|
||
|
virtual void OnCommand( const char *command )
|
||
|
{
|
||
|
BaseClass::OnCommand( command );
|
||
|
|
||
|
// For some weird reason, this dialog can
|
||
|
if ( Q_stricmp( command, "RunAnyway" ) == 0 )
|
||
|
{
|
||
|
m_pDialog->Launch( m_iActiveItem, true );
|
||
|
MarkForDeletion();
|
||
|
}
|
||
|
else if ( Q_stricmp( command, "Troubleshooting" ) == 0 )
|
||
|
{
|
||
|
OpenLocalizedURL( "URL_SDK_FAQ" );
|
||
|
MarkForDeletion();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CSDKLauncherDialog *m_pDialog;
|
||
|
int m_iActiveItem;
|
||
|
};
|
||
|
|
||
|
class CMinFootprintRefreshConfirmationDialog : public vgui::Frame
|
||
|
{
|
||
|
public:
|
||
|
typedef vgui::Frame BaseClass;
|
||
|
|
||
|
CMinFootprintRefreshConfirmationDialog( Panel *pParent, const char *pPanelName )
|
||
|
: BaseClass( pParent, pPanelName )
|
||
|
{
|
||
|
SetSizeable( false );
|
||
|
LoadControlSettings( "min_footprint_confirm_box.res" );
|
||
|
|
||
|
m_hOldModalSurface = input()->GetAppModalSurface();
|
||
|
input()->SetAppModalSurface( GetVPanel() );
|
||
|
}
|
||
|
~CMinFootprintRefreshConfirmationDialog()
|
||
|
{
|
||
|
input()->SetAppModalSurface( m_hOldModalSurface );
|
||
|
}
|
||
|
|
||
|
void OnCommand( const char *command )
|
||
|
{
|
||
|
BaseClass::OnCommand( command );
|
||
|
|
||
|
if ( Q_stricmp( command, "Continue" ) == 0 )
|
||
|
{
|
||
|
PostMessage( g_pSDKLauncherDialog, new KeyValues( "Command", "command", "RefreshMinFootprint" ) );
|
||
|
MarkForDeletion();
|
||
|
}
|
||
|
else if ( Q_stricmp( command, "Close" ) == 0 )
|
||
|
{
|
||
|
MarkForDeletion();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VPANEL m_hOldModalSurface;
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Constructor
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CSDKLauncherDialog::CSDKLauncherDialog(vgui::Panel *parent, const char *name) : BaseClass(parent, name)
|
||
|
{
|
||
|
Assert( !g_pSDKLauncherDialog );
|
||
|
g_pSDKLauncherDialog = this;
|
||
|
|
||
|
SetSize(384, 480);
|
||
|
SetMinimumSize(250, 200);
|
||
|
|
||
|
SetMinimizeButtonVisible( true );
|
||
|
m_pImageList = new ImageList( true );
|
||
|
|
||
|
m_pMediaList = new SectionedListPanel(this, "MediaList");
|
||
|
m_pMediaList->AddActionSignalTarget( this );
|
||
|
m_pMediaList->SetImageList( m_pImageList, true );
|
||
|
|
||
|
m_pContextMenu = new Menu( m_pMediaList, "AppsContextMenu" );
|
||
|
|
||
|
m_pCurrentGameCombo = new ComboBox( this, "CurrentGameList", 8, false );
|
||
|
m_pCurrentGameCombo->AddActionSignalTarget( this );
|
||
|
|
||
|
m_pCurrentEngineCombo = new ComboBox( this, "CurrentEngineList", 4, false );
|
||
|
m_pCurrentEngineCombo->AddActionSignalTarget( this );
|
||
|
|
||
|
PopulateMediaList();
|
||
|
|
||
|
LoadControlSettings( "SDKLauncherDialog.res" );
|
||
|
|
||
|
GetEngineVersion( g_engineDir, sizeof( g_engineDir ) );
|
||
|
|
||
|
PopulateCurrentEngineCombo( false );
|
||
|
|
||
|
RefreshConfigs();
|
||
|
}
|
||
|
|
||
|
CSDKLauncherDialog::~CSDKLauncherDialog()
|
||
|
{
|
||
|
delete m_pMediaList;
|
||
|
g_pSDKLauncherDialog = NULL;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: kills the whole app on close
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CSDKLauncherDialog::OnClose()
|
||
|
{
|
||
|
BaseClass::OnClose();
|
||
|
ivgui()->Stop();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: loads media list from file
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CSDKLauncherDialog::PopulateMediaList()
|
||
|
{
|
||
|
KeyValues *dataFile = new KeyValues("Media");
|
||
|
dataFile->UsesEscapeSequences( true );
|
||
|
|
||
|
if (dataFile->LoadFromFile( g_pFullFileSystem, "MediaList.txt", NULL ) )
|
||
|
{
|
||
|
// Load all the images.
|
||
|
KeyValues *pImages = dataFile->FindKey( "Images" );
|
||
|
if ( !pImages )
|
||
|
Error( "MediaList.txt missing Images key." );
|
||
|
|
||
|
for ( KeyValues *pCur=pImages->GetFirstTrueSubKey(); pCur; pCur=pCur->GetNextTrueSubKey() )
|
||
|
{
|
||
|
IImage *pImage = scheme()->GetImage( pCur->GetString( "Image", "" ), false );
|
||
|
int iIndex = pCur->GetInt( "Index", -1 );
|
||
|
if ( pImage && iIndex != -1 )
|
||
|
{
|
||
|
m_pImageList->SetImageAtIndex( iIndex, pImage );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Load all the sections.
|
||
|
KeyValues *pSections = dataFile->FindKey( "Sections" );
|
||
|
if ( !pSections )
|
||
|
Error( "MediaList.txt missing Sections key." );
|
||
|
|
||
|
for ( KeyValues *pSection=pSections->GetFirstTrueSubKey(); pSection; pSection=pSection->GetNextTrueSubKey() )
|
||
|
{
|
||
|
int id = pSection->GetInt( "id" );
|
||
|
const char *pName = pSection->GetString( "Name" );
|
||
|
m_pMediaList->AddSection( id, pName );
|
||
|
m_pMediaList->AddColumnToSection( id, "Image", "", SectionedListPanel::COLUMN_IMAGE, 20 );
|
||
|
m_pMediaList->AddColumnToSection( id, "Text", pName, 0, 200 );
|
||
|
|
||
|
// Set all the rows.
|
||
|
for ( KeyValues *kv = pSection->GetFirstTrueSubKey(); kv != NULL; kv=kv->GetNextTrueSubKey() )
|
||
|
{
|
||
|
m_pMediaList->AddItem( id, kv );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dataFile->deleteThis();
|
||
|
}
|
||
|
|
||
|
void CSDKLauncherDialog::Launch( int hActiveListItem, bool bForce )
|
||
|
{
|
||
|
if (!m_pMediaList->IsItemIDValid(hActiveListItem))
|
||
|
return;
|
||
|
|
||
|
// display the file
|
||
|
KeyValues *item = m_pMediaList->GetItemData( hActiveListItem );
|
||
|
if ( !item )
|
||
|
return;
|
||
|
|
||
|
// Is this a ShellExecute or a program they want to run?
|
||
|
const char *pStr = item->GetString( "InlineProgram", NULL );
|
||
|
if ( pStr )
|
||
|
{
|
||
|
if ( Q_stricmp( pStr, "CreateMod" ) == 0 )
|
||
|
{
|
||
|
if ( !V_stricmp( g_engineDir, "ep1" ) || !V_stricmp( g_engineDir, "source2007" ) )
|
||
|
{
|
||
|
RunCreateModWizard( false );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
VGUIMessageBox( this, "Unable to Run 'Create A Mod' Wizard", "Support for creating total conversions are not available using this engine versions." );
|
||
|
}
|
||
|
}
|
||
|
else if ( Q_stricmp( pStr, "refresh_min_footprint" ) == 0 )
|
||
|
{
|
||
|
CMinFootprintRefreshConfirmationDialog *pDlg = new CMinFootprintRefreshConfirmationDialog( this, "RefreshConfirmation" );
|
||
|
|
||
|
pDlg->RequestFocus();
|
||
|
pDlg->SetVisible( true );
|
||
|
pDlg->MoveToCenterOfScreen();
|
||
|
}
|
||
|
else if ( Q_stricmp( pStr, "reset_configs" ) == 0 )
|
||
|
{
|
||
|
CResetConfirmationMessageBox *pDlg = new CResetConfirmationMessageBox( this, "ResetConfirmation" );
|
||
|
|
||
|
pDlg->RequestFocus();
|
||
|
pDlg->SetVisible( true );
|
||
|
pDlg->MoveToCenterOfScreen();
|
||
|
input()->SetAppModalSurface( pDlg->GetVPanel() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Error( "Unknown InlineProgram value: %s", pStr );
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pStr = item->GetString( "ShellExecute", NULL );
|
||
|
if ( pStr )
|
||
|
{
|
||
|
// Replace tokens we know about like %basedir%.
|
||
|
system()->ShellExecute( "open", pStr );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pStr = item->GetString( "Program", NULL );
|
||
|
if ( pStr )
|
||
|
{
|
||
|
// Get our current config.
|
||
|
KeyValues *kv = m_pCurrentGameCombo->GetActiveItemUserData();
|
||
|
if ( !kv )
|
||
|
{
|
||
|
VGUIMessageBox( this, "Error", "No game configurations to run with." );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const char *pModDir = kv->GetString( "ModDir", NULL );
|
||
|
if ( !pModDir )
|
||
|
{
|
||
|
VGUIMessageBox( this, "Error", "Missing 'ModDir' key/value." );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool bRun = true;
|
||
|
if ( !bForce && Q_stristr( pStr, "%gamedir%" ) )
|
||
|
{
|
||
|
// Make sure the currently-selected gamedir is valid and has a gameinfo.txt in it.
|
||
|
char testStr[MAX_PATH];
|
||
|
Q_strncpy( testStr, pModDir, sizeof( testStr ) );
|
||
|
Q_AppendSlash( testStr, sizeof( testStr ) );
|
||
|
Q_strncat( testStr, "gameinfo.txt", sizeof( testStr ), COPY_ALL_CHARACTERS );
|
||
|
if ( _access( testStr, 0 ) != 0 )
|
||
|
{
|
||
|
CGameInfoMessageBox *dlg = new CGameInfoMessageBox( this, "GameInfoMessageBox" );
|
||
|
|
||
|
dlg->m_pDialog = this;
|
||
|
dlg->m_iActiveItem = hActiveListItem;
|
||
|
|
||
|
dlg->RequestFocus();
|
||
|
dlg->SetVisible( true );
|
||
|
dlg->MoveToCenterOfScreen();
|
||
|
input()->SetAppModalSurface( dlg->GetVPanel() );
|
||
|
|
||
|
bRun = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( bRun )
|
||
|
{
|
||
|
// Get the program name and its arguments.
|
||
|
char programNameTemp[1024], programName[1024], launchDirectory[1024];
|
||
|
|
||
|
SubstituteBaseDir( pStr, programNameTemp, sizeof( programNameTemp ) );
|
||
|
V_StrSubst( programNameTemp, "%gamedir%", pModDir, programName, sizeof( programName ) );
|
||
|
V_strncpy( programNameTemp, programName, sizeof( programNameTemp ) );
|
||
|
V_StrSubst( programNameTemp, "%enginedir%", g_engineDir , programName, sizeof( programName ) );
|
||
|
|
||
|
V_strncpy( launchDirectory, GetSDKLauncherBaseDirectory(), sizeof( launchDirectory ) );
|
||
|
V_strncat( launchDirectory, "\\bin\\", sizeof( launchDirectory ) );
|
||
|
V_strncat( launchDirectory, g_engineDir, sizeof( launchDirectory ) );
|
||
|
|
||
|
// Check to see if we're running in tools mode
|
||
|
if ( NULL != V_strstr( programName, "-tools" ) )
|
||
|
{
|
||
|
// We can't run tools mode in engine versions earlier than OB
|
||
|
if ( !V_strcmp( g_engineDir, "ep1" ) )
|
||
|
{
|
||
|
VGUIMessageBox( this, "Error", "Source Engine Tools is not compatible with the selected engine version." );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// If we are running the engine tools then change our launch directory to the game directory
|
||
|
V_strncpy( launchDirectory, pModDir, sizeof( launchDirectory ) );
|
||
|
V_StripLastDir( launchDirectory, sizeof( launchDirectory ) );
|
||
|
V_strncat( launchDirectory, "bin", sizeof( launchDirectory ) );
|
||
|
}
|
||
|
|
||
|
STARTUPINFO si;
|
||
|
memset( &si, 0, sizeof( si ) );
|
||
|
si.cb = sizeof( si );
|
||
|
|
||
|
PROCESS_INFORMATION pi;
|
||
|
memset( &pi, 0, sizeof( pi ) );
|
||
|
|
||
|
|
||
|
DWORD dwFlags = 0;
|
||
|
if ( !CreateProcess(
|
||
|
0,
|
||
|
programName,
|
||
|
NULL, // security
|
||
|
NULL,
|
||
|
TRUE,
|
||
|
dwFlags, // flags
|
||
|
NULL, // environment
|
||
|
launchDirectory, // current directory
|
||
|
&si,
|
||
|
&pi ) )
|
||
|
{
|
||
|
::MessageBoxA( NULL, GetLastWindowsErrorString(), "Error", MB_OK | MB_ICONINFORMATION | MB_APPLMODAL );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CSDKLauncherDialog::OnCommand( const char *command )
|
||
|
{
|
||
|
if ( Q_stricmp( command, "LaunchButton" ) == 0 )
|
||
|
{
|
||
|
Launch( m_pMediaList->GetSelectedItem(), false );
|
||
|
}
|
||
|
else if ( Q_stricmp( command, "ResetConfigs" ) == 0 )
|
||
|
{
|
||
|
ResetConfigs();
|
||
|
}
|
||
|
else if ( Q_stricmp( command, "RefreshMinFootprint" ) == 0 )
|
||
|
{
|
||
|
DumpMinFootprintFiles( true );
|
||
|
}
|
||
|
|
||
|
BaseClass::OnCommand( command );
|
||
|
}
|
||
|
|
||
|
|
||
|
void CSDKLauncherDialog::OnItemDoubleLeftClick( int iItem )
|
||
|
{
|
||
|
Launch( iItem, false );
|
||
|
}
|
||
|
|
||
|
|
||
|
void CSDKLauncherDialog::OnItemContextMenu( int hActiveListItem )
|
||
|
{
|
||
|
if (!m_pMediaList->IsItemIDValid(hActiveListItem))
|
||
|
return;
|
||
|
|
||
|
// display the file
|
||
|
KeyValues *item = m_pMediaList->GetItemData( hActiveListItem );
|
||
|
if ( !item )
|
||
|
return;
|
||
|
|
||
|
// Build the context menu.
|
||
|
m_pContextMenu->DeleteAllItems();
|
||
|
|
||
|
// Is this a ShellExecute or a program they want to run?
|
||
|
const char *pStr = item->GetString( "ShellExecute", NULL );
|
||
|
if ( pStr )
|
||
|
m_pContextMenu->AddMenuItem( "RunGame", "Open In Web Browser", new KeyValues("ItemDoubleLeftClick", "itemID", hActiveListItem), this);
|
||
|
else
|
||
|
m_pContextMenu->AddMenuItem( "RunGame", "Launch", new KeyValues("ItemDoubleLeftClick", "itemID", hActiveListItem), this);
|
||
|
|
||
|
int menuWide, menuTall;
|
||
|
m_pContextMenu->SetVisible(true);
|
||
|
m_pContextMenu->InvalidateLayout(true);
|
||
|
m_pContextMenu->GetSize(menuWide, menuTall);
|
||
|
|
||
|
// work out where the cursor is and therefore the best place to put the menu
|
||
|
int wide, tall;
|
||
|
surface()->GetScreenSize(wide, tall);
|
||
|
|
||
|
int cx, cy;
|
||
|
input()->GetCursorPos(cx, cy);
|
||
|
|
||
|
if (wide - menuWide > cx)
|
||
|
{
|
||
|
// menu hanging right
|
||
|
if (tall - menuTall > cy)
|
||
|
{
|
||
|
// menu hanging down
|
||
|
m_pContextMenu->SetPos(cx, cy);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// menu hanging up
|
||
|
m_pContextMenu->SetPos(cx, cy - menuTall);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// menu hanging left
|
||
|
if (tall - menuTall > cy)
|
||
|
{
|
||
|
// menu hanging down
|
||
|
m_pContextMenu->SetPos(cx - menuWide, cy);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// menu hanging up
|
||
|
m_pContextMenu->SetPos(cx - menuWide, cy - menuTall);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_pContextMenu->RequestFocus();
|
||
|
m_pContextMenu->MoveToFront();
|
||
|
}
|
||
|
|
||
|
bool CSDKLauncherDialog::ParseConfigs( CUtlVector<CGameConfig*> &configs )
|
||
|
{
|
||
|
if ( !g_ConfigManager.IsLoaded() )
|
||
|
return false;
|
||
|
|
||
|
// Find the games block of the keyvalues
|
||
|
KeyValues *gameBlock = g_ConfigManager.GetGameBlock();
|
||
|
|
||
|
if ( gameBlock == NULL )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Iterate through all subkeys
|
||
|
for ( KeyValues *pGame=gameBlock->GetFirstTrueSubKey(); pGame; pGame=pGame->GetNextTrueSubKey() )
|
||
|
{
|
||
|
const char *pName = pGame->GetName();
|
||
|
const char *pDir = pGame->GetString( TOKEN_GAME_DIRECTORY );
|
||
|
|
||
|
CGameConfig *newConfig = new CGameConfig();
|
||
|
UtlStrcpy( newConfig->m_Name, pName );
|
||
|
UtlStrcpy( newConfig->m_ModDir, pDir );
|
||
|
|
||
|
configs.AddToTail( newConfig );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void CSDKLauncherDialog::PopulateCurrentEngineCombo( bool bSelectLast )
|
||
|
{
|
||
|
int nActiveEngine = 0;
|
||
|
|
||
|
m_pCurrentEngineCombo->DeleteAllItems();
|
||
|
|
||
|
// Add ep1 engine
|
||
|
KeyValues *kv = new KeyValues( "values" );
|
||
|
kv = new KeyValues( "values" );
|
||
|
kv->SetString( "EngineVer", "ep1" );
|
||
|
m_pCurrentEngineCombo->AddItem( "Source Engine 2006", kv );
|
||
|
kv->deleteThis();
|
||
|
if ( !V_strcmp( g_engineDir, "ep1" ) )
|
||
|
{
|
||
|
nActiveEngine = 0;
|
||
|
}
|
||
|
|
||
|
// Add ep2 engine
|
||
|
kv = new KeyValues( "values" );
|
||
|
kv->SetString( "EngineVer", "source2007" );
|
||
|
m_pCurrentEngineCombo->AddItem( "Source Engine 2007", kv );
|
||
|
kv->deleteThis();
|
||
|
if ( !V_strcmp( g_engineDir, "source2007" ) )
|
||
|
{
|
||
|
nActiveEngine = 1;
|
||
|
}
|
||
|
|
||
|
// Add SP engine
|
||
|
kv = new KeyValues( "values" );
|
||
|
kv->SetString( "EngineVer", "source2009" );
|
||
|
m_pCurrentEngineCombo->AddItem( "Source Engine 2009", kv );
|
||
|
kv->deleteThis();
|
||
|
if ( !V_strcmp( g_engineDir, "source2009" ) )
|
||
|
{
|
||
|
nActiveEngine = 2;
|
||
|
}
|
||
|
|
||
|
// Add MP engine
|
||
|
kv = new KeyValues( "values" );
|
||
|
kv->SetString( "EngineVer", "orangebox" );
|
||
|
m_pCurrentEngineCombo->AddItem( "Source Engine MP", kv );
|
||
|
kv->deleteThis();
|
||
|
if ( !V_strcmp( g_engineDir, "orangebox" ) )
|
||
|
{
|
||
|
nActiveEngine = 3;
|
||
|
}
|
||
|
|
||
|
// Determine active configuration
|
||
|
m_pCurrentEngineCombo->ActivateItem( nActiveEngine );
|
||
|
}
|
||
|
|
||
|
void CSDKLauncherDialog::SetCurrentGame( const char* pcCurrentGame )
|
||
|
{
|
||
|
int activeConfig = -1;
|
||
|
|
||
|
for ( int i=0; i < m_pCurrentGameCombo->GetItemCount(); i++ )
|
||
|
{
|
||
|
KeyValues *kv = m_pCurrentGameCombo->GetItemUserData( i );
|
||
|
|
||
|
// Check to see if this is our currently active game
|
||
|
if ( Q_stricmp( kv->GetString( "ModDir" ), pcCurrentGame ) == 0 )
|
||
|
{
|
||
|
activeConfig = i;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( activeConfig > -1 )
|
||
|
{
|
||
|
// Activate our currently selected game
|
||
|
m_pCurrentGameCombo->ActivateItem( activeConfig );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// If the VCONFIG value for the game is not found then repopulate
|
||
|
PopulateCurrentGameCombo( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CSDKLauncherDialog::PopulateCurrentGameCombo( bool bSelectLast )
|
||
|
{
|
||
|
m_pCurrentGameCombo->DeleteAllItems();
|
||
|
|
||
|
CUtlVector<CGameConfig*> configs;
|
||
|
|
||
|
ParseConfigs( configs );
|
||
|
|
||
|
char szGame[MAX_PATH];
|
||
|
GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGame, sizeof( szGame ) );
|
||
|
|
||
|
int activeConfig = -1;
|
||
|
|
||
|
CUtlVector<int> itemIDs;
|
||
|
itemIDs.SetSize( configs.Count() );
|
||
|
for ( int i=0; i < configs.Count(); i++ )
|
||
|
{
|
||
|
KeyValues *kv = new KeyValues( "values" );
|
||
|
kv->SetString( "ModDir", configs[i]->m_ModDir.Base() );
|
||
|
kv->SetPtr( "panel", m_pCurrentGameCombo );
|
||
|
|
||
|
|
||
|
// Check to see if this is our currently active game
|
||
|
if ( Q_stricmp( configs[i]->m_ModDir.Base(), szGame ) == 0 )
|
||
|
{
|
||
|
activeConfig = i;
|
||
|
}
|
||
|
|
||
|
itemIDs[i] = m_pCurrentGameCombo->AddItem( configs[i]->m_Name.Base(), kv );
|
||
|
|
||
|
kv->deleteThis();
|
||
|
}
|
||
|
|
||
|
// Activate the correct entry if valid
|
||
|
if ( itemIDs.Count() > 0 )
|
||
|
{
|
||
|
m_pCurrentGameCombo->SetEnabled( true );
|
||
|
|
||
|
if ( bSelectLast )
|
||
|
{
|
||
|
m_pCurrentGameCombo->ActivateItem( itemIDs[itemIDs.Count()-1] );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( activeConfig > -1 )
|
||
|
{
|
||
|
// Activate our currently selected game
|
||
|
m_pCurrentGameCombo->ActivateItem( activeConfig );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Always default to the first otherwise
|
||
|
m_pCurrentGameCombo->ActivateItem( 0 );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pCurrentGameCombo->SetEnabled( false );
|
||
|
}
|
||
|
|
||
|
configs.PurgeAndDeleteElements();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Selection has changed in the active config drop-down, set the environment
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CSDKLauncherDialog::OnTextChanged( KeyValues *pkv )
|
||
|
{
|
||
|
const vgui::ComboBox* combo = (vgui::ComboBox*)pkv->GetPtr("panel");
|
||
|
|
||
|
if ( combo == m_pCurrentGameCombo)
|
||
|
{
|
||
|
KeyValues *kv = m_pCurrentGameCombo->GetActiveItemUserData();
|
||
|
|
||
|
if ( kv )
|
||
|
{
|
||
|
const char *modDir = kv->GetString( "ModDir" );
|
||
|
SetVConfigRegistrySetting( GAMEDIR_TOKEN, modDir, true );
|
||
|
}
|
||
|
}
|
||
|
else if ( combo == m_pCurrentEngineCombo )
|
||
|
{
|
||
|
KeyValues *kv = m_pCurrentEngineCombo->GetActiveItemUserData();
|
||
|
|
||
|
if ( kv )
|
||
|
{
|
||
|
const char *engineDir = kv->GetString( "EngineVer" );
|
||
|
SetEngineVersion( engineDir );
|
||
|
RefreshConfigs();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Refresh our configs after a file change outside our process
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CSDKLauncherDialog::RefreshConfigs( void )
|
||
|
{
|
||
|
char szGameConfigDir[MAX_PATH];
|
||
|
|
||
|
V_strcpy_safe( szGameConfigDir, GetSDKLauncherBinDirectory() );
|
||
|
V_AppendSlash( szGameConfigDir, MAX_PATH );
|
||
|
V_strncat( szGameConfigDir, g_engineDir, MAX_PATH );
|
||
|
V_AppendSlash( szGameConfigDir, MAX_PATH );
|
||
|
V_strncat( szGameConfigDir, "bin", MAX_PATH );
|
||
|
|
||
|
// Set directory in which GameConfig.txt is found
|
||
|
g_ConfigManager.SetBaseDirectory( szGameConfigDir );
|
||
|
|
||
|
// Tell the config manager which games to put in the config by default
|
||
|
if ( !stricmp( g_engineDir, "ep1" ) )
|
||
|
{
|
||
|
g_ConfigManager.SetSDKEpoch( EP1 );
|
||
|
}
|
||
|
else if ( !stricmp( g_engineDir, "source2007" ) )
|
||
|
{
|
||
|
g_ConfigManager.SetSDKEpoch( EP2 );
|
||
|
}
|
||
|
else if ( !stricmp( g_engineDir, "source2009" ) )
|
||
|
{
|
||
|
g_ConfigManager.SetSDKEpoch( SP2009 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
g_ConfigManager.SetSDKEpoch( MP2009 );
|
||
|
}
|
||
|
|
||
|
|
||
|
// Load configurations
|
||
|
if ( g_ConfigManager.LoadConfigs( szGameConfigDir ) == false )
|
||
|
{
|
||
|
m_pCurrentGameCombo->DeleteAllItems();
|
||
|
m_pCurrentGameCombo->SetEnabled( false );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pCurrentGameCombo->SetEnabled( true );
|
||
|
|
||
|
if ( g_ConfigManager.WasConvertedOnLoad() )
|
||
|
{
|
||
|
// Notify of a conversion
|
||
|
CConversionInfoMessageBox *pDlg = new CConversionInfoMessageBox( this, "ConversionInfo" );
|
||
|
|
||
|
pDlg->RequestFocus();
|
||
|
pDlg->SetVisible( true );
|
||
|
pDlg->MoveToCenterOfScreen();
|
||
|
input()->SetAppModalSurface( pDlg->GetVPanel() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Dump the current settings and reparse the change
|
||
|
PopulateCurrentGameCombo( false );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Reset our config files
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CSDKLauncherDialog::ResetConfigs( void )
|
||
|
{
|
||
|
// Reset the configs
|
||
|
g_ConfigManager.ResetConfigs();
|
||
|
|
||
|
// Refresh the listing
|
||
|
PopulateCurrentGameCombo( false );
|
||
|
|
||
|
// Notify the user
|
||
|
VGUIMessageBox( this, "Complete", "Your game configurations have successfully been reset to their default values." );
|
||
|
}
|
||
|
|
||
|
void CSDKLauncherDialog::GetEngineVersion(char* pcEngineVer, int nSize)
|
||
|
{
|
||
|
IRegistry *reg = InstanceRegistry( "Source SDK" );
|
||
|
Assert( reg );
|
||
|
V_strncpy( pcEngineVer, reg->ReadString( "EngineVer", "orangebox" ), nSize );
|
||
|
ReleaseInstancedRegistry( reg );
|
||
|
}
|
||
|
|
||
|
void CSDKLauncherDialog::SetEngineVersion(const char *pcEngineVer)
|
||
|
{
|
||
|
IRegistry *reg = InstanceRegistry( "Source SDK" );
|
||
|
Assert( reg );
|
||
|
reg->WriteString( "EngineVer", pcEngineVer );
|
||
|
ReleaseInstancedRegistry( reg );
|
||
|
|
||
|
// Set the global to the same value as the registry
|
||
|
V_strncpy( g_engineDir, pcEngineVer, sizeof( g_engineDir ) );
|
||
|
}
|