|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Deals with singleton
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "igamesystem.h"
#include "datacache/imdlcache.h"
#include "utlvector.h"
#include "vprof.h"
#if defined( _X360 )
#include "xbox/xbox_console.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Pointer to a member method of IGameSystem
typedef void (IGameSystem::*GameSystemFunc_t)();
// Pointer to a member method of IGameSystem
typedef void (IGameSystemPerFrame::*PerFrameGameSystemFunc_t)();
// Used to invoke a method of all added Game systems in order
static void InvokeMethod( GameSystemFunc_t f, char const *timed = 0 ); // Used to invoke a method of all added Game systems in reverse order
static void InvokeMethodReverseOrder( GameSystemFunc_t f );
// Used to invoke a method of all added Game systems in order
static void InvokePerFrameMethod( PerFrameGameSystemFunc_t f, char const *timed = 0 );
static bool s_bSystemsInitted = false;
// List of all installed Game systems
static CUtlVector<IGameSystem*> s_GameSystems( 0, 4 ); // List of all installed Game systems
static CUtlVector<IGameSystemPerFrame*> s_GameSystemsPerFrame( 0, 4 );
// The map name
static char* s_pMapName = 0;
static CBasePlayer *s_pRunCommandPlayer = NULL; static CUserCmd *s_pRunCommandUserCmd = NULL;
//-----------------------------------------------------------------------------
// Auto-registration of game systems
//-----------------------------------------------------------------------------
static CAutoGameSystem *s_pSystemList = NULL;
CAutoGameSystem::CAutoGameSystem( char const *name ) : m_pszName( name ) { // If s_GameSystems hasn't been initted yet, then add ourselves to the global list
// because we don't know if the constructor for s_GameSystems has happened yet.
// Otherwise, we can add ourselves right into that list.
if ( s_bSystemsInitted ) { Add( this ); } else { m_pNext = s_pSystemList; s_pSystemList = this; } }
static CAutoGameSystemPerFrame *s_pPerFrameSystemList = NULL;
//-----------------------------------------------------------------------------
// Purpose: This is a CAutoGameSystem which also cares about the "per frame" hooks
//-----------------------------------------------------------------------------
CAutoGameSystemPerFrame::CAutoGameSystemPerFrame( char const *name ) : m_pszName( name ) { // If s_GameSystems hasn't been initted yet, then add ourselves to the global list
// because we don't know if the constructor for s_GameSystems has happened yet.
// Otherwise, we can add ourselves right into that list.
if ( s_bSystemsInitted ) { Add( this ); } else { m_pNext = s_pPerFrameSystemList; s_pPerFrameSystemList = this; } }
//-----------------------------------------------------------------------------
// destructor, cleans up automagically....
//-----------------------------------------------------------------------------
IGameSystem::~IGameSystem() { Remove( this ); }
//-----------------------------------------------------------------------------
// destructor, cleans up automagically....
//-----------------------------------------------------------------------------
IGameSystemPerFrame::~IGameSystemPerFrame() { Remove( this ); }
//-----------------------------------------------------------------------------
// Adds a system to the list of systems to run
//-----------------------------------------------------------------------------
void IGameSystem::Add( IGameSystem* pSys ) { s_GameSystems.AddToTail( pSys ); if ( dynamic_cast< IGameSystemPerFrame * >( pSys ) != NULL ) { s_GameSystemsPerFrame.AddToTail( static_cast< IGameSystemPerFrame * >( pSys ) ); } }
//-----------------------------------------------------------------------------
// Removes a system from the list of systems to update
//-----------------------------------------------------------------------------
void IGameSystem::Remove( IGameSystem* pSys ) { s_GameSystems.FindAndRemove( pSys ); if ( dynamic_cast< IGameSystemPerFrame * >( pSys ) != NULL ) { s_GameSystemsPerFrame.FindAndRemove( static_cast< IGameSystemPerFrame * >( pSys ) ); } }
//-----------------------------------------------------------------------------
// Removes *all* systems from the list of systems to update
//-----------------------------------------------------------------------------
void IGameSystem::RemoveAll( ) { s_GameSystems.RemoveAll(); s_GameSystemsPerFrame.RemoveAll(); }
//-----------------------------------------------------------------------------
// Client systems can use this to get at the map name
//-----------------------------------------------------------------------------
char const* IGameSystem::MapName() { return s_pMapName; }
#ifndef CLIENT_DLL
CBasePlayer *IGameSystem::RunCommandPlayer() { return s_pRunCommandPlayer; }
CUserCmd *IGameSystem::RunCommandUserCmd() { return s_pRunCommandUserCmd; } #endif
//-----------------------------------------------------------------------------
// Invokes methods on all installed game systems
//-----------------------------------------------------------------------------
bool IGameSystem::InitAllSystems() { int i;
{ // first add any auto systems to the end
CAutoGameSystem *pSystem = s_pSystemList; while ( pSystem ) { if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() ) { Add( pSystem ); } else { DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" ); } pSystem = pSystem->m_pNext; } s_pSystemList = NULL; }
{ CAutoGameSystemPerFrame *pSystem = s_pPerFrameSystemList; while ( pSystem ) { if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() ) { Add( pSystem ); } else { DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" ); }
pSystem = pSystem->m_pNext; } s_pSystemList = NULL; } // Now remember that we are initted so new CAutoGameSystems will add themselves automatically.
s_bSystemsInitted = true;
for ( i = 0; i < s_GameSystems.Count(); ++i ) { MDLCACHE_CRITICAL_SECTION();
IGameSystem *sys = s_GameSystems[i];
#if defined( _X360 )
char sz[128]; Q_snprintf( sz, sizeof( sz ), "%s->Init():Start", sys->Name() ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif
bool valid = sys->Init();
#if defined( _X360 )
Q_snprintf( sz, sizeof( sz ), "%s->Init():Finish", sys->Name() ); XBX_rTimeStampLog( Plat_FloatTime(), sz ); #endif
if ( !valid ) return false; }
return true; }
void IGameSystem::PostInitAllSystems( void ) { InvokeMethod( &IGameSystem::PostInit, "PostInit" ); }
void IGameSystem::ShutdownAllSystems() { InvokeMethodReverseOrder( &IGameSystem::Shutdown ); }
void IGameSystem::LevelInitPreEntityAllSystems( char const* pMapName ) { // Store off the map name
if ( s_pMapName ) { delete[] s_pMapName; }
int len = Q_strlen(pMapName) + 1; s_pMapName = new char [ len ]; Q_strncpy( s_pMapName, pMapName, len );
InvokeMethod( &IGameSystem::LevelInitPreEntity, "LevelInitPreEntity" ); }
void IGameSystem::LevelInitPostEntityAllSystems( void ) { InvokeMethod( &IGameSystem::LevelInitPostEntity, "LevelInitPostEntity" ); }
void IGameSystem::LevelShutdownPreClearSteamAPIContextAllSystems() { InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPreClearSteamAPIContext ); }
void IGameSystem::LevelShutdownPreEntityAllSystems() { InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPreEntity ); }
void IGameSystem::LevelShutdownPostEntityAllSystems() { InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPostEntity );
if ( s_pMapName ) { delete[] s_pMapName; s_pMapName = 0; } }
void IGameSystem::OnSaveAllSystems() { InvokeMethod( &IGameSystem::OnSave ); }
void IGameSystem::OnRestoreAllSystems() { InvokeMethod( &IGameSystem::OnRestore ); }
void IGameSystem::SafeRemoveIfDesiredAllSystems() { InvokeMethodReverseOrder( &IGameSystem::SafeRemoveIfDesired ); }
#ifdef CLIENT_DLL
void IGameSystem::PreRenderAllSystems() { VPROF("IGameSystem::PreRenderAllSystems"); InvokePerFrameMethod( &IGameSystemPerFrame::PreRender ); }
void IGameSystem::UpdateAllSystems( float frametime ) { SafeRemoveIfDesiredAllSystems();
int i; int c = s_GameSystemsPerFrame.Count(); for ( i = 0; i < c; ++i ) { IGameSystemPerFrame *sys = s_GameSystemsPerFrame[i]; MDLCACHE_CRITICAL_SECTION(); tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s - %s", __FUNCTION__, sys->Name() ); sys->Update( frametime ); } }
void IGameSystem::PostRenderAllSystems() { InvokePerFrameMethod( &IGameSystemPerFrame::PostRender ); }
#else
void IGameSystem::FrameUpdatePreEntityThinkAllSystems() { InvokePerFrameMethod( &IGameSystemPerFrame::FrameUpdatePreEntityThink ); }
void IGameSystem::FrameUpdatePostEntityThinkAllSystems() { SafeRemoveIfDesiredAllSystems();
InvokePerFrameMethod( &IGameSystemPerFrame::FrameUpdatePostEntityThink ); }
void IGameSystem::PreClientUpdateAllSystems() { InvokePerFrameMethod( &IGameSystemPerFrame::PreClientUpdate ); }
#endif
//-----------------------------------------------------------------------------
// Invokes a method on all installed game systems in proper order
//-----------------------------------------------------------------------------
void InvokeMethod( GameSystemFunc_t f, char const *timed /*=0*/ ) { NOTE_UNUSED( timed );
int i; int c = s_GameSystems.Count(); for ( i = 0; i < c ; ++i ) { IGameSystem *sys = s_GameSystems[i];
MDLCACHE_CRITICAL_SECTION();
(sys->*f)(); } }
//-----------------------------------------------------------------------------
// Invokes a method on all installed game systems in proper order
//-----------------------------------------------------------------------------
void InvokePerFrameMethod( PerFrameGameSystemFunc_t f, char const *timed /*=0*/ ) { NOTE_UNUSED( timed );
int i; int c = s_GameSystemsPerFrame.Count(); for ( i = 0; i < c ; ++i ) { IGameSystemPerFrame *sys = s_GameSystemsPerFrame[i]; MDLCACHE_CRITICAL_SECTION(); (sys->*f)(); } }
//-----------------------------------------------------------------------------
// Invokes a method on all installed game systems in reverse order
//-----------------------------------------------------------------------------
void InvokeMethodReverseOrder( GameSystemFunc_t f ) { int i; int c = s_GameSystems.Count(); for ( i = c; --i >= 0; ) { IGameSystem *sys = s_GameSystems[i]; MDLCACHE_CRITICAL_SECTION(); (sys->*f)(); } }
|