1 //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
8 //-----------------------------------------------------------------------------
10 //===========================================================================//
19 #include "tier0/dbg.h"
20 #include "tier1/iconvar.h"
21 #include "tier1/utlvector.h"
22 #include "tier1/utlstring.h"
26 #define FORCEINLINE_CVAR FORCEINLINE
28 #define FORCEINLINE_CVAR inline
34 //-----------------------------------------------------------------------------
35 // Forward declarations
36 //-----------------------------------------------------------------------------
41 struct characterset_t;
45 //-----------------------------------------------------------------------------
46 // Any executable that wants to use ConVars need to implement one of
47 // these to hook up access to console variables.
48 //-----------------------------------------------------------------------------
49 class IConCommandBaseAccessor
52 // Flags is a combination of FCVAR flags in cvar.h.
53 // hOut is filled in with a handle to the variable.
54 virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
58 //-----------------------------------------------------------------------------
59 // Helper method for console development
60 //-----------------------------------------------------------------------------
61 #if defined( _X360 ) && !defined( _RETAIL )
62 void ConVar_PublishToVXConsole();
66 //-----------------------------------------------------------------------------
67 // Called when a ConCommand needs to execute
68 //-----------------------------------------------------------------------------
69 typedef void ( *FnCommandCallbackV1_t )( void );
70 typedef void ( *FnCommandCallback_t )( const CCommand &command );
72 #define COMMAND_COMPLETION_MAXITEMS 64
73 #define COMMAND_COMPLETION_ITEM_LENGTH 64
75 //-----------------------------------------------------------------------------
76 // Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
77 //-----------------------------------------------------------------------------
78 typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
81 //-----------------------------------------------------------------------------
83 //-----------------------------------------------------------------------------
84 class ICommandCallback
87 virtual void CommandCallback( const CCommand &command ) = 0;
90 class ICommandCompletionCallback
93 virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
96 //-----------------------------------------------------------------------------
97 // Purpose: The base console invoked command/cvar interface
98 //-----------------------------------------------------------------------------
103 friend class ConCommand;
104 friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
105 friend void ConVar_PublishToVXConsole();
107 // FIXME: Remove when ConVar changes are done
108 friend class CDefaultCvar;
111 ConCommandBase( void );
112 ConCommandBase( const char *pName, const char *pHelpString = 0,
115 virtual ~ConCommandBase( void );
117 virtual bool IsCommand( void ) const;
120 virtual bool IsFlagSet( int flag ) const;
122 virtual void AddFlags( int flags );
124 virtual void RemoveFlags( int flags );
126 virtual int GetFlags( void ) const;
128 // Return name of cvar
129 virtual const char *GetName( void ) const;
131 // Return help text for cvar
132 virtual const char *GetHelpText( void ) const;
134 // Deal with next pointer
135 const ConCommandBase *GetNext( void ) const;
136 ConCommandBase *GetNext( void );
138 inline void SetNext(ConCommandBase *pBase)
143 virtual bool IsRegistered( void ) const;
145 // Returns the DLL identifier
146 virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
149 virtual void Create( const char *pName, const char *pHelpString = 0,
152 // Used internally by OneTimeInit to initialize/shutdown
156 // Internal copy routine ( uses new operator from correct module )
157 char *CopyString( const char *from );
160 // Next ConVar in chain
161 // Prior to register, it points to the next convar in the DLL.
162 // Once registered, though, m_pNext is reset to point to the next
163 // convar in the global list
164 ConCommandBase *m_pNext;
166 // Has the cvar been added to the global list?
170 const char *m_pszName;
171 const char *m_pszHelpString;
177 // ConVars add themselves to this list for the executable.
178 // Then ConVar_Register runs through all the console variables
179 // and registers them into a global list stored in vstdlib.dll
180 static ConCommandBase *s_pConCommandBases;
182 // ConVars in this executable use this 'global' to access values.
183 static IConCommandBaseAccessor *s_pAccessor;
185 inline void SetFlags(int flags)
192 //-----------------------------------------------------------------------------
194 //-----------------------------------------------------------------------------
199 CCommand( int nArgC, const char **ppArgV );
200 bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
204 const char **ArgV() const;
205 const char *ArgS() const; // All args that occur after the 0th arg, in string form
206 const char *GetCommandString() const; // The entire command in string form, including the 0th arg
207 const char *operator[]( int nIndex ) const; // Gets at arguments
208 const char *Arg( int nIndex ) const; // Gets at arguments
210 // Helper functions to parse arguments to commands.
211 const char* FindArg( const char *pName ) const;
212 int FindArgInt( const char *pName, int nDefaultVal ) const;
214 static int MaxCommandLength();
215 static characterset_t* DefaultBreakSet();
220 COMMAND_MAX_ARGC = 64,
221 COMMAND_MAX_LENGTH = 512,
226 char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
227 char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
228 const char* m_ppArgv[ COMMAND_MAX_ARGC ];
231 inline int CCommand::MaxCommandLength()
233 return COMMAND_MAX_LENGTH - 1;
236 inline int CCommand::ArgC() const
241 inline const char **CCommand::ArgV() const
243 return m_nArgc ? (const char**)m_ppArgv : NULL;
246 inline const char *CCommand::ArgS() const
248 return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
251 inline const char *CCommand::GetCommandString() const
253 return m_nArgc ? m_pArgSBuffer : "";
256 inline const char *CCommand::Arg( int nIndex ) const
258 // FIXME: Many command handlers appear to not be particularly careful
259 // about checking for valid argc range. For now, we're going to
260 // do the extra check and return an empty string if it's out of range
261 if ( nIndex < 0 || nIndex >= m_nArgc )
263 return m_ppArgv[nIndex];
266 inline const char *CCommand::operator[]( int nIndex ) const
268 return Arg( nIndex );
272 //-----------------------------------------------------------------------------
273 // Purpose: The console invoked command
274 //-----------------------------------------------------------------------------
275 class ConCommand : public ConCommandBase
280 typedef ConCommandBase BaseClass;
282 ConCommand( const char *pName, FnCommandCallbackV1_t callback,
283 const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
284 ConCommand( const char *pName, FnCommandCallback_t callback,
285 const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
286 ConCommand( const char *pName, ICommandCallback *pCallback,
287 const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
289 virtual ~ConCommand( void );
291 virtual bool IsCommand( void ) const;
293 virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
295 virtual bool CanAutoComplete( void );
297 // Invoke the function
298 virtual void Dispatch( const CCommand &command );
301 // NOTE: To maintain backward compat, we have to be very careful:
302 // All public virtual methods must appear in the same order always
303 // since engine code will be calling into this code, which *does not match*
304 // in the mod code; it's using slightly different, but compatible versions
305 // of this class. Also: Be very careful about adding new fields to this class.
306 // Those fields will not exist in the version of this class that is instanced
309 // Call this function when executing the command
312 FnCommandCallbackV1_t m_fnCommandCallbackV1;
313 FnCommandCallback_t m_fnCommandCallback;
314 ICommandCallback *m_pCommandCallback;
319 FnCommandCompletionCallback m_fnCompletionCallback;
320 ICommandCompletionCallback *m_pCommandCompletionCallback;
323 bool m_bHasCompletionCallback : 1;
324 bool m_bUsingNewCommandCallback : 1;
325 bool m_bUsingCommandCallbackInterface : 1;
327 inline FnCommandCallback_t GetCallback() const
329 return m_fnCommandCallback;
334 //-----------------------------------------------------------------------------
335 // Purpose: A console variable
336 //-----------------------------------------------------------------------------
337 class ConVar : public ConCommandBase, public IConVar
340 friend class ConVarRef;
343 typedef ConCommandBase BaseClass;
345 ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
347 ConVar( const char *pName, const char *pDefaultValue, int flags,
348 const char *pHelpString );
349 ConVar( const char *pName, const char *pDefaultValue, int flags,
350 const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
351 ConVar( const char *pName, const char *pDefaultValue, int flags,
352 const char *pHelpString, FnChangeCallback_t callback );
353 ConVar( const char *pName, const char *pDefaultValue, int flags,
354 const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
355 FnChangeCallback_t callback );
357 virtual ~ConVar( void );
359 virtual bool IsCommand( void ) const;
360 virtual bool IsFlagSet( int flag ) const;
361 virtual void AddFlags( int flags );
362 virtual int GetFlags( void ) const;
363 virtual const char *GetName( void ) const;
364 virtual const char* GetHelpText( void ) const;
365 virtual bool IsRegistered( void ) const;
367 // Install a change callback (there shouldn't already be one....)
368 void InstallChangeCallback( FnChangeCallback_t callback );
371 FORCEINLINE_CVAR float GetFloat( void ) const;
372 FORCEINLINE_CVAR int GetInt( void ) const;
373 FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
374 FORCEINLINE_CVAR char const *GetString( void ) const;
376 // Used internally by OneTimeInit to initialize.
379 virtual const char *GetBaseName( void ) const;
380 virtual int GetSplitScreenPlayerSlot ( void ) const;
382 // Any function that allocates/frees memory needs to be virtual or else you'll have crashes
383 // from alloc/free across dll/exe boundaries.
385 // These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
386 virtual void SetValue( const char *value );
387 virtual void SetValue( float value );
388 virtual void SetValue( int value );
389 #if SOURCE_ENGINE == SE_LEFT4DEAD2
390 virtual void SetValue( Color value );
393 // Reset to default value
396 // True if it has a min/max setting
397 bool GetMin( float& minVal ) const;
398 bool GetMax( float& maxVal ) const;
399 const char *GetDefault( void ) const;
402 // Called by CCvar when the value of a var is changing.
403 virtual void InternalSetValue(const char *value);
404 // For CVARs marked FCVAR_NEVER_AS_STRING
405 virtual void InternalSetFloatValue( float fNewValue );
406 virtual void InternalSetIntValue( int nValue );
408 virtual bool ClampValue( float& value );
409 virtual void ChangeStringValue( const char *tempVal, float flOldValue );
411 virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
412 const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
413 bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
417 // This either points to "this" or it points to the original declaration of a ConVar.
418 // This allows ConVars to exist in separate modules, and they all use the first one to be declared.
419 // m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
423 const char *m_pszDefaultValue;
426 // Dynamically allocated
440 // Call this function when ConVar changes
441 FnChangeCallback_t m_fnChangeCallback;
443 inline FnChangeCallback_t GetCallback() const
445 return m_fnChangeCallback;
447 inline void SetMin(bool set, float min=0.0)
452 inline void SetMax(bool set, float max=0.0)
460 //-----------------------------------------------------------------------------
461 // Purpose: Return ConVar value as a float
463 //-----------------------------------------------------------------------------
464 FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
466 return m_pParent->m_fValue;
469 //-----------------------------------------------------------------------------
470 // Purpose: Return ConVar value as an int
472 //-----------------------------------------------------------------------------
473 FORCEINLINE_CVAR int ConVar::GetInt( void ) const
475 return m_pParent->m_nValue;
479 //-----------------------------------------------------------------------------
480 // Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
481 // Output : const char *
482 //-----------------------------------------------------------------------------
483 FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
485 if ( m_nFlags & FCVAR_NEVER_AS_STRING )
486 return "FCVAR_NEVER_AS_STRING";
488 return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
492 //-----------------------------------------------------------------------------
493 // Used to read/write convars that already exist (replaces the FindVar method)
494 //-----------------------------------------------------------------------------
498 ConVarRef( const char *pName );
499 ConVarRef( const char *pName, bool bIgnoreMissing );
500 ConVarRef( IConVar *pConVar );
502 void Init( const char *pName, bool bIgnoreMissing );
503 bool IsValid() const;
504 bool IsFlagSet( int nFlags ) const;
505 IConVar *GetLinkedConVar();
508 float GetFloat( void ) const;
509 int GetInt( void ) const;
510 bool GetBool() const { return !!GetInt(); }
511 const char *GetString( void ) const;
513 void SetValue( const char *pValue );
514 void SetValue( float flValue );
515 void SetValue( int nValue );
516 void SetValue( bool bValue );
518 const char *GetName() const;
520 const char *GetDefault() const;
523 // High-speed method to read convar data
525 ConVar *m_pConVarState;
529 //-----------------------------------------------------------------------------
530 // Did we find an existing convar of that name?
531 //-----------------------------------------------------------------------------
532 FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
534 return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
537 FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
542 FORCEINLINE_CVAR const char *ConVarRef::GetName() const
544 return m_pConVar->GetName();
548 //-----------------------------------------------------------------------------
549 // Purpose: Return ConVar value as a float
550 //-----------------------------------------------------------------------------
551 FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
553 return m_pConVarState->m_fValue;
556 //-----------------------------------------------------------------------------
557 // Purpose: Return ConVar value as an int
558 //-----------------------------------------------------------------------------
559 FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
561 return m_pConVarState->m_nValue;
564 //-----------------------------------------------------------------------------
565 // Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
566 //-----------------------------------------------------------------------------
567 FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
569 Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
570 return m_pConVarState->m_pszString;
574 FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
576 m_pConVar->SetValue( pValue );
579 FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
581 m_pConVar->SetValue( flValue );
584 FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
586 m_pConVar->SetValue( nValue );
589 FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
591 m_pConVar->SetValue( bValue ? 1 : 0 );
594 FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
596 return m_pConVarState->m_pszDefaultValue;
600 //-----------------------------------------------------------------------------
601 // Called by the framework to register ConCommands with the ICVar
602 //-----------------------------------------------------------------------------
603 void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
604 void ConVar_Unregister( );
607 //-----------------------------------------------------------------------------
609 //-----------------------------------------------------------------------------
610 void ConVar_PrintFlags( const ConCommandBase *var );
611 void ConVar_PrintDescription( const ConCommandBase *pVar );
614 //-----------------------------------------------------------------------------
615 // Purpose: Utility class to quickly allow ConCommands to call member methods
616 //-----------------------------------------------------------------------------
618 #pragma warning (disable : 4355 )
622 class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
624 typedef ConCommand BaseClass;
625 typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
626 typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
629 CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
630 int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
631 BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
635 m_CompletionFunc = completionFunc;
638 ~CConCommandMemberAccessor()
643 void SetOwner( T* pOwner )
648 virtual void CommandCallback( const CCommand &command )
650 Assert( m_pOwner && m_Func );
651 (m_pOwner->*m_Func)( command );
654 virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
656 Assert( m_pOwner && m_CompletionFunc );
657 return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
662 FnMemberCommandCallback_t m_Func;
663 FnMemberCommandCompletionCallback_t m_CompletionFunc;
667 #pragma warning ( default : 4355 )
670 //-----------------------------------------------------------------------------
671 // Purpose: Utility macros to quicky generate a simple console command
672 //-----------------------------------------------------------------------------
673 #define CON_COMMAND( name, description ) \
674 static void name( const CCommand &args ); \
675 static ConCommand name##_command( #name, name, description ); \
676 static void name( const CCommand &args )
678 #define CON_COMMAND_F( name, description, flags ) \
679 static void name( const CCommand &args ); \
680 static ConCommand name##_command( #name, name, description, flags ); \
681 static void name( const CCommand &args )
683 #define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
684 static void name( const CCommand &args ); \
685 static ConCommand name##_command( #name, name, description, flags, completion ); \
686 static void name( const CCommand &args )
688 #define CON_COMMAND_EXTERN( name, _funcname, description ) \
689 void _funcname( const CCommand &args ); \
690 static ConCommand name##_command( #name, _funcname, description ); \
691 void _funcname( const CCommand &args )
693 #define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
694 void _funcname( const CCommand &args ); \
695 static ConCommand name##_command( #name, _funcname, description, flags ); \
696 void _funcname( const CCommand &args )
698 #define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
699 void _funcname( const CCommand &args ); \
700 friend class CCommandMemberInitializer_##_funcname; \
701 class CCommandMemberInitializer_##_funcname \
704 CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
706 m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
709 CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
712 CCommandMemberInitializer_##_funcname m_##_funcname##_register; \