implement ConcurrentlyPrepareScreen and IsConcurrentlyLoading
This commit is contained in:
@@ -31,9 +31,11 @@
|
||||
#include "Screen.h"
|
||||
#include "Foreach.h"
|
||||
#include "ActorUtil.h"
|
||||
#include "GameLoop.h"
|
||||
|
||||
ScreenManager* SCREENMAN = NULL; // global and accessable from anywhere in our program
|
||||
|
||||
static Preference<bool> g_bConcurrentLoading( "ConcurrentLoading", false );
|
||||
|
||||
// Screen registration
|
||||
static map<CString,CreateScreenFn> *g_pmapRegistrees = NULL;
|
||||
@@ -56,6 +58,7 @@ ScreenManager::ScreenManager()
|
||||
|
||||
m_bZeroNextUpdate = false;
|
||||
m_PopTopScreen = SM_Invalid;
|
||||
m_OnDonePreparingScreen = SM_Invalid;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,6 +118,8 @@ bool ScreenManager::IsStackedScreen( const Screen *pScreen ) const
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool g_bIsConcurrentlyLoading = false;
|
||||
|
||||
void ScreenManager::Update( float fDeltaTime )
|
||||
{
|
||||
//
|
||||
@@ -197,12 +202,41 @@ void ScreenManager::Update( float fDeltaTime )
|
||||
if( bFirstUpdate )
|
||||
SOUND->Flush();
|
||||
|
||||
if( m_sDelayedScreen.size() != 0 )
|
||||
/* If we're currently inside a background screen load, and m_sDelayedScreen
|
||||
* is set, then the screen called SetNewScreen before we finished preparing.
|
||||
* Postpone it until we're finished loading. */
|
||||
if( !IsConcurrentlyLoading() && m_sDelayedScreen.size() != 0 )
|
||||
{
|
||||
LoadDelayedScreen();
|
||||
}
|
||||
|
||||
if( !m_sDelayedConcurrentPrepare.empty() )
|
||||
{
|
||||
/* Don't call BackgroundPrepareScreen() from within another background load. */
|
||||
ASSERT( !IsConcurrentlyLoading() );
|
||||
|
||||
/* Push rendering into a thread, and prepare the screen. */
|
||||
g_bIsConcurrentlyLoading = true;
|
||||
StartConcurrentRendering();
|
||||
PrepareScreen( m_sDelayedConcurrentPrepare );
|
||||
FinishConcurrentRendering();
|
||||
g_bIsConcurrentlyLoading = false;
|
||||
|
||||
LOG->Trace( "Concurrent prepare of %s finished", m_sDelayedConcurrentPrepare.c_str() );
|
||||
|
||||
/* We're done. Send the message. The screen is allowed to start
|
||||
* another concurrent prepare from this message. */
|
||||
ScreenMessage SM = m_OnDonePreparingScreen;
|
||||
m_sDelayedConcurrentPrepare = "";
|
||||
m_OnDonePreparingScreen = SM_None;
|
||||
SendMessageToTopScreen( SM );
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenManager::IsConcurrentlyLoading() const
|
||||
{
|
||||
return g_bIsConcurrentlyLoading;
|
||||
}
|
||||
|
||||
void ScreenManager::Draw()
|
||||
{
|
||||
@@ -347,6 +381,21 @@ void ScreenManager::PrepareScreen( const CString &sScreenName )
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenManager::ConcurrentlyPrepareScreen( const CString &sScreenName, ScreenMessage SM )
|
||||
{
|
||||
ASSERT_M( m_sDelayedConcurrentPrepare == "", m_sDelayedConcurrentPrepare );
|
||||
|
||||
if( !g_bConcurrentLoading || !DISPLAY->SupportsThreadedRendering() )
|
||||
return false;
|
||||
|
||||
LOG->Trace( "ConcurrentlyPrepareScreen(%s)", sScreenName.c_str() );
|
||||
ASSERT( !IsConcurrentlyLoading() );
|
||||
|
||||
m_sDelayedConcurrentPrepare = sScreenName;
|
||||
m_OnDonePreparingScreen = SM;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScreenManager::DeletePreparedScreens()
|
||||
{
|
||||
FOREACH( Screen*, m_vPreparedScreens, s )
|
||||
@@ -559,7 +608,11 @@ void ScreenManager::RefreshCreditsMessages()
|
||||
|
||||
void ScreenManager::ZeroNextUpdate()
|
||||
{
|
||||
m_bZeroNextUpdate = true;
|
||||
if( !IsConcurrentlyLoading() )
|
||||
{
|
||||
LOG->Trace("ScreenManager::ZeroNextUpdate");
|
||||
m_bZeroNextUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Always play these sounds, even if we're in a silent attract loop. */
|
||||
|
||||
@@ -39,6 +39,8 @@ public:
|
||||
void SetNewScreen( const CString &sName );
|
||||
void AddNewScreenToTop( const CString &sName );
|
||||
void PrepareScreen( const CString &sScreenName ); // creates and caches screen so that the next call to SetNewScreen for the prep'd screen will be very quick.
|
||||
bool ConcurrentlyPrepareScreen( const CString &sScreenName, ScreenMessage send_when_done = SM_None );
|
||||
bool IsConcurrentlyLoading() const;
|
||||
void DeletePreparedScreens();
|
||||
void SetFromNewScreen( Screen *pNewScreen );
|
||||
void PopTopScreen( ScreenMessage SM );
|
||||
@@ -82,9 +84,10 @@ private:
|
||||
vector<Screen*> m_vPreparedScreens;
|
||||
vector<Actor*> m_vPreparedBackgrounds;
|
||||
|
||||
// Screen loads and removals are delayed until the next update, so the
|
||||
// screen being removed isn't on the stack.
|
||||
// Screen loads, removals, and concurrent prepares are delayed until the next update.
|
||||
CString m_sDelayedScreen;
|
||||
CString m_sDelayedConcurrentPrepare;
|
||||
ScreenMessage m_OnDonePreparingScreen;
|
||||
ScreenMessage m_PopTopScreen;
|
||||
|
||||
// Set this to true anywhere we create of delete objects. These
|
||||
|
||||
Reference in New Issue
Block a user