You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
8.4 KiB
342 lines
8.4 KiB
//========= 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 <windows.h> |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// 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; |
|
} |
|
|
|
|