343 lines
8.4 KiB
C++
343 lines
8.4 KiB
C++
|
//========= 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;
|
||
|
}
|
||
|
|