summaryrefslogtreecommitdiff
path: root/vstdlib/cvar.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vstdlib/cvar.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'vstdlib/cvar.cpp')
-rw-r--r--vstdlib/cvar.cpp899
1 files changed, 899 insertions, 0 deletions
diff --git a/vstdlib/cvar.cpp b/vstdlib/cvar.cpp
new file mode 100644
index 0000000..72aca7b
--- /dev/null
+++ b/vstdlib/cvar.cpp
@@ -0,0 +1,899 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#include "vstdlib/cvar.h"
+#include <ctype.h>
+#include "tier0/icommandline.h"
+#include "tier1/utlrbtree.h"
+#include "tier1/strtools.h"
+#include "tier1/KeyValues.h"
+#include "tier1/convar.h"
+#include "tier0/vprof.h"
+#include "tier1/tier1.h"
+#include "tier1/utlbuffer.h"
+
+#ifdef _X360
+#include "xbox/xbox_console.h"
+#endif
+
+#ifdef POSIX
+#include <wctype.h>
+#include <wchar.h>
+#endif
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+//-----------------------------------------------------------------------------
+// Default implementation of CvarQuery
+//-----------------------------------------------------------------------------
+class CDefaultCvarQuery : public CBaseAppSystem< ICvarQuery >
+{
+public:
+ virtual void *QueryInterface( const char *pInterfaceName )
+ {
+ if ( !Q_stricmp( pInterfaceName, CVAR_QUERY_INTERFACE_VERSION ) )
+ return (ICvarQuery*)this;
+ return NULL;
+
+ }
+
+ virtual bool AreConVarsLinkable( const ConVar *child, const ConVar *parent )
+ {
+ return true;
+ }
+};
+
+static CDefaultCvarQuery s_DefaultCvarQuery;
+static ICvarQuery *s_pCVarQuery = NULL;
+
+
+//-----------------------------------------------------------------------------
+// Default implementation
+//-----------------------------------------------------------------------------
+class CCvar : public ICvar
+{
+public:
+ CCvar();
+
+ // Methods of IAppSystem
+ virtual bool Connect( CreateInterfaceFn factory );
+ virtual void Disconnect();
+ virtual void *QueryInterface( const char *pInterfaceName );
+ virtual InitReturnVal_t Init();
+ virtual void Shutdown();
+
+ // Inherited from ICVar
+ virtual CVarDLLIdentifier_t AllocateDLLIdentifier();
+ virtual void RegisterConCommand( ConCommandBase *pCommandBase );
+ virtual void UnregisterConCommand( ConCommandBase *pCommandBase );
+ virtual void UnregisterConCommands( CVarDLLIdentifier_t id );
+ virtual const char* GetCommandLineValue( const char *pVariableName );
+ virtual ConCommandBase *FindCommandBase( const char *name );
+ virtual const ConCommandBase *FindCommandBase( const char *name ) const;
+ virtual ConVar *FindVar ( const char *var_name );
+ virtual const ConVar *FindVar ( const char *var_name ) const;
+ virtual ConCommand *FindCommand( const char *name );
+ virtual const ConCommand *FindCommand( const char *name ) const;
+ virtual ConCommandBase *GetCommands( void );
+ virtual const ConCommandBase *GetCommands( void ) const;
+ virtual void InstallGlobalChangeCallback( FnChangeCallback_t callback );
+ virtual void RemoveGlobalChangeCallback( FnChangeCallback_t callback );
+ virtual void CallGlobalChangeCallbacks( ConVar *var, const char *pOldString, float flOldValue );
+ virtual void InstallConsoleDisplayFunc( IConsoleDisplayFunc* pDisplayFunc );
+ virtual void RemoveConsoleDisplayFunc( IConsoleDisplayFunc* pDisplayFunc );
+ virtual void ConsoleColorPrintf( const Color& clr, const char *pFormat, ... ) const;
+ virtual void ConsolePrintf( const char *pFormat, ... ) const;
+ virtual void ConsoleDPrintf( const char *pFormat, ... ) const;
+ virtual void RevertFlaggedConVars( int nFlag );
+ virtual void InstallCVarQuery( ICvarQuery *pQuery );
+
+#if defined( _X360 )
+ virtual void PublishToVXConsole( );
+#endif
+
+ virtual bool IsMaterialThreadSetAllowed( ) const;
+ virtual void QueueMaterialThreadSetValue( ConVar *pConVar, const char *pValue );
+ virtual void QueueMaterialThreadSetValue( ConVar *pConVar, int nValue );
+ virtual void QueueMaterialThreadSetValue( ConVar *pConVar, float flValue );
+ virtual bool HasQueuedMaterialThreadConVarSets() const;
+ virtual int ProcessQueuedMaterialThreadConVarSets();
+private:
+ enum
+ {
+ CONSOLE_COLOR_PRINT = 0,
+ CONSOLE_PRINT,
+ CONSOLE_DPRINT,
+ };
+
+ void DisplayQueuedMessages( );
+
+ CUtlVector< FnChangeCallback_t > m_GlobalChangeCallbacks;
+ CUtlVector< IConsoleDisplayFunc* > m_DisplayFuncs;
+ int m_nNextDLLIdentifier;
+ ConCommandBase *m_pConCommandList;
+
+ // temporary console area so we can store prints before console display funs are installed
+ mutable CUtlBuffer m_TempConsoleBuffer;
+protected:
+
+ // internals for ICVarIterator
+ class CCVarIteratorInternal : public ICVarIteratorInternal
+ {
+ public:
+ CCVarIteratorInternal( CCvar *outer )
+ : m_pOuter( outer )
+ //, m_pHash( &outer->m_CommandHash ), // remember my CCvar,
+ //m_hashIter( -1, -1 ) // and invalid iterator
+ , m_pCur( NULL )
+ {}
+ virtual void SetFirst( void );
+ virtual void Next( void );
+ virtual bool IsValid( void );
+ virtual ConCommandBase *Get( void );
+ protected:
+ CCvar * const m_pOuter;
+ //CConCommandHash * const m_pHash;
+ //CConCommandHash::CCommandHashIterator_t m_hashIter;
+ ConCommandBase *m_pCur;
+ };
+
+ virtual ICVarIteratorInternal *FactoryInternalIterator( void );
+ friend class CCVarIteratorInternal;
+
+ enum ConVarSetType_t
+ {
+ CONVAR_SET_STRING = 0,
+ CONVAR_SET_INT,
+ CONVAR_SET_FLOAT,
+ };
+ struct QueuedConVarSet_t
+ {
+ ConVar *m_pConVar;
+ ConVarSetType_t m_nType;
+ int m_nInt;
+ float m_flFloat;
+ CUtlString m_String;
+ };
+ CUtlVector< QueuedConVarSet_t > m_QueuedConVarSets;
+ bool m_bMaterialSystemThreadSetAllowed;
+
+private:
+ // Standard console commands -- DO NOT PLACE ANY HIGHER THAN HERE BECAUSE THESE MUST BE THE FIRST TO DESTRUCT
+ CON_COMMAND_MEMBER_F( CCvar, "find", Find, "Find concommands with the specified string in their name/help text.", 0 )
+};
+
+void CCvar::CCVarIteratorInternal::SetFirst( void ) RESTRICT
+{
+ //m_hashIter = m_pHash->First();
+ m_pCur = m_pOuter->GetCommands();
+}
+
+void CCvar::CCVarIteratorInternal::Next( void ) RESTRICT
+{
+ //m_hashIter = m_pHash->Next( m_hashIter );
+ if ( m_pCur )
+ m_pCur = m_pCur->GetNext();
+}
+
+bool CCvar::CCVarIteratorInternal::IsValid( void ) RESTRICT
+{
+ //return m_pHash->IsValidIterator( m_hashIter );
+ return m_pCur != NULL;
+}
+
+ConCommandBase *CCvar::CCVarIteratorInternal::Get( void ) RESTRICT
+{
+ Assert( IsValid( ) );
+ //return (*m_pHash)[m_hashIter];
+ return m_pCur;
+}
+
+ICvar::ICVarIteratorInternal *CCvar::FactoryInternalIterator( void )
+{
+ return new CCVarIteratorInternal( this );
+}
+
+//-----------------------------------------------------------------------------
+// Factor for CVars
+//-----------------------------------------------------------------------------
+static CCvar s_Cvar;
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CCvar, ICvar, CVAR_INTERFACE_VERSION, s_Cvar );
+
+
+//-----------------------------------------------------------------------------
+// Returns a CVar dictionary for tool usage
+//-----------------------------------------------------------------------------
+CreateInterfaceFn VStdLib_GetICVarFactory()
+{
+ return Sys_GetFactoryThis();
+}
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+CCvar::CCvar() : m_TempConsoleBuffer( 0, 1024 )
+{
+ m_nNextDLLIdentifier = 0;
+ m_pConCommandList = NULL;
+
+ m_bMaterialSystemThreadSetAllowed = false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Methods of IAppSystem
+//-----------------------------------------------------------------------------
+bool CCvar::Connect( CreateInterfaceFn factory )
+{
+ ConnectTier1Libraries( &factory, 1 );
+
+ s_pCVarQuery = (ICvarQuery*)factory( CVAR_QUERY_INTERFACE_VERSION, NULL );
+ if ( !s_pCVarQuery )
+ {
+ s_pCVarQuery = &s_DefaultCvarQuery;
+ }
+
+ ConVar_Register();
+ return true;
+}
+
+void CCvar::Disconnect()
+{
+ ConVar_Unregister();
+ s_pCVarQuery = NULL;
+ DisconnectTier1Libraries();
+}
+
+InitReturnVal_t CCvar::Init()
+{
+ return INIT_OK;
+}
+
+void CCvar::Shutdown()
+{
+}
+
+void *CCvar::QueryInterface( const char *pInterfaceName )
+{
+ // We implement the ICvar interface
+ if ( !V_strcmp( pInterfaceName, CVAR_INTERFACE_VERSION ) )
+ return (ICvar*)this;
+
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Method allowing the engine ICvarQuery interface to take over
+//-----------------------------------------------------------------------------
+void CCvar::InstallCVarQuery( ICvarQuery *pQuery )
+{
+ Assert( s_pCVarQuery == &s_DefaultCvarQuery );
+ s_pCVarQuery = pQuery ? pQuery : &s_DefaultCvarQuery;
+}
+
+
+//-----------------------------------------------------------------------------
+// Used by DLLs to be able to unregister all their commands + convars
+//-----------------------------------------------------------------------------
+CVarDLLIdentifier_t CCvar::AllocateDLLIdentifier()
+{
+ return m_nNextDLLIdentifier++;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *variable -
+//-----------------------------------------------------------------------------
+void CCvar::RegisterConCommand( ConCommandBase *variable )
+{
+ // Already registered
+ if ( variable->IsRegistered() )
+ return;
+
+ variable->m_bRegistered = true;
+
+ const char *pName = variable->GetName();
+ if ( !pName || !pName[0] )
+ {
+ variable->m_pNext = NULL;
+ return;
+ }
+
+ // If the variable is already defined, then setup the new variable as a proxy to it.
+ const ConCommandBase *pOther = FindVar( variable->GetName() );
+ if ( pOther )
+ {
+ if ( variable->IsCommand() || pOther->IsCommand() )
+ {
+ Warning( "WARNING: unable to link %s and %s because one or more is a ConCommand.\n", variable->GetName(), pOther->GetName() );
+ }
+ else
+ {
+ // This cast is ok because we make sure they're ConVars above.
+ const ConVar *pChildVar = static_cast< const ConVar* >( variable );
+ const ConVar *pParentVar = static_cast< const ConVar* >( pOther );
+
+ // See if it's a valid linkage
+ if ( s_pCVarQuery->AreConVarsLinkable( pChildVar, pParentVar ) )
+ {
+ // Make sure the default values are the same (but only spew about this for FCVAR_REPLICATED)
+ if( pChildVar->m_pszDefaultValue && pParentVar->m_pszDefaultValue &&
+ pChildVar->IsFlagSet( FCVAR_REPLICATED ) && pParentVar->IsFlagSet( FCVAR_REPLICATED ) )
+ {
+ if( Q_stricmp( pChildVar->m_pszDefaultValue, pParentVar->m_pszDefaultValue ) != 0 )
+ {
+ Warning( "Parent and child ConVars with different default values! %s child: %s parent: %s (parent wins)\n",
+ variable->GetName(), pChildVar->m_pszDefaultValue, pParentVar->m_pszDefaultValue );
+ }
+ }
+
+ const_cast<ConVar*>( pChildVar )->m_pParent = const_cast<ConVar*>( pParentVar )->m_pParent;
+
+ // Absorb material thread related convar flags
+ const_cast<ConVar*>( pParentVar )->m_nFlags |= pChildVar->m_nFlags & ( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS );
+
+ // check the parent's callbacks and slam if doesn't have, warn if both have callbacks
+ if( pChildVar->m_fnChangeCallback )
+ {
+ if ( !pParentVar->m_fnChangeCallback )
+ {
+ const_cast<ConVar*>( pParentVar )->m_fnChangeCallback = pChildVar->m_fnChangeCallback;
+ }
+ else
+ {
+ Warning( "Convar %s has multiple different change callbacks\n", variable->GetName() );
+ }
+ }
+
+ // make sure we don't have conflicting help strings.
+ if ( pChildVar->m_pszHelpString && Q_strlen( pChildVar->m_pszHelpString ) != 0 )
+ {
+ if ( pParentVar->m_pszHelpString && Q_strlen( pParentVar->m_pszHelpString ) != 0 )
+ {
+ if ( Q_stricmp( pParentVar->m_pszHelpString, pChildVar->m_pszHelpString ) != 0 )
+ {
+ Warning( "Convar %s has multiple help strings:\n\tparent (wins): \"%s\"\n\tchild: \"%s\"\n",
+ variable->GetName(), pParentVar->m_pszHelpString, pChildVar->m_pszHelpString );
+ }
+ }
+ else
+ {
+ const_cast<ConVar *>( pParentVar )->m_pszHelpString = pChildVar->m_pszHelpString;
+ }
+ }
+
+ // make sure we don't have conflicting FCVAR_CHEAT flags.
+ if ( ( pChildVar->m_nFlags & FCVAR_CHEAT ) != ( pParentVar->m_nFlags & FCVAR_CHEAT ) )
+ {
+ Warning( "Convar %s has conflicting FCVAR_CHEAT flags (child: %s, parent: %s, parent wins)\n",
+ variable->GetName(), ( pChildVar->m_nFlags & FCVAR_CHEAT ) ? "FCVAR_CHEAT" : "no FCVAR_CHEAT",
+ ( pParentVar->m_nFlags & FCVAR_CHEAT ) ? "FCVAR_CHEAT" : "no FCVAR_CHEAT" );
+ }
+
+ // make sure we don't have conflicting FCVAR_REPLICATED flags.
+ if ( ( pChildVar->m_nFlags & FCVAR_REPLICATED ) != ( pParentVar->m_nFlags & FCVAR_REPLICATED ) )
+ {
+ Warning( "Convar %s has conflicting FCVAR_REPLICATED flags (child: %s, parent: %s, parent wins)\n",
+ variable->GetName(), ( pChildVar->m_nFlags & FCVAR_REPLICATED ) ? "FCVAR_REPLICATED" : "no FCVAR_REPLICATED",
+ ( pParentVar->m_nFlags & FCVAR_REPLICATED ) ? "FCVAR_REPLICATED" : "no FCVAR_REPLICATED" );
+ }
+
+ // make sure we don't have conflicting FCVAR_DONTRECORD flags.
+ if ( ( pChildVar->m_nFlags & FCVAR_DONTRECORD ) != ( pParentVar->m_nFlags & FCVAR_DONTRECORD ) )
+ {
+ Warning( "Convar %s has conflicting FCVAR_DONTRECORD flags (child: %s, parent: %s, parent wins)\n",
+ variable->GetName(), ( pChildVar->m_nFlags & FCVAR_DONTRECORD ) ? "FCVAR_DONTRECORD" : "no FCVAR_DONTRECORD",
+ ( pParentVar->m_nFlags & FCVAR_DONTRECORD ) ? "FCVAR_DONTRECORD" : "no FCVAR_DONTRECORD" );
+ }
+ }
+ }
+
+ variable->m_pNext = NULL;
+ return;
+ }
+
+ // link the variable in
+ variable->m_pNext = m_pConCommandList;
+ m_pConCommandList = variable;
+}
+
+void CCvar::UnregisterConCommand( ConCommandBase *pCommandToRemove )
+{
+ // Not registered? Don't bother
+ if ( !pCommandToRemove->IsRegistered() )
+ return;
+
+ pCommandToRemove->m_bRegistered = false;
+
+ // FIXME: Should we make this a doubly-linked list? Would remove faster
+ ConCommandBase *pPrev = NULL;
+ for( ConCommandBase *pCommand = m_pConCommandList; pCommand; pCommand = pCommand->m_pNext )
+ {
+ if ( pCommand != pCommandToRemove )
+ {
+ pPrev = pCommand;
+ continue;
+ }
+
+ if ( pPrev == NULL )
+ {
+ m_pConCommandList = pCommand->m_pNext;
+ }
+ else
+ {
+ pPrev->m_pNext = pCommand->m_pNext;
+ }
+ pCommand->m_pNext = NULL;
+ break;
+ }
+}
+
+// Crash here in TF2, so I'm adding some debugging stuff.
+#ifdef WIN32
+#pragma optimize( "", off )
+#endif
+void CCvar::UnregisterConCommands( CVarDLLIdentifier_t id )
+{
+ ConCommandBase *pNewList;
+ ConCommandBase *pCommand, *pNext;
+
+ int iCommandsLooped = 0;
+
+ pNewList = NULL;
+ pCommand = m_pConCommandList;
+ while ( pCommand )
+ {
+ pNext = pCommand->m_pNext;
+ if ( pCommand->GetDLLIdentifier() != id )
+ {
+ pCommand->m_pNext = pNewList;
+ pNewList = pCommand;
+ }
+ else
+ {
+ // Unlink
+ pCommand->m_bRegistered = false;
+ pCommand->m_pNext = NULL;
+ }
+
+ pCommand = pNext;
+ iCommandsLooped++;
+ }
+
+ m_pConCommandList = pNewList;
+}
+#ifdef WIN32
+#pragma optimize( "", on )
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Finds base commands
+//-----------------------------------------------------------------------------
+const ConCommandBase *CCvar::FindCommandBase( const char *name ) const
+{
+ const ConCommandBase *cmd = GetCommands();
+ for ( ; cmd; cmd = cmd->GetNext() )
+ {
+ if ( !Q_stricmp( name, cmd->GetName() ) )
+ return cmd;
+ }
+ return NULL;
+}
+
+ConCommandBase *CCvar::FindCommandBase( const char *name )
+{
+ ConCommandBase *cmd = GetCommands();
+ for ( ; cmd; cmd = cmd->GetNext() )
+ {
+ if ( !Q_stricmp( name, cmd->GetName() ) )
+ return cmd;
+ }
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose Finds ConVars
+//-----------------------------------------------------------------------------
+const ConVar *CCvar::FindVar( const char *var_name ) const
+{
+ VPROF_INCREMENT_COUNTER( "CCvar::FindVar", 1 );
+ VPROF( "CCvar::FindVar" );
+ const ConCommandBase *var = FindCommandBase( var_name );
+ if ( !var || var->IsCommand() )
+ return NULL;
+
+ return static_cast<const ConVar*>(var);
+}
+
+ConVar *CCvar::FindVar( const char *var_name )
+{
+ VPROF_INCREMENT_COUNTER( "CCvar::FindVar", 1 );
+ VPROF( "CCvar::FindVar" );
+ ConCommandBase *var = FindCommandBase( var_name );
+ if ( !var || var->IsCommand() )
+ return NULL;
+
+ return static_cast<ConVar*>( var );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose Finds ConCommands
+//-----------------------------------------------------------------------------
+const ConCommand *CCvar::FindCommand( const char *pCommandName ) const
+{
+ const ConCommandBase *var = FindCommandBase( pCommandName );
+ if ( !var || !var->IsCommand() )
+ return NULL;
+
+ return static_cast<const ConCommand*>(var);
+}
+
+ConCommand *CCvar::FindCommand( const char *pCommandName )
+{
+ ConCommandBase *var = FindCommandBase( pCommandName );
+ if ( !var || !var->IsCommand() )
+ return NULL;
+
+ return static_cast<ConCommand*>( var );
+}
+
+
+const char* CCvar::GetCommandLineValue( const char *pVariableName )
+{
+ int nLen = Q_strlen(pVariableName);
+ char *pSearch = (char*)stackalloc( nLen + 2 );
+ pSearch[0] = '+';
+ memcpy( &pSearch[1], pVariableName, nLen + 1 );
+ return CommandLine()->ParmValue( pSearch );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+ConCommandBase *CCvar::GetCommands( void )
+{
+ return m_pConCommandList;
+}
+
+const ConCommandBase *CCvar::GetCommands( void ) const
+{
+ return m_pConCommandList;
+}
+
+
+//-----------------------------------------------------------------------------
+// Install, remove global callbacks
+//-----------------------------------------------------------------------------
+void CCvar::InstallGlobalChangeCallback( FnChangeCallback_t callback )
+{
+ Assert( callback && m_GlobalChangeCallbacks.Find( callback ) < 0 );
+ m_GlobalChangeCallbacks.AddToTail( callback );
+}
+
+void CCvar::RemoveGlobalChangeCallback( FnChangeCallback_t callback )
+{
+ Assert( callback );
+ m_GlobalChangeCallbacks.FindAndRemove( callback );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CCvar::CallGlobalChangeCallbacks( ConVar *var, const char *pOldString, float flOldValue )
+{
+ int nCallbackCount = m_GlobalChangeCallbacks.Count();
+ for ( int i = 0; i < nCallbackCount; ++i )
+ {
+ (*m_GlobalChangeCallbacks[i])( var, pOldString, flOldValue );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets convars containing the flags to their default value
+//-----------------------------------------------------------------------------
+void CCvar::RevertFlaggedConVars( int nFlag )
+{
+ for (const ConCommandBase *var= GetCommands() ; var ; var=var->GetNext())
+ {
+ if ( var->IsCommand() )
+ continue;
+
+ ConVar *pCvar = ( ConVar * )var;
+
+ if ( !pCvar->IsFlagSet( nFlag ) )
+ continue;
+
+ // It's == to the default value, don't count
+ if ( !Q_stricmp( pCvar->GetDefault(), pCvar->GetString() ) )
+ continue;
+
+ pCvar->Revert();
+
+ // DevMsg( "%s = \"%s\" (reverted)\n", cvar->GetName(), cvar->GetString() );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Deal with queued material system convars
+//-----------------------------------------------------------------------------
+bool CCvar::IsMaterialThreadSetAllowed( ) const
+{
+ Assert( ThreadInMainThread() );
+ return m_bMaterialSystemThreadSetAllowed;
+}
+
+void CCvar::QueueMaterialThreadSetValue( ConVar *pConVar, const char *pValue )
+{
+ Assert( ThreadInMainThread() );
+ int j = m_QueuedConVarSets.AddToTail();
+ m_QueuedConVarSets[j].m_pConVar = pConVar;
+ m_QueuedConVarSets[j].m_nType = CONVAR_SET_STRING;
+ m_QueuedConVarSets[j].m_String = pValue;
+}
+
+void CCvar::QueueMaterialThreadSetValue( ConVar *pConVar, int nValue )
+{
+ Assert( ThreadInMainThread() );
+ int j = m_QueuedConVarSets.AddToTail();
+ m_QueuedConVarSets[j].m_pConVar = pConVar;
+ m_QueuedConVarSets[j].m_nType = CONVAR_SET_INT;
+ m_QueuedConVarSets[j].m_nInt = nValue;
+}
+
+void CCvar::QueueMaterialThreadSetValue( ConVar *pConVar, float flValue )
+{
+ Assert( ThreadInMainThread() );
+ int j = m_QueuedConVarSets.AddToTail();
+ m_QueuedConVarSets[j].m_pConVar = pConVar;
+ m_QueuedConVarSets[j].m_nType = CONVAR_SET_FLOAT;
+ m_QueuedConVarSets[j].m_flFloat = flValue;
+}
+
+bool CCvar::HasQueuedMaterialThreadConVarSets() const
+{
+ Assert( ThreadInMainThread() );
+ return m_QueuedConVarSets.Count() > 0;
+}
+
+int CCvar::ProcessQueuedMaterialThreadConVarSets()
+{
+ Assert( ThreadInMainThread() );
+ m_bMaterialSystemThreadSetAllowed = true;
+
+ int nUpdateFlags = 0;
+ int nCount = m_QueuedConVarSets.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ const QueuedConVarSet_t& set = m_QueuedConVarSets[i];
+ switch( set.m_nType )
+ {
+ case CONVAR_SET_FLOAT:
+ set.m_pConVar->SetValue( set.m_flFloat );
+ break;
+ case CONVAR_SET_INT:
+ set.m_pConVar->SetValue( set.m_nInt );
+ break;
+ case CONVAR_SET_STRING:
+ set.m_pConVar->SetValue( set.m_String );
+ break;
+ }
+
+ nUpdateFlags |= set.m_pConVar->GetFlags() & FCVAR_MATERIAL_THREAD_MASK;
+ }
+
+ m_QueuedConVarSets.RemoveAll();
+ m_bMaterialSystemThreadSetAllowed = false;
+ return nUpdateFlags;
+}
+
+
+//-----------------------------------------------------------------------------
+// Display queued messages
+//-----------------------------------------------------------------------------
+void CCvar::DisplayQueuedMessages( )
+{
+ // Display any queued up messages
+ if ( m_TempConsoleBuffer.TellPut() == 0 )
+ return;
+
+ Color clr;
+ int nStringLength;
+ while( m_TempConsoleBuffer.IsValid() )
+ {
+ int nType = m_TempConsoleBuffer.GetChar();
+ if ( nType == CONSOLE_COLOR_PRINT )
+ {
+ clr.SetRawColor( m_TempConsoleBuffer.GetInt() );
+ }
+ nStringLength = m_TempConsoleBuffer.PeekStringLength();
+ char* pTemp = (char*)stackalloc( nStringLength + 1 );
+ m_TempConsoleBuffer.GetStringManualCharCount( pTemp, nStringLength + 1 );
+
+ switch( nType )
+ {
+ case CONSOLE_COLOR_PRINT:
+ ConsoleColorPrintf( clr, pTemp );
+ break;
+
+ case CONSOLE_PRINT:
+ ConsolePrintf( pTemp );
+ break;
+
+ case CONSOLE_DPRINT:
+ ConsoleDPrintf( pTemp );
+ break;
+ }
+ }
+
+ m_TempConsoleBuffer.Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// Install a console printer
+//-----------------------------------------------------------------------------
+void CCvar::InstallConsoleDisplayFunc( IConsoleDisplayFunc* pDisplayFunc )
+{
+ Assert( m_DisplayFuncs.Find( pDisplayFunc ) < 0 );
+ m_DisplayFuncs.AddToTail( pDisplayFunc );
+ DisplayQueuedMessages();
+}
+
+void CCvar::RemoveConsoleDisplayFunc( IConsoleDisplayFunc* pDisplayFunc )
+{
+ m_DisplayFuncs.FindAndRemove( pDisplayFunc );
+}
+
+void CCvar::ConsoleColorPrintf( const Color& clr, const char *pFormat, ... ) const
+{
+ char temp[ 8192 ];
+ va_list argptr;
+ va_start( argptr, pFormat );
+ _vsnprintf( temp, sizeof( temp ) - 1, pFormat, argptr );
+ va_end( argptr );
+ temp[ sizeof( temp ) - 1 ] = 0;
+
+ int c = m_DisplayFuncs.Count();
+ if ( c == 0 )
+ {
+ m_TempConsoleBuffer.PutChar( CONSOLE_COLOR_PRINT );
+ m_TempConsoleBuffer.PutInt( clr.GetRawColor() );
+ m_TempConsoleBuffer.PutString( temp );
+ return;
+ }
+
+ for ( int i = 0 ; i < c; ++i )
+ {
+ m_DisplayFuncs[ i ]->ColorPrint( clr, temp );
+ }
+}
+
+void CCvar::ConsolePrintf( const char *pFormat, ... ) const
+{
+ char temp[ 8192 ];
+ va_list argptr;
+ va_start( argptr, pFormat );
+ _vsnprintf( temp, sizeof( temp ) - 1, pFormat, argptr );
+ va_end( argptr );
+ temp[ sizeof( temp ) - 1 ] = 0;
+
+ int c = m_DisplayFuncs.Count();
+ if ( c == 0 )
+ {
+ m_TempConsoleBuffer.PutChar( CONSOLE_PRINT );
+ m_TempConsoleBuffer.PutString( temp );
+ return;
+ }
+
+ for ( int i = 0 ; i < c; ++i )
+ {
+ m_DisplayFuncs[ i ]->Print( temp );
+ }
+}
+
+void CCvar::ConsoleDPrintf( const char *pFormat, ... ) const
+{
+ char temp[ 8192 ];
+ va_list argptr;
+ va_start( argptr, pFormat );
+ _vsnprintf( temp, sizeof( temp ) - 1, pFormat, argptr );
+ va_end( argptr );
+ temp[ sizeof( temp ) - 1 ] = 0;
+
+ int c = m_DisplayFuncs.Count();
+ if ( c == 0 )
+ {
+ m_TempConsoleBuffer.PutChar( CONSOLE_DPRINT );
+ m_TempConsoleBuffer.PutString( temp );
+ return;
+ }
+
+ for ( int i = 0 ; i < c; ++i )
+ {
+ m_DisplayFuncs[ i ]->DPrint( temp );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+#if defined( _X360 )
+
+void CCvar::PublishToVXConsole()
+{
+ const char *commands[4096];
+ const char *helptext[4096];
+ const ConCommandBase *pCur;
+ int numCommands = 0;
+
+ // iterate and publish commands to the remote console
+ for ( pCur = m_pConCommandList; pCur; pCur=pCur->GetNext() )
+ {
+ // add unregistered commands to list
+ if ( numCommands < sizeof(commands)/sizeof(commands[0]) )
+ {
+ commands[numCommands] = pCur->GetName();
+ helptext[numCommands] = pCur->GetHelpText();
+ numCommands++;
+ }
+ }
+
+ if ( numCommands )
+ {
+ XBX_rAddCommands( numCommands, commands, helptext );
+ }
+}
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Console commands
+//-----------------------------------------------------------------------------
+void CCvar::Find( const CCommand &args )
+{
+ const char *search;
+ const ConCommandBase *var;
+
+ if ( args.ArgC() != 2 )
+ {
+ ConMsg( "Usage: find <string>\n" );
+ return;
+ }
+
+ // Get substring to find
+ search = args[1];
+
+ // Loop through vars and print out findings
+ for ( var = GetCommands(); var; var=var->GetNext() )
+ {
+ if ( var->IsFlagSet(FCVAR_DEVELOPMENTONLY) || var->IsFlagSet(FCVAR_HIDDEN) )
+ continue;
+
+ if ( !Q_stristr( var->GetName(), search ) &&
+ !Q_stristr( var->GetHelpText(), search ) )
+ continue;
+
+ ConVar_PrintDescription( var );
+ }
+}
+
+