source-engine-2018-hl2_src/app/legion/gamemanager.cpp

343 lines
8.4 KiB
C++
Raw Permalink Normal View History

2020-04-23 00:56:21 +08:00
//========= 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;
}