//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: List of game managers to update // // $Revision: $ // $NoKeywords: $ //===========================================================================// #include "gamemanager.h" #include "tier0/icommandline.h" // FIXME: REMOVE (for Sleep) #include //----------------------------------------------------------------------------- // globals //----------------------------------------------------------------------------- int IGameManager::m_nFrameNumber = 0; bool IGameManager::m_bStopRequested = false; bool IGameManager::m_bIsRunning = false; bool IGameManager::m_bIsInitialized = false; bool IGameManager::m_bLevelStartRequested = false; bool IGameManager::m_bLevelShutdownRequested = false; float IGameManager::m_flCurrentTime = 0.0f; float IGameManager::m_flLastTime = 0.0f; LevelState_t IGameManager::m_LevelState = NOT_IN_LEVEL; CUtlVector< IGameManager* > IGameManager::m_GameManagers; //----------------------------------------------------------------------------- // Adds a system to the list of systems to run //----------------------------------------------------------------------------- void IGameManager::Add( IGameManager* pSys ) { Assert( !m_bIsRunning ); m_GameManagers.AddToTail( pSys ); } //----------------------------------------------------------------------------- // Removes a system from the list of systems to update //----------------------------------------------------------------------------- void IGameManager::Remove( IGameManager* pSys ) { Assert( !m_bIsRunning ); m_GameManagers.FindAndRemove( pSys ); } //----------------------------------------------------------------------------- // Removes *all* systems from the list of systems to update //----------------------------------------------------------------------------- void IGameManager::RemoveAll( ) { m_GameManagers.RemoveAll(); } //----------------------------------------------------------------------------- // Invokes a method on all installed game systems in proper order //----------------------------------------------------------------------------- void IGameManager::InvokeMethod( GameManagerFunc_t f ) { int i; int nCount = m_GameManagers.Count(); for ( i = 0; i < nCount; ++i ) { (m_GameManagers[i]->*f)(); } } void IGameManager::InvokeMethodReverseOrder( GameManagerFunc_t f ) { int i; int nCount = m_GameManagers.Count(); for ( i = nCount; --i >= 0; ) { (m_GameManagers[i]->*f)(); } } bool IGameManager::InvokeMethod( GameManagerInitFunc_t f ) { int i; int nCount = m_GameManagers.Count(); for ( i = 0; i < nCount; ++i ) { if ( !(m_GameManagers[i]->*f)() ) return false; } return true; } LevelRetVal_t IGameManager::InvokeLevelMethod( GameManagerLevelFunc_t f, bool bFirstCall ) { LevelRetVal_t nRetVal = FINISHED; int i; int nCount = m_GameManagers.Count(); for ( i = 0; i < nCount; ++i ) { LevelRetVal_t val = (m_GameManagers[i]->*f)( bFirstCall ); if ( val == FAILED ) return FAILED; if ( val == MORE_WORK ) { nRetVal = MORE_WORK; } } return nRetVal; } LevelRetVal_t IGameManager::InvokeLevelMethodReverseOrder( GameManagerLevelFunc_t f, bool bFirstCall ) { LevelRetVal_t nRetVal = FINISHED; int i; int nCount = m_GameManagers.Count(); for ( i = 0; i < nCount; ++i ) { LevelRetVal_t val = ( m_GameManagers[i]->*f )( bFirstCall ); if ( val == FAILED ) { nRetVal = FAILED; } if ( ( val == MORE_WORK ) && ( nRetVal != FAILED ) ) { nRetVal = MORE_WORK; } } return nRetVal; } //----------------------------------------------------------------------------- // Init, shutdown game system //----------------------------------------------------------------------------- bool IGameManager::InitAllManagers() { m_nFrameNumber = 0; if ( !InvokeMethod( &IGameManager::Init ) ) return false; m_bIsInitialized = true; return true; } void IGameManager::ShutdownAllManagers() { if ( m_bIsInitialized ) { InvokeMethodReverseOrder( &IGameManager::Shutdown ); m_bIsInitialized = false; } } //----------------------------------------------------------------------------- // Updates the state machine related to loading levels //----------------------------------------------------------------------------- void IGameManager::UpdateLevelStateMachine() { // Do we want to switch into the level shutdown state? bool bFirstLevelShutdownFrame = false; if ( m_bLevelShutdownRequested ) { if ( m_LevelState != LOADING_LEVEL ) { m_bLevelShutdownRequested = false; } if ( m_LevelState == IN_LEVEL ) { m_LevelState = SHUTTING_DOWN_LEVEL; bFirstLevelShutdownFrame = true; } } // Perform level shutdown if ( m_LevelState == SHUTTING_DOWN_LEVEL ) { LevelRetVal_t val = InvokeLevelMethodReverseOrder( &IGameManager::LevelShutdown, bFirstLevelShutdownFrame ); if ( val != MORE_WORK ) { m_LevelState = NOT_IN_LEVEL; } } // Do we want to switch into the level startup state? bool bFirstLevelStartFrame = false; if ( m_bLevelStartRequested ) { if ( m_LevelState != SHUTTING_DOWN_LEVEL ) { m_bLevelStartRequested = false; } if ( m_LevelState == NOT_IN_LEVEL ) { m_LevelState = LOADING_LEVEL; bFirstLevelStartFrame = true; } } // Perform level load if ( m_LevelState == LOADING_LEVEL ) { LevelRetVal_t val = InvokeLevelMethod( &IGameManager::LevelInit, bFirstLevelStartFrame ); if ( val == FAILED ) { m_LevelState = NOT_IN_LEVEL; } else if ( val == FINISHED ) { m_LevelState = IN_LEVEL; } } } //----------------------------------------------------------------------------- // Runs the main loop. //----------------------------------------------------------------------------- void IGameManager::Start() { Assert( !m_bIsRunning && m_bIsInitialized ); m_bIsRunning = true; m_bStopRequested = false; // This option is useful when running the app twice on the same machine // It makes the 2nd instance of the app run a lot faster bool bPlayNice = ( CommandLine()->CheckParm( "-yieldcycles" ) != 0 ); float flStartTime = m_flCurrentTime = m_flLastTime = Plat_FloatTime(); int nFramesSimulated = 0; int nCount = m_GameManagers.Count(); while ( !m_bStopRequested ) { UpdateLevelStateMachine(); m_flLastTime = m_flCurrentTime; m_flCurrentTime = Plat_FloatTime(); int nSimulationFramesNeeded = 1 + (int)( ( m_flCurrentTime - flStartTime ) / TICK_INTERVAL ); while( nSimulationFramesNeeded > nFramesSimulated ) { for ( int i = 0; i < nCount; ++i ) { if ( m_GameManagers[i]->PerformsSimulation() ) { m_GameManagers[i]->Update(); } } ++m_nFrameNumber; ++nFramesSimulated; } // Always do I/O related managers regardless of framerate for ( int i = 0; i < nCount; ++i ) { if ( !m_GameManagers[i]->PerformsSimulation() ) { m_GameManagers[i]->Update(); } } if ( bPlayNice ) { Sleep( 1 ); } } m_bIsRunning = false; } //----------------------------------------------------------------------------- // Stops the main loop at the next appropriate time //----------------------------------------------------------------------------- void IGameManager::Stop() { if ( m_bIsRunning ) { m_bStopRequested = true; } } //----------------------------------------------------------------------------- // Returns the current frame number //----------------------------------------------------------------------------- int IGameManager::FrameNumber() { return m_nFrameNumber; } float IGameManager::CurrentSimulationTime() { return m_nFrameNumber * TICK_INTERVAL; } float IGameManager::SimulationDeltaTime() { return TICK_INTERVAL; } //----------------------------------------------------------------------------- // Used in rendering //----------------------------------------------------------------------------- float IGameManager::CurrentTime() { return m_flCurrentTime; } float IGameManager::DeltaTime() { return m_flCurrentTime - m_flLastTime; } //----------------------------------------------------------------------------- // Returns the current level state //----------------------------------------------------------------------------- LevelState_t IGameManager::GetLevelState() { return m_LevelState; } //----------------------------------------------------------------------------- // Start loading a level //----------------------------------------------------------------------------- void IGameManager::StartNewLevel() { m_bLevelShutdownRequested = true; m_bLevelStartRequested = true; } void IGameManager::ShutdownLevel() { m_bLevelShutdownRequested = true; }