diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/vconfig | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/vconfig')
| -rw-r--r-- | utils/vconfig/ManageGamesDialog.cpp | 203 | ||||
| -rw-r--r-- | utils/vconfig/ManageGamesDialog.h | 54 | ||||
| -rw-r--r-- | utils/vconfig/VConfig.rc | 73 | ||||
| -rw-r--r-- | utils/vconfig/VConfigDialog.cpp | 310 | ||||
| -rw-r--r-- | utils/vconfig/VConfigDialog.h | 59 | ||||
| -rw-r--r-- | utils/vconfig/icon1.ico | bin | 0 -> 19030 bytes | |||
| -rw-r--r-- | utils/vconfig/icon2.ico | bin | 0 -> 19030 bytes | |||
| -rw-r--r-- | utils/vconfig/main.cpp | 646 | ||||
| -rw-r--r-- | utils/vconfig/resource.h | 18 | ||||
| -rw-r--r-- | utils/vconfig/vconfig.vpc | 63 | ||||
| -rw-r--r-- | utils/vconfig/vconfig_main.h | 57 |
11 files changed, 1483 insertions, 0 deletions
diff --git a/utils/vconfig/ManageGamesDialog.cpp b/utils/vconfig/ManageGamesDialog.cpp new file mode 100644 index 0000000..f3706e6 --- /dev/null +++ b/utils/vconfig/ManageGamesDialog.cpp @@ -0,0 +1,203 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include <windows.h> +#include <vgui/IVGui.h> +#include <vgui_controls/DirectorySelectDialog.h> +#include <vgui/IInput.h> +#include <KeyValues.h> + +#include "vconfig_main.h" +#include "ManageGamesDialog.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +using namespace vgui; + +CManageGamesDialog *g_pManageGamesDialog = NULL; + +class CModalDirectorySelectDialog : public vgui::DirectorySelectDialog +{ +public: + CModalDirectorySelectDialog( vgui::Panel *parent, const char *title ) + : vgui::DirectorySelectDialog( parent, title ) + { + m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface(); + } + + ~CModalDirectorySelectDialog( void ) + { + vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel ); + } + + +public: + vgui::VPANEL m_PrevAppFocusPanel; +}; + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CManageGamesDialog::CManageGamesDialog( Panel *parent, const char *name, int configID ) : BaseClass( parent, name ), m_nConfigID( configID ) +{ + Assert( !g_pManageGamesDialog ); + g_pManageGamesDialog = this; + + SetSize(384, 420); + SetMinimumSize(200, 50); + + SetMinimizeButtonVisible( false ); + + m_pGameNameEntry= new vgui::TextEntry( this, "GameName" ); + m_pGameDirEntry = new vgui::TextEntry( this, "GamePath" ); + + LoadControlSettings( "ManageGamesDialog.res" ); + + SetDeleteSelfOnClose( true ); + + SetSizeable( false ); + MoveToCenterOfScreen(); +} + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- +CManageGamesDialog::~CManageGamesDialog( void ) +{ + g_pManageGamesDialog = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Sets the game directory +//----------------------------------------------------------------------------- +void CManageGamesDialog::SetGameDir( const char *szDir ) +{ + // Strip any trailing slashes + char szGameDir[MAX_PATH]; + Q_strncpy( szGameDir, szDir, MAX_PATH ); + Q_StripTrailingSlash( szGameDir ); + + m_pGameDirEntry->SetText( szGameDir ); +} + +//----------------------------------------------------------------------------- +// Purpose: Set the game name +//----------------------------------------------------------------------------- +void CManageGamesDialog::SetGameName( const char *szDir ) +{ + m_pGameNameEntry->SetText( szDir ); +} + +//----------------------------------------------------------------------------- +// Purpose: Ensures the parameter name is unique +// Input : *name - name to test +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CManageGamesDialog::IsGameNameUnique( const char *name ) +{ + // Check all names + for ( int i = 0; i < g_Configs.Count(); i++ ) + { + // Skip ourself + if ( i == m_nConfigID ) + continue; + + // Test it + if ( Q_stricmp( name, g_Configs[i]->m_Name.Base() ) == 0 ) + return false; + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Handles dialog commands +//----------------------------------------------------------------------------- +void CManageGamesDialog::OnCommand( const char *command ) +{ + // Handle "OK" button + if ( Q_stricmp( command, "Select" ) == 0 ) + { + char textBuffer[1024]; + + // Save out the data + m_pGameNameEntry->GetText( textBuffer, sizeof( textBuffer ) ); + + // Make sure we're not setting this to a duplicate + if ( IsGameNameUnique( textBuffer ) == false ) + { + // Select the text + m_pGameNameEntry->SelectAllText( true ); + + // Pop a message box and refuse to close + VGUIMessageBox( this, "Error", "Game name %s already exists! Please enter a unique name.", textBuffer ); + + BaseClass::OnCommand( command ); + return; + } + + KeyValues *actionSignal = new KeyValues("ManageSelect"); + + if ( actionSignal == NULL ) + { + Assert( 0 ); + return; + } + + // See if we need to add a new config + if ( m_nConfigID == NEW_CONFIG_ID ) + { + // Create a new data container and point to it + m_nConfigID = g_Configs.AddToTail( new CGameConfig() ); + + // Send an overidden action signal to notify that we've added, not edited a field + actionSignal->SetName("AddSelect"); + } + + // Otherwise take the name + UtlStrcpy( g_Configs[m_nConfigID]->m_Name, textBuffer ); + + // Take the game directory + m_pGameDirEntry->GetText( textBuffer, sizeof( textBuffer ) ); + + // Strip off the trailing slash always + Q_StripTrailingSlash( textBuffer ); + + UtlStrcpy( g_Configs[m_nConfigID]->m_ModDir, textBuffer ); + + // Tell the parent we altered its data so it can refresh + PostActionSignal( actionSignal ); + + Close(); + } + // Modified to allow more than one browse button + else if ( Q_stricmp( command, "BrowseDir" ) == 0 ) + { + // Create a new dialog + CModalDirectorySelectDialog *pDlg = vgui::SETUP_PANEL( new CModalDirectorySelectDialog( this, "Select Game Directory" ) ); + + char textBuffer[1024]; + m_pGameDirEntry->GetText( textBuffer, sizeof( textBuffer ) ); + + // Get the currently set dir and use that as the start + pDlg->ExpandTreeToPath( textBuffer ); + pDlg->MoveToCenterOfScreen(); + pDlg->AddActionSignalTarget( this ); + pDlg->SetDeleteSelfOnClose( true ); + pDlg->DoModal(); + } + + BaseClass::OnCommand( command ); +} + +//----------------------------------------------------------------------------- +// Purpose: Notify us that the directory dialog has returned a new entry +//----------------------------------------------------------------------------- +void CManageGamesDialog::OnChooseDirectory( const char *dir ) +{ + SetGameDir( dir ); +} diff --git a/utils/vconfig/ManageGamesDialog.h b/utils/vconfig/ManageGamesDialog.h new file mode 100644 index 0000000..d73121e --- /dev/null +++ b/utils/vconfig/ManageGamesDialog.h @@ -0,0 +1,54 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef MANAGEGAMESDIALOG_H +#define MANAGEGAMESDIALOG_H +#ifdef _WIN32 +#pragma once +#endif + +#include <vgui_controls/Frame.h> +#include <vgui_controls/TextEntry.h> +#include <vgui_controls/PHandle.h> + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Purpose: Main dialog for media browser +//----------------------------------------------------------------------------- +class CManageGamesDialog : public Frame +{ + DECLARE_CLASS_SIMPLE( CManageGamesDialog, Frame ); + +public: + + CManageGamesDialog( Panel *parent, const char *name, int configID ); + virtual ~CManageGamesDialog(); + + void SetGameDir( const char *szDir ); + void SetGameName( const char *szDir ); + +protected: + + virtual void OnCommand( const char *command ); + + bool IsGameNameUnique( const char *name ); + +private: + + int m_nConfigID; + + vgui::TextEntry *m_pGameNameEntry; + vgui::TextEntry *m_pGameDirEntry; + + MESSAGE_FUNC_CHARPTR( OnChooseDirectory, "DirectorySelected", dir ); +}; + + +extern CManageGamesDialog *g_pManageGamesDialog; + + +#endif // MANAGEGAMESDIALOG_H diff --git a/utils/vconfig/VConfig.rc b/utils/vconfig/VConfig.rc new file mode 100644 index 0000000..0e6ea6a --- /dev/null +++ b/utils/vconfig/VConfig.rc @@ -0,0 +1,73 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "icon1.ico" +IDI_ICON2 ICON "icon2.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/utils/vconfig/VConfigDialog.cpp b/utils/vconfig/VConfigDialog.cpp new file mode 100644 index 0000000..e3b7a08 --- /dev/null +++ b/utils/vconfig/VConfigDialog.cpp @@ -0,0 +1,310 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Dialog for selecting game configurations +// +//=====================================================================================// + +#include <windows.h> + +#include <vgui/IVGui.h> +#include <vgui/IInput.h> +#include <vgui/ISystem.h> +#include <vgui_controls/ComboBox.h> +#include <vgui_controls/MessageBox.h> +#include <KeyValues.h> + +#include "vconfig_main.h" +#include "VConfigDialog.h" +#include "ManageGamesDialog.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +using namespace vgui; + +CVConfigDialog *g_pVConfigDialog = NULL; + +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 ) + { + system()->ShellExecute( "open", "http://www.valve-erc.com/srcsdk/faq.html#convertINI" ); + } + } +}; + +class CModalPreserveMessageBox : public vgui::MessageBox +{ +public: + CModalPreserveMessageBox(const char *title, const char *text, vgui::Panel *parent) + : vgui::MessageBox( title, text, parent ) + { + m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface(); + } + + ~CModalPreserveMessageBox() + { + vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel ); + } + + +public: + vgui::VPANEL m_PrevAppFocusPanel; +}; + +//----------------------------------------------------------------------------- +// Purpose: Utility function to pop up a VGUI message box +//----------------------------------------------------------------------------- +void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, const char *pMsg, ... ) +{ + char msg[4096]; + va_list marker; + va_start( marker, pMsg ); + Q_vsnprintf( msg, sizeof( msg ), pMsg, marker ); + va_end( marker ); + + vgui::MessageBox *dlg = new CModalPreserveMessageBox( pTitle, msg, pParent ); + dlg->DoModal(); + dlg->Activate(); + dlg->RequestFocus(); +} + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CVConfigDialog::CVConfigDialog( Panel *parent, const char *name ) : BaseClass( parent, name ), m_bChanged( false ) +{ + Assert( !g_pVConfigDialog ); + g_pVConfigDialog = this; + + SetSize(384, 420); + SetMinimumSize(200, 100); + + SetMinimizeButtonVisible( true ); + + m_pConfigCombo = new ComboBox( this, "ConfigCombo", 8, false ); + + PopulateConfigList(); + + LoadControlSettings( "VConfigDialog.res" ); + + // See if we converted on load and notify + if ( g_ConfigManager.WasConvertedOnLoad() ) + { + //VGUIMessageBox( this, "Update Occured", "Your game configurations have been updated.\n\nA backup file GameCfg.INI.OLD has been created.\n\nPlease visit http://www.valve-erc.com/srcsdk/faq.html#GameConfigUpdate for more information." ); + CConversionInfoMessageBox *pDlg = new CConversionInfoMessageBox( this, "ConversionInfo" ); + + pDlg->RequestFocus(); + pDlg->SetVisible( true ); + pDlg->MoveToCenterOfScreen(); + input()->SetAppModalSurface( pDlg->GetVPanel() ); + } +} + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- +CVConfigDialog::~CVConfigDialog() +{ + delete m_pConfigCombo; + g_pVConfigDialog = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Populate the configuration list for selection +//----------------------------------------------------------------------------- +void CVConfigDialog::PopulateConfigList( bool bSelectActiveConfig /*=true*/ ) +{ + int activeItem = -1; + + char szKeyValue[1024] = "\0"; + + if ( bSelectActiveConfig ) + { + // Get the currently set game configuration + if ( GetVConfigRegistrySetting( GAMEDIR_TOKEN, szKeyValue, sizeof( szKeyValue ) ) == false ) + { + //NOTE: We may want to pop an info dialog here if there was no initial VPROJECT setting + activeItem = 0; + } + } + else + { + activeItem = m_pConfigCombo->GetActiveItem(); + } + + // Purge all our items + m_pConfigCombo->DeleteAllItems(); + + KeyValues *kv = new KeyValues( "Items" ); + + // Add all configurations + for ( int i = 0; i < g_Configs.Count(); i++ ) + { + // Set the text + kv->SetString( "ModDir", g_Configs[i]->m_ModDir.Base() ); + + // Add the item into the list + int index = m_pConfigCombo->AddItem( g_Configs[i]->m_Name.Base(), kv ); + + if ( bSelectActiveConfig ) + { + if ( !Q_stricmp( g_Configs[i]->m_ModDir.Base(), szKeyValue ) ) + { + activeItem = index; + } + } + } + + // Make sure we have an active item + if ( activeItem < 0 ) + { + // Give a warning if they have a mismatched directory! + VGUIMessageBox( this, "Invalid Game Directory", "The currently selected game directory: %s is invalid.\nChoose a new directory, or select 'Cancel' to exit.\n", szKeyValue ); + + // Default to the first config in the list + activeItem = 0; + } + + // Set us to the active config + m_pConfigCombo->ActivateItem( activeItem ); + + kv->deleteThis(); +} + +//----------------------------------------------------------------------------- +// Purpose: Kills the whole app on close +//----------------------------------------------------------------------------- +void CVConfigDialog::OnClose( void ) +{ + BaseClass::OnClose(); + ivgui()->Stop(); +} + +//----------------------------------------------------------------------------- +// Purpose: Select the item from the list (updating the environment variable as well) +// Input : index - item to select +//----------------------------------------------------------------------------- +void CVConfigDialog::SetGlobalConfig( const char *modDir ) +{ + // Set our environment variable + SetMayaScriptSettings( ); + SetXSIScriptSettings( ); + SetPathSettings( ); + SetVConfigRegistrySetting( GAMEDIR_TOKEN, modDir ); +} + +//----------------------------------------------------------------------------- +// Purpose: Parse commands coming in from the VGUI dialog +//----------------------------------------------------------------------------- +void CVConfigDialog::OnCommand( const char *command ) +{ + if ( Q_stricmp( command, "Select" ) == 0 ) + { + int activeID = m_pConfigCombo->GetActiveItem(); + + SetGlobalConfig( g_Configs[activeID]->m_ModDir.Base() ); + + // Save off our data + if ( m_bChanged ) + { + SaveConfigs(); + } + + Close(); + } + else if ( Q_stricmp( command, "Manage" ) == 0 ) + { + int activeID = m_pConfigCombo->GetActiveItem(); + + // Launch the edit window + CManageGamesDialog *pDialog = new CManageGamesDialog( this, "ManageGamesDialog", activeID ); + + pDialog->AddActionSignalTarget( this ); + pDialog->SetGameDir( g_Configs[activeID]->m_ModDir.Base() ); + pDialog->SetGameName( g_Configs[activeID]->m_Name.Base() ); + pDialog->DoModal(); + } + else if ( Q_stricmp( command, "AddConfig" ) == 0 ) + { + // Launch the edit window, specifying that we're adding a config + CManageGamesDialog *pDialog = new CManageGamesDialog( this, "ManageGamesDialog", NEW_CONFIG_ID ); + + pDialog->AddActionSignalTarget( this ); + pDialog->DoModal(); + } + else if ( Q_stricmp( command, "RemoveConfig" ) == 0 ) + { + // Don't allow the list to completely vanish + // NOTE: We should display the list as being empty, i.e. "<EMPTY>" + if ( g_Configs.Count() <= 1 ) + { + VGUIMessageBox( this, "Error", "Cannot remove last configuration from list!" ); + return; + } + + // Remove this config from our list + int activeID = m_pConfigCombo->GetActiveItem(); + + RemoveConfig( activeID ); + + ReloadConfigs( true ); + + // Select the next entry + m_pConfigCombo->ActivateItem( g_Configs.Count()-1 ); + + // Mark that we changed our configs + m_bChanged = true; + } + + BaseClass::OnCommand( command ); +} + +//----------------------------------------------------------------------------- +// Purpose: Manage dialog has reported a need to update +//----------------------------------------------------------------------------- +void CVConfigDialog::OnManageSelect( void ) +{ + // Publish the config changes to the internal data in the configuration manager + UpdateConfigs(); + + // Update the configuration list + PopulateConfigList( false ); + + m_bChanged = true; +} + +//----------------------------------------------------------------------------- +// Purpose: Manage dialog has reported that it has added a configuration +//----------------------------------------------------------------------------- +void CVConfigDialog::OnAddSelect( void ) +{ + // Add the last config we entered + AddConfig( g_Configs.Count()-1 ); + + // Re-populate the configuration list + ReloadConfigs(); + + // Select the last entry (which will be the new one) + m_pConfigCombo->ActivateItem( g_Configs.Count()-1 ); + + // Mark us as changed + m_bChanged = true; +} diff --git a/utils/vconfig/VConfigDialog.h b/utils/vconfig/VConfigDialog.h new file mode 100644 index 0000000..c86b702 --- /dev/null +++ b/utils/vconfig/VConfigDialog.h @@ -0,0 +1,59 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef VCONFIGDIALOG_H +#define VCONFIGDIALOG_H +#ifdef _WIN32 +#pragma once +#endif + +#include <vgui_controls/Frame.h> +#include <vgui_controls/ImageList.h> +#include <vgui_controls/SectionedListPanel.h> +#include <vgui_controls/PHandle.h> +#include <FileSystem.h> +#include "vgui/mousecode.h" +#include "vgui/IScheme.h" + +#include "ConfigManager.h" + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Purpose: Main dialog for media browser +//----------------------------------------------------------------------------- +class CVConfigDialog : public Frame +{ + DECLARE_CLASS_SIMPLE( CVConfigDialog, Frame ); + +public: + + CVConfigDialog(Panel *parent, const char *name); + virtual ~CVConfigDialog(); + + void PopulateConfigList( bool bSelectActiveConfig = true ); + +protected: + + virtual void OnClose(); + virtual void OnCommand( const char *command ); + +private: + + void SetGlobalConfig( const char *modDir ); + + vgui::ComboBox *m_pConfigCombo; + bool m_bChanged; + + MESSAGE_FUNC( OnManageSelect, "ManageSelect" ); + MESSAGE_FUNC( OnAddSelect, "AddSelect" ); +}; + + +extern CVConfigDialog *g_pVConfigDialog; + + +#endif // VCONFIGDIALOG_H diff --git a/utils/vconfig/icon1.ico b/utils/vconfig/icon1.ico Binary files differnew file mode 100644 index 0000000..1cf30a0 --- /dev/null +++ b/utils/vconfig/icon1.ico diff --git a/utils/vconfig/icon2.ico b/utils/vconfig/icon2.ico Binary files differnew file mode 100644 index 0000000..1cf30a0 --- /dev/null +++ b/utils/vconfig/icon2.ico diff --git a/utils/vconfig/main.cpp b/utils/vconfig/main.cpp new file mode 100644 index 0000000..175c2eb --- /dev/null +++ b/utils/vconfig/main.cpp @@ -0,0 +1,646 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Configuration utility +// +//===========================================================================// + +#include <windows.h> +#include <io.h> +#include <stdio.h> + +#include <vgui/ILocalize.h> +#include <vgui/ISurface.h> +#include <vgui/IVGui.h> +#include <vgui_controls/Panel.h> + +#include "tier0/icommandline.h" +#include "inputsystem/iinputsystem.h" +#include "appframework/tier3app.h" +#include "vconfig_main.h" +#include "VConfigDialog.h" +#include "ConfigManager.h" +#include "steam/steam_api.h" +#include <iregistry.h> + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +#define VCONFIG_MAIN_PATH_ID "MAIN" + +CVConfigDialog *g_pMainFrame = 0; +char g_engineDir[50]; + + +// Dummy window +static WNDCLASS staticWndclass = { NULL }; +static ATOM staticWndclassAtom = 0; +static HWND staticHwnd = 0; + +// List of our game configs, as read from the gameconfig.txt file +CGameConfigManager g_ConfigManager; +CUtlVector<CGameConfig *> g_Configs; +HANDLE g_dwChangeHandle = NULL; +CSteamAPIContext g_SteamAPIContext; +CSteamAPIContext *steamapicontext = &g_SteamAPIContext; + +//----------------------------------------------------------------------------- +// Purpose: Copy a string into a CUtlVector of characters +//----------------------------------------------------------------------------- +void UtlStrcpy( CUtlVector<char> &dest, const char *pSrc ) +{ + dest.EnsureCount( (int) (strlen( pSrc ) + 1) ); + Q_strncpy( dest.Base(), pSrc, dest.Count() ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *GetBaseDirectory( void ) +{ + static char path[MAX_PATH] = {0}; + if ( path[0] == 0 ) + { + GetModuleFileName( (HMODULE)GetAppInstance(), path, sizeof( path ) ); + Q_StripLastDir( path, sizeof( path ) ); // Get rid of the filename. + Q_StripTrailingSlash( path ); + } + return path; +} + +// Fetch the engine version for when running in steam. +void GetEngineVersion(char* pcEngineVer, int nSize) +{ + IRegistry *reg = InstanceRegistry( "Source SDK" ); + Assert( reg ); + V_strncpy( pcEngineVer, reg->ReadString( "EngineVer", "orangebox" ), nSize ); + ReleaseInstancedRegistry( reg ); +} +//----------------------------------------------------------------------------- +// Purpose: Add a new configuration with proper defaults to a keyvalue block +//----------------------------------------------------------------------------- +bool AddConfig( int configID ) +{ + // Find the games block of the keyvalues + KeyValues *gameBlock = g_ConfigManager.GetGameBlock(); + + if ( gameBlock == NULL ) + { + Assert( 0 ); + return false; + } + + // Set to defaults + defaultConfigInfo_t newInfo; + memset( &newInfo, 0, sizeof( newInfo ) ); + + // Data for building the new configuration + const char *pModName = g_Configs[configID]->m_Name.Base(); + const char *pModDirectory = g_Configs[configID]->m_ModDir.Base(); + + // Mod name + Q_strncpy( newInfo.gameName, pModName, sizeof( newInfo.gameName ) ); + + // FGD + Q_strncpy( newInfo.FGD, "base.fgd", sizeof( newInfo.FGD ) ); + + // Get the base directory + Q_FileBase( pModDirectory, newInfo.gameDir, sizeof( newInfo.gameDir ) ); + + // Default executable + Q_strncpy( newInfo.exeName, "hl2.exe", sizeof( newInfo.exeName ) ); + + char szPath[MAX_PATH]; + Q_strncpy( szPath, pModDirectory, sizeof( szPath ) ); + Q_StripLastDir( szPath, sizeof( szPath ) ); + Q_StripTrailingSlash( szPath ); + + char fullDir[MAX_PATH]; + g_ConfigManager.GetRootGameDirectory( fullDir, sizeof( fullDir ), g_ConfigManager.GetRootDirectory() ); + + return g_ConfigManager.AddDefaultConfig( newInfo, gameBlock, szPath, fullDir ); +} + +//----------------------------------------------------------------------------- +// Purpose: Remove a configuration from the data block +//----------------------------------------------------------------------------- +bool RemoveConfig( int configID ) +{ + if ( !g_ConfigManager.IsLoaded() ) + return false; + + // Find the games block of the keyvalues + KeyValues *gameBlock = g_ConfigManager.GetGameBlock(); + + if ( gameBlock == NULL ) + { + Assert( 0 ); + return false; + } + + int i = 0; + + // Iterate through all subkeys + for ( KeyValues *pGame=gameBlock->GetFirstTrueSubKey(); pGame; pGame=pGame->GetNextTrueSubKey(), i++ ) + { + if ( i == configID ) + { + KeyValues *pOldGame = pGame; + pGame = pGame->GetNextTrueSubKey(); + + gameBlock->RemoveSubKey( pOldGame ); + pOldGame->deleteThis(); + + if ( pGame == NULL ) + return true; + } + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Updates the internal data of the keyvalue buffer with the edited info +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool UpdateConfigs( void ) +{ + if ( !g_ConfigManager.IsLoaded() ) + return false; + + // Find the games block of the keyvalues + KeyValues *gameBlock = g_ConfigManager.GetGameBlock(); + + if ( gameBlock == NULL ) + { + Assert( 0 ); + return false; + } + + int i = 0; + + // Stomp parsed data onto the contained keyvalues + for ( KeyValues *pGame=gameBlock->GetFirstTrueSubKey(); pGame != NULL; pGame=pGame->GetNextTrueSubKey(), i++ ) + { + pGame->SetName( g_Configs[i]->m_Name.Base() ); + pGame->SetString( TOKEN_GAME_DIRECTORY, g_Configs[i]->m_ModDir.Base() ); + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Saves out changes to the config file +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool SaveConfigs( void ) +{ + // Move the internal changes up to the base data stored in the config manager + if ( UpdateConfigs() == false ) + return false; + + // Save out the data + if ( g_ConfigManager.SaveConfigs() == false ) + return false; + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Read the information we use out of the configs +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool ParseConfigs( void ) +{ + if ( !g_ConfigManager.IsLoaded() ) + return false; + + // Find the games block of the keyvalues + KeyValues *gameBlock = g_ConfigManager.GetGameBlock(); + + if ( gameBlock == NULL ) + { + Assert( 0 ); + 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( pName, pDir ); + g_Configs.AddToTail( newConfig ); + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Startup our file watch +//----------------------------------------------------------------------------- +void UpdateConfigsStatus_Init( void ) +{ + // Watch our config file for changes + if ( g_dwChangeHandle == NULL) + { + char szConfigDir[MAX_PATH]; + Q_strncpy( szConfigDir, GetBaseDirectory(), sizeof( szConfigDir ) ); + + g_dwChangeHandle = FindFirstChangeNotification( + szConfigDir, // directory to watch + false, // watch the subtree + FILE_NOTIFY_CHANGE_LAST_WRITE ); // watch file and dir name changes + + if ( g_dwChangeHandle == INVALID_HANDLE_VALUE ) + { + // FIXME: Unable to watch the file + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Reload and re-parse our configuration data +//----------------------------------------------------------------------------- +void ReloadConfigs( bool bNoWarning /*= false*/ ) +{ + g_Configs.PurgeAndDeleteElements(); + ParseConfigs(); + g_pMainFrame->PopulateConfigList( bNoWarning ); +} + +//----------------------------------------------------------------------------- +// Purpose: Update our status +//----------------------------------------------------------------------------- +void UpdateConfigsStatus( void ) +{ + // Wait for notification. + DWORD dwWaitStatus = WaitForSingleObject( g_dwChangeHandle, 0 ); + + if ( dwWaitStatus == WAIT_OBJECT_0 ) + { + // Something in the watched folder changed! + if ( g_pMainFrame != NULL ) + { + // Reload the configs + g_ConfigManager.LoadConfigs(); + + // Reparse the configurations + ReloadConfigs(); + } + + // Start the next update + if ( FindNextChangeNotification( g_dwChangeHandle ) == FALSE ) + { + // This means that something unknown happened to our search handle! + Assert( 0 ); + return; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Stop watching the file +//----------------------------------------------------------------------------- +void UpdateConfigsStatus_Shutdown( void ) +{ + FindCloseChangeNotification( g_dwChangeHandle ); +} + +//----------------------------------------------------------------------------- +// Purpose: Message handler for dummy app +//----------------------------------------------------------------------------- +static LRESULT CALLBACK messageProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + // See if we've gotten a VPROJECT change + if ( msg == WM_SETTINGCHANGE ) + { + if ( g_pMainFrame != NULL ) + { + // Reset the list and pop an error if they've chosen something we don't understand + g_pMainFrame->PopulateConfigList(); + } + } + + return ::DefWindowProc(hwnd,msg,wparam,lparam); +} + +//----------------------------------------------------------------------------- +// Purpose: Creates a dummy window that handles windows messages +//----------------------------------------------------------------------------- +void CreateMessageWindow( void ) +{ + // Make and register a very simple window class + memset(&staticWndclass, 0, sizeof(staticWndclass)); + staticWndclass.style = 0; + staticWndclass.lpfnWndProc = messageProc; + staticWndclass.hInstance = GetModuleHandle(NULL); + staticWndclass.lpszClassName = "VConfig_Window"; + staticWndclassAtom = ::RegisterClass( &staticWndclass ); + + // Create an empty window just for message handling + staticHwnd = CreateWindowEx(0, "VConfig_Window", "Hidden Window", 0, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ShutdownMessageWindow( void ) +{ + // Kill our windows instance + ::DestroyWindow( staticHwnd ); + ::UnregisterClass("VConfig_Window", ::GetModuleHandle(NULL)); +} + + +//----------------------------------------------------------------------------- +// Sets up, shuts down vgui +//----------------------------------------------------------------------------- +bool InitializeVGUI( void ) +{ + vgui::ivgui()->SetSleep(false); + + // Init the surface + vgui::Panel *pPanel = new vgui::Panel( NULL, "TopPanel" ); + pPanel->SetVisible(true); + + vgui::surface()->SetEmbeddedPanel(pPanel->GetVPanel()); + + // load the scheme + vgui::scheme()->LoadSchemeFromFile( "vconfig_scheme.res", NULL ); + + // localization + g_pVGuiLocalize->AddFile( "resource/platform_%language%.txt"); + g_pVGuiLocalize->AddFile( "vgui/resource/vgui_%language%.txt" ); + g_pVGuiLocalize->AddFile( "vconfig_english.txt"); + + // Start vgui + vgui::ivgui()->Start(); + + // add our main window + g_pMainFrame = new CVConfigDialog( pPanel, "VConfigDialog" ); + + // show main window + g_pMainFrame->MoveToCenterOfScreen(); + g_pMainFrame->Activate(); + g_pMainFrame->SetSizeable( false ); + g_pMainFrame->SetMenuButtonVisible( true ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Stop VGUI +//----------------------------------------------------------------------------- +void ShutdownVGUI( void ) +{ + delete g_pMainFrame; +} + + +//----------------------------------------------------------------------------- +// Points the maya script to the appropriate place +//----------------------------------------------------------------------------- +void SetMayaScriptSettings( ) +{ + char pMayaScriptPath[ MAX_PATH ]; + Q_snprintf( pMayaScriptPath, sizeof(pMayaScriptPath), "%%VPROJECT%%\\..\\sdktools\\maya\\scripts" ); + SetVConfigRegistrySetting( "MAYA_SCRIPT_PATH", pMayaScriptPath, false ); +} + + +//----------------------------------------------------------------------------- +// Points the XSI script to the appropriate place +//----------------------------------------------------------------------------- +void SetXSIScriptSettings( ) +{ + // Determine the currently installed version of XSI + char *pXSIVersion = "5.1"; + + // FIXME: We need a way of knowing the current version of XSI being used + // so we can set up the appropriate search paths. There's no easy way of doing this currently + // so I'm defining my own environment variable + char pXSIVersionBuf[ MAX_PATH ]; + if ( GetVConfigRegistrySetting( "XSI_VERSION", pXSIVersionBuf, sizeof(pXSIVersionBuf) ) ) + { + pXSIVersion = pXSIVersionBuf; + } + + char pXSIPluginPath[ MAX_PATH ]; + Q_snprintf( pXSIPluginPath, sizeof(pXSIPluginPath), "%%VPROJECT%%\\..\\sdktools\\xsi\\%s\\valvesource", pXSIVersion ); + SetVConfigRegistrySetting( "XSI_PLUGINS", pXSIPluginPath, false ); + SetVConfigRegistrySetting( "XSI_VERSION", pXSIVersion, false ); +} + + +//----------------------------------------------------------------------------- +// Points the XSI script to the appropriate place +//----------------------------------------------------------------------------- +#define VPROJECT_BIN_PATH "%vproject%\\..\\bin" + +void SetPathSettings( ) +{ + char pPathBuf[ MAX_PATH*32 ]; + if ( GetVConfigRegistrySetting( "PATH", pPathBuf, sizeof(pPathBuf) ) ) + { + Q_FixSlashes( pPathBuf ); + const char *pPath = pPathBuf; + const char *pFound = Q_stristr( pPath, VPROJECT_BIN_PATH ); + int nLen = Q_strlen( VPROJECT_BIN_PATH ); + while ( pFound ) + { + if ( pFound[nLen] == '\\' ) + { + ++nLen; + } + if ( !pFound[nLen] || pFound[nLen] == ';' ) + return; + + pPath += nLen; + pFound = Q_stristr( pPath, VPROJECT_BIN_PATH ); + } + + Q_strncat( pPathBuf, ";%VPROJECT%\\..\\bin", sizeof(pPathBuf) ); + } + else + { + Q_strncpy( pPathBuf, "%VPROJECT%\\..\\bin", sizeof(pPathBuf) ); + } + + SetVConfigRegistrySetting( "PATH", pPathBuf, false ); +} + + +//----------------------------------------------------------------------------- +// Spew func +//----------------------------------------------------------------------------- +SpewRetval_t VConfig_SpewOutputFunc( SpewType_t type, char const *pMsg ) +{ +#ifdef _DEBUG + OutputDebugString( pMsg ); +#endif + + switch( type ) + { + case SPEW_ERROR: + ::MessageBox( NULL, pMsg, "VConfig Error", MB_OK ); + return SPEW_ABORT; + + case SPEW_ASSERT: + return SPEW_DEBUGGER; + } + + return SPEW_CONTINUE; +} + + +//----------------------------------------------------------------------------- +// The application object +//----------------------------------------------------------------------------- +class CVConfigApp : public CVguiSteamApp +{ + typedef CVguiSteamApp BaseClass; + +public: + // Methods of IApplication + virtual bool Create(); + virtual bool PreInit(); + virtual int Main(); + virtual void PostShutdown(); + virtual void Destroy() {} +}; + +DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT( CVConfigApp ); + + +//----------------------------------------------------------------------------- +// The application object +//----------------------------------------------------------------------------- +bool CVConfigApp::Create() +{ + SpewOutputFunc( VConfig_SpewOutputFunc ); + + // If they pass in -game, just set the registry key to the value they asked for. + const char *pSetGame = CommandLine()->ParmValue( "-game" ); + if ( pSetGame ) + { + SetMayaScriptSettings( ); + SetXSIScriptSettings( ); + SetPathSettings( ); + SetVConfigRegistrySetting( GAMEDIR_TOKEN, pSetGame ); + return false; + } + + AppSystemInfo_t appSystems[] = + { + { "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION }, + { "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION }, + { "", "" } // Required to terminate the list + }; + + return AddSystems( appSystems ); +} + + +//----------------------------------------------------------------------------- +// Pre-init +//----------------------------------------------------------------------------- +bool CVConfigApp::PreInit() +{ + if ( !BaseClass::PreInit() ) + return false; + + // Create a window to capture messages + CreateMessageWindow(); + + // Make sure we're using the proper environment variable + ConvertObsoleteVConfigRegistrySetting( GAMEDIR_TOKEN ); + + FileSystem_SetErrorMode( FS_ERRORMODE_AUTO ); + + // We only want to use the gameinfo.txt that is in the bin\vconfig directory. + char dirName[MAX_PATH]; + Q_strncpy( dirName, GetBaseDirectory(), sizeof( dirName ) ); + Q_AppendSlash( dirName, sizeof( dirName ) ); + Q_strncat( dirName, "vconfig", sizeof( dirName ), COPY_ALL_CHARACTERS ); + + if ( !SetupSearchPaths( dirName, true, true ) ) + { + ::MessageBox( NULL, "Error", "Unable to initialize file system\n", MB_OK ); + return false; + } + + // Load our configs + if ( g_ConfigManager.LoadConfigs() == false ) + { + ::MessageBox( NULL, "Error", "Unable to load configuration file\n", MB_OK ); + return false; + } + + // Parse them for internal use + if ( ParseConfigs() == false ) + { + ::MessageBox( NULL, "Error", "Unable to parse configuration file\n", MB_OK ); + return false; + } + + // Start looking for file updates + UpdateConfigsStatus_Init(); + + // the "base dir" so we can scan mod name + g_pFullFileSystem->AddSearchPath( GetBaseDirectory(), VCONFIG_MAIN_PATH_ID ); + + // the main platform dir + g_pFullFileSystem->AddSearchPath( "platform","PLATFORM", PATH_ADD_TO_HEAD ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Pre-init +//----------------------------------------------------------------------------- +void CVConfigApp::PostShutdown() +{ + // Stop our message window + ShutdownMessageWindow(); + + // Clear our configs + g_Configs.PurgeAndDeleteElements(); + + // Stop file notifications + UpdateConfigsStatus_Shutdown(); + + BaseClass::PostShutdown(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Main function +//----------------------------------------------------------------------------- +int CVConfigApp::Main() +{ + if ( !InitializeVGUI() ) + return 0; + + SteamAPI_InitSafe(); + SteamAPI_SetTryCatchCallbacks( false ); // We don't use exceptions, so tell steam not to use try/catch in callback handlers + g_SteamAPIContext.Init(); + + GetEngineVersion( g_engineDir, sizeof( g_engineDir ) ); + + // Run the app + while ( vgui::ivgui()->IsRunning() ) + { + Sleep( 10 ); + UpdateConfigsStatus(); + vgui::ivgui()->RunFrame(); + } + + ShutdownVGUI(); + + return 1; +} + diff --git a/utils/vconfig/resource.h b/utils/vconfig/resource.h new file mode 100644 index 0000000..226ddd5 --- /dev/null +++ b/utils/vconfig/resource.h @@ -0,0 +1,18 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by VConfig.rc +// +#define IDI_ICON1 101 +#define IDI_ICON2 102 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 104 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/utils/vconfig/vconfig.vpc b/utils/vconfig/vconfig.vpc new file mode 100644 index 0000000..bbd1c28 --- /dev/null +++ b/utils/vconfig/vconfig.vpc @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// VCONFIG.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin" + +$Include "$SRCDIR\vpc_scripts\source_exe_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,..\common" + $PreprocessorDefinitions "$BASE;VERSION_SAFE_STEAM_API_INTERFACES" + } +} + +$Project "VConfig" +{ + $Folder "Source Files" + { + $File "$SRCDIR\common\ConfigManager.cpp" + $File "$SRCDIR\common\SourceAppInfo.cpp" + $File "$SRCDIR\public\filesystem_init.cpp" + $File "$SRCDIR\public\registry.cpp" + $File "main.cpp" + $File "ManageGamesDialog.cpp" + $File "VConfigDialog.cpp" + $File "$SRCDIR\public\vgui_controls\vgui_controls.cpp" + } + + $Folder "Header Files" + { + $File "$SRCDIR\common\ConfigManager.h" + $File "..\common\filesystem_tools.h" + $File "$SRCDIR\public\tier1\KeyValues.h" + $File "ManageGamesDialog.h" + $File "resource.h" + $File "$SRCDIR\public\tier1\utlbuffer.h" + $File "vconfig_main.h" + $File "VConfigDialog.h" + } + + $Folder "Resources" + { + $File "icon1.ico" + $File "icon2.ico" + $File "VConfig.rc" + } + + $Folder "Link Libraries" + { + $Lib appframework + $ImpLib steam_api + $Lib tier2 + $Lib tier3 + $Lib vgui_controls + $Lib mathlib + } +} diff --git a/utils/vconfig/vconfig_main.h b/utils/vconfig/vconfig_main.h new file mode 100644 index 0000000..6ede1f8 --- /dev/null +++ b/utils/vconfig/vconfig_main.h @@ -0,0 +1,57 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#ifndef VPICKER_MAIN_H +#define VPICKER_MAIN_H +#ifdef _WIN32 +#pragma once +#endif + +#include <vgui_controls/Frame.h> +#include <KeyValues.h> + +#include "tier2/vconfig.h" +#include "ConfigManager.h" + +#define INVALID_CONFIG_ID -1 +#define NEW_CONFIG_ID -2 + +void UtlStrcpy( CUtlVector<char> &dest, const char *pSrc ); + +// ============================================== +// Container class for config information +// ============================================== +class CGameConfig +{ +public: + CGameConfig( void ) {} + CGameConfig( const char *name, const char *dir ) + { + UtlStrcpy( m_Name, name ); + UtlStrcpy( m_ModDir, dir ); + } + + CUtlVector<char> m_Name; + CUtlVector<char> m_ModDir; +}; + +extern CGameConfigManager g_ConfigManager; +extern CUtlVector<CGameConfig *> g_Configs; + +bool UpdateConfigs( void ); +void ReloadConfigs( bool bNoWarning = false ); +bool RemoveConfig( int configID ); +bool AddConfig( int configID ); +bool SaveConfigs( void ); +void SetMayaScriptSettings( ); +void SetXSIScriptSettings( ); +void SetPathSettings( ); + +const char *GetBaseDirectory( void ); +void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, PRINTF_FORMAT_STRING const char *pMsg, ... ); + + +#endif // VPICKER_MAIN_H |