allow multiple, simultaneous prepared screens

This commit is contained in:
Chris Danford
2004-12-09 09:41:06 +00:00
parent 7085d480ec
commit 12d556c759
12 changed files with 114 additions and 54 deletions
+16
View File
@@ -45,6 +45,8 @@ void GameCommand::Init()
m_SortOrder = SORT_INVALID; m_SortOrder = SORT_INVALID;
m_iUnlockIndex = -1; m_iUnlockIndex = -1;
m_sSoundPath = ""; m_sSoundPath = "";
m_vsScreensToPrepare.clear();
m_bDeletePreparedScreens = false;
m_bClearBookkeepingData = false; m_bClearBookkeepingData = false;
m_bClearMachineStats = false; m_bClearMachineStats = false;
@@ -246,6 +248,16 @@ void GameCommand::Load( int iIndex, const Commands& cmds )
m_sSoundPath = sValue; m_sSoundPath = sValue;
} }
else if( sName == "preparescreen" )
{
m_vsScreensToPrepare.push_back( sValue );
}
else if( sName == "deletepreparedscreens" )
{
m_bDeletePreparedScreens = true;
}
else if( sName == "clearbookkeepingdata" ) else if( sName == "clearbookkeepingdata" )
{ {
m_bClearBookkeepingData = true; m_bClearBookkeepingData = true;
@@ -548,6 +560,10 @@ void GameCommand::Apply( PlayerNumber pn ) const
UNLOCKMAN->UnlockCode( m_iUnlockIndex ); UNLOCKMAN->UnlockCode( m_iUnlockIndex );
if( m_sSoundPath != "" ) if( m_sSoundPath != "" )
SOUND->PlayOnce( THEME->GetPathToS( m_sSoundPath ) ); SOUND->PlayOnce( THEME->GetPathToS( m_sSoundPath ) );
FOREACH_CONST( CString, m_vsScreensToPrepare, s )
SCREENMAN->PrepareScreen( *s );
if( m_bDeletePreparedScreens )
SCREENMAN->DeletePreparedScreens();
if( m_bClearBookkeepingData ) if( m_bClearBookkeepingData )
{ {
+2
View File
@@ -51,6 +51,8 @@ struct GameCommand // used in SelectMode
SortOrder m_SortOrder; SortOrder m_SortOrder;
int m_iUnlockIndex; // -1 for no unlock int m_iUnlockIndex; // -1 for no unlock
CString m_sSoundPath; // "" for no sound CString m_sSoundPath; // "" for no sound
vector<CString> m_vsScreensToPrepare;
bool m_bDeletePreparedScreens;
bool m_bClearBookkeepingData; bool m_bClearBookkeepingData;
bool m_bClearMachineStats; bool m_bClearMachineStats;
+1
View File
@@ -156,6 +156,7 @@ void Screen::HandleScreenMessage( const ScreenMessage SM )
SCREENMAN->SetNewScreen( NEXT_SCREEN ); SCREENMAN->SetNewScreen( NEXT_SCREEN );
break; break;
case SM_GoToPrevScreen: case SM_GoToPrevScreen:
SCREENMAN->DeletePreparedScreens();
SCREENMAN->SetNewScreen( PREV_SCREEN ); SCREENMAN->SetNewScreen( PREV_SCREEN );
break; break;
} }
+6
View File
@@ -2295,6 +2295,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
GAMESTATE->CancelStage(); GAMESTATE->CancelStage();
SCREENMAN->DeletePreparedScreens();
SCREENMAN->SetNewScreen( PREV_SCREEN ); SCREENMAN->SetNewScreen( PREV_SCREEN );
break; break;
@@ -2364,10 +2365,15 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
if( PREFSMAN->m_bEventMode ) if( PREFSMAN->m_bEventMode )
{ {
if(EVAL_ON_FAIL) // go to the eval screen if we fail if(EVAL_ON_FAIL) // go to the eval screen if we fail
{
SCREENMAN->SetNewScreen( "ScreenEvaluationStage" ); SCREENMAN->SetNewScreen( "ScreenEvaluationStage" );
}
else // the theme says just fail and go back to the song select for event mode else // the theme says just fail and go back to the song select for event mode
{
SCREENMAN->DeletePreparedScreens();
SCREENMAN->SetNewScreen( PREV_SCREEN ); SCREENMAN->SetNewScreen( PREV_SCREEN );
} }
}
else if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() ) else if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() )
SCREENMAN->SetNewScreen( "ScreenEvaluationStage" ); SCREENMAN->SetNewScreen( "ScreenEvaluationStage" );
else else
+55 -36
View File
@@ -30,6 +30,7 @@
#include "ThemeManager.h" #include "ThemeManager.h"
#include "ScreenSystemLayer.h" #include "ScreenSystemLayer.h"
#include "BGAnimation.h" #include "BGAnimation.h"
#include "Foreach.h"
ScreenManager* SCREENMAN = NULL; // global and accessable from anywhere in our program ScreenManager* SCREENMAN = NULL; // global and accessable from anywhere in our program
@@ -54,15 +55,14 @@ ScreenManager::ScreenManager()
m_pSharedBGA = new BGAnimation; m_pSharedBGA = new BGAnimation;
m_SystemLayer = NULL; m_SystemLayer = NULL;
m_MessageSendOnPop = SM_None;
/* By the time this is constructed, THEME has already been set up and set to /* By the time this is constructed, THEME has already been set up and set to
* the current theme. Call ThemeChanged(), to handle the starting theme * the current theme. Call ThemeChanged(), to handle the starting theme
* and set up m_SystemLayer. */ * and set up m_SystemLayer. */
ASSERT( THEME ); ASSERT( THEME );
ASSERT( !THEME->GetCurThemeName().empty() ); ASSERT( !THEME->GetCurThemeName().empty() );
this->ThemeChanged(); this->ThemeChanged();
m_ScreenBuffered = NULL;
m_MessageSendOnPop = SM_None;
} }
@@ -74,9 +74,9 @@ ScreenManager::~ScreenManager()
SAFE_DELETE( m_pSharedBGA ); SAFE_DELETE( m_pSharedBGA );
for( unsigned i=0; i<m_ScreenStack.size(); i++ ) for( unsigned i=0; i<m_ScreenStack.size(); i++ )
delete m_ScreenStack[i]; SAFE_DELETE( m_ScreenStack[i] );
delete m_ScreenBuffered; DeletePreparedScreens();
delete m_SystemLayer; SAFE_DELETE( m_SystemLayer );
} }
/* This is called when we start up, and when the theme changes or is reloaded. */ /* This is called when we start up, and when the theme changes or is reloaded. */
@@ -99,14 +99,13 @@ void ScreenManager::ThemeChanged()
void ScreenManager::EmptyDeleteQueue() void ScreenManager::EmptyDeleteQueue()
{ {
if(!m_ScreensToDelete.size()) if(!m_vScreensToDelete.size())
return; return;
// delete all ScreensToDelete for( unsigned i=0; i<m_vScreensToDelete.size(); i++ )
for( unsigned i=0; i<m_ScreensToDelete.size(); i++ ) SAFE_DELETE( m_vScreensToDelete[i] );
SAFE_DELETE( m_ScreensToDelete[i] );
m_ScreensToDelete.clear(); m_vScreensToDelete.clear();
/* Now that we've actually deleted a screen, it makes sense to clear out /* Now that we've actually deleted a screen, it makes sense to clear out
* cached textures. */ * cached textures. */
@@ -249,23 +248,26 @@ Screen* ScreenManager::MakeNewScreen( const CString &sScreenName )
return ret; return ret;
} }
void ScreenManager::PrepNewScreen( const CString &sScreenName ) void ScreenManager::PrepareScreen( const CString &sScreenName )
{ {
ASSERT(m_ScreenBuffered == NULL); // Delete previously prepared versions of the screen.
m_ScreenBuffered = MakeNewScreen(sScreenName); FOREACH( Screen*, m_vPreparedScreens, s )
{
if( (*s)->m_sName == sScreenName )
{
SAFE_DELETE( *s );
break;
}
}
m_vPreparedScreens.push_back( MakeNewScreen(sScreenName) );
} }
void ScreenManager::LoadPreppedScreen() void ScreenManager::DeletePreparedScreens()
{ {
ASSERT( m_ScreenBuffered != NULL); FOREACH( Screen*, m_vPreparedScreens, s )
SetFromNewScreen( m_ScreenBuffered, false ); SAFE_DELETE( *s );
m_vPreparedScreens.clear();
m_ScreenBuffered = NULL;
}
void ScreenManager::DeletePreppedScreen()
{
SAFE_DELETE( m_ScreenBuffered );
TEXTUREMAN->DeleteCachedTextures(); TEXTUREMAN->DeleteCachedTextures();
} }
@@ -279,7 +281,7 @@ void ScreenManager::ClearScreenStack()
m_ScreenStack.back()->HandleScreenMessage( SM_LoseFocus ); m_ScreenStack.back()->HandleScreenMessage( SM_LoseFocus );
// move current screen(s) to ScreenToDelete // move current screen(s) to ScreenToDelete
m_ScreensToDelete.insert(m_ScreensToDelete.end(), m_ScreenStack.begin(), m_ScreenStack.end()); m_vScreensToDelete.insert(m_vScreensToDelete.end(), m_ScreenStack.begin(), m_ScreenStack.end());
m_ScreenStack.clear(); m_ScreenStack.clear();
} }
@@ -299,7 +301,7 @@ void ScreenManager::SetFromNewScreen( Screen *pNewScreen, bool Stack )
void ScreenManager::SetNewScreen( const CString &sScreenName ) void ScreenManager::SetNewScreen( const CString &sScreenName )
{ {
m_DelayedScreen = sScreenName; m_sDelayedScreen = sScreenName;
/* If we're not delaying screen loads, load it now. Otherwise, we'll load /* If we're not delaying screen loads, load it now. Otherwise, we'll load
* it on the next iteration. Only delay if we already have a screen * it on the next iteration. Only delay if we already have a screen
@@ -311,21 +313,38 @@ void ScreenManager::SetNewScreen( const CString &sScreenName )
void ScreenManager::LoadDelayedScreen() void ScreenManager::LoadDelayedScreen()
{ {
retry: retry:
CString sScreenName = m_DelayedScreen; CString sScreenName = m_sDelayedScreen;
m_DelayedScreen = ""; m_sDelayedScreen = "";
/* If we prepped a screen but didn't use it, nuke it. */
SAFE_DELETE( m_ScreenBuffered );
Screen* pOldTopScreen = m_ScreenStack.empty() ? NULL : m_ScreenStack.back(); Screen* pOldTopScreen = m_ScreenStack.empty() ? NULL : m_ScreenStack.back();
// It makes sense that ScreenManager should allocate memory for a new screen since it //
// deletes it later on. This also convention will reduce includes because screens won't // Search prepped screens to see if we already have this screen available.
// have to include each other's headers of other screens. // If not prepped, then make it.
Screen* pNewScreen = MakeNewScreen(sScreenName); //
Screen* pNewScreen = NULL;
FOREACH( Screen*, m_vPreparedScreens, s )
{
if( (*s)->m_sName == sScreenName )
{
pNewScreen = *s;
m_vPreparedScreens.erase( s );
break;
}
}
if( pNewScreen == NULL )
pNewScreen = MakeNewScreen(sScreenName);
// Load shared BGAnimation
CString sNewBGA = THEME->GetPathToB(sScreenName+" background");
if( m_sLastLoadedBackground != sNewBGA )
{
m_pSharedBGA->LoadFromAniDir( sNewBGA );
m_sLastLoadedBackground = sNewBGA;
}
if( pOldTopScreen!=NULL && m_ScreenStack.back()!=pOldTopScreen ) if( pOldTopScreen!=NULL && m_ScreenStack.back()!=pOldTopScreen )
{ {
@@ -425,7 +444,7 @@ void ScreenManager::PopTopScreen( ScreenMessage SM )
Screen* pScreenToPop = m_ScreenStack.back(); // top menu Screen* pScreenToPop = m_ScreenStack.back(); // top menu
pScreenToPop->HandleScreenMessage( SM_LoseFocus ); pScreenToPop->HandleScreenMessage( SM_LoseFocus );
m_ScreenStack.erase(m_ScreenStack.end()-1, m_ScreenStack.end()); m_ScreenStack.erase(m_ScreenStack.end()-1, m_ScreenStack.end());
m_ScreensToDelete.push_back( pScreenToPop ); m_vScreensToDelete.push_back( pScreenToPop );
/* Post to the new top. This must be done now; otherwise, we'll have a single /* Post to the new top. This must be done now; otherwise, we'll have a single
* frame between popping and these messages, which can result in a frame where eg. * frame between popping and these messages, which can result in a frame where eg.
+10 -10
View File
@@ -35,9 +35,8 @@ public:
void Draw(); void Draw();
void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ); void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI );
void PrepNewScreen( 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.
void LoadPreppedScreen(); void DeletePreparedScreens();
void DeletePreppedScreen();
void SetNewScreen( const CString &sName ); void SetNewScreen( const CString &sName );
void AddNewScreenToTop( const CString &sName, ScreenMessage messageSendOnPop ); void AddNewScreenToTop( const CString &sName, ScreenMessage messageSendOnPop );
@@ -55,10 +54,6 @@ public:
void RefreshCreditsMessages(); void RefreshCreditsMessages();
void ThemeChanged(); void ThemeChanged();
void EmptyDeleteQueue();
void LoadDelayedScreen();
Screen *GetTopScreen(); Screen *GetTopScreen();
public: public:
@@ -69,15 +64,20 @@ public:
void PlaySharedBackgroundOffCommand(); void PlaySharedBackgroundOffCommand();
private: private:
vector<Screen*> m_ScreenStack; // bottommost to topmost vector<Screen*> m_ScreenStack; // bottommost to topmost
ScreenMessage m_MessageSendOnPop;
vector<Screen*> m_ScreensToDelete;
Screen *m_ScreenBuffered;
ScreenSystemLayer *m_SystemLayer; ScreenSystemLayer *m_SystemLayer;
CString m_sLastLoadedBackground;
CString m_sDelayedScreen;
ScreenMessage m_MessageSendOnPop;
vector<Screen*> m_vPreparedScreens;
vector<Screen*> m_vScreensToDelete;
Screen* MakeNewScreen( const CString &sName ); Screen* MakeNewScreen( const CString &sName );
void SetFromNewScreen( Screen *pNewScreen, bool Stack ); void SetFromNewScreen( Screen *pNewScreen, bool Stack );
CString m_DelayedScreen; CString m_DelayedScreen;
void ClearScreenStack(); void ClearScreenStack();
void EmptyDeleteQueue();
void LoadDelayedScreen();
// Keep these sounds always loaded, because they could be // Keep these sounds always loaded, because they could be
// played at any time. We want to eliminate SOUND->PlayOnce // played at any time. We want to eliminate SOUND->PlayOnce
+5
View File
@@ -577,10 +577,15 @@ void ScreenOptionsMaster::GoToPrevScreen()
{ {
/* XXX: A better way to handle this would be to check if we're a pushed screen. */ /* XXX: A better way to handle this would be to check if we're a pushed screen. */
if( GAMESTATE->m_bEditing ) if( GAMESTATE->m_bEditing )
{
SCREENMAN->PopTopScreen(); SCREENMAN->PopTopScreen();
// XXX: handle different destinations based on play mode? // XXX: handle different destinations based on play mode?
}
else else
{
SCREENMAN->DeletePreparedScreens();
SCREENMAN->SetNewScreen( PREV_SCREEN ); // (GAMESTATE->m_PlayMode) ); SCREENMAN->SetNewScreen( PREV_SCREEN ); // (GAMESTATE->m_PlayMode) );
}
} }
void ScreenOptionsMaster::RefreshIcons() void ScreenOptionsMaster::RefreshIcons()
+5
View File
@@ -60,9 +60,14 @@ ScreenPlayerOptions::ScreenPlayerOptions( CString sClassName ) :
void ScreenPlayerOptions::GoToPrevScreen() void ScreenPlayerOptions::GoToPrevScreen()
{ {
if( GAMESTATE->m_bEditing ) if( GAMESTATE->m_bEditing )
{
SCREENMAN->PopTopScreen(); SCREENMAN->PopTopScreen();
}
else else
{
SCREENMAN->DeletePreparedScreens();
SCREENMAN->SetNewScreen( PREV_SCREEN ); SCREENMAN->SetNewScreen( PREV_SCREEN );
}
} }
void ScreenPlayerOptions::GoToNextScreen() void ScreenPlayerOptions::GoToNextScreen()
+2
View File
@@ -1045,7 +1045,9 @@ void ScreenSelectMusic::HandleScreenMessage( const ScreenMessage SM )
} }
return; return;
case SM_GoToPrevScreen: case SM_GoToPrevScreen:
SCREENMAN->DeletePreparedScreens();
SCREENMAN->SetNewScreen( PREV_SCREEN ); SCREENMAN->SetNewScreen( PREV_SCREEN );
/* We may have stray SM_SongChanged messages from the music wheel. We can't /* We may have stray SM_SongChanged messages from the music wheel. We can't
* handle them anymore, since the title menu (and attract screens) reset * handle them anymore, since the title menu (and attract screens) reset
* the game state, so just discard them. */ * the game state, so just discard them. */
+5
View File
@@ -32,9 +32,14 @@ ScreenSongOptions::ScreenSongOptions( CString sClassName ) :
void ScreenSongOptions::GoToPrevScreen() void ScreenSongOptions::GoToPrevScreen()
{ {
if( GAMESTATE->m_bEditing ) if( GAMESTATE->m_bEditing )
{
SCREENMAN->PopTopScreen( SM_None ); SCREENMAN->PopTopScreen( SM_None );
}
else else
{
SCREENMAN->DeletePreparedScreens();
SCREENMAN->SetNewScreen( PREV_SCREEN ); SCREENMAN->SetNewScreen( PREV_SCREEN );
}
} }
void ScreenSongOptions::GoToNextScreen() void ScreenSongOptions::GoToNextScreen()
+3 -5
View File
@@ -105,7 +105,7 @@ void ScreenStage::HandleScreenMessage( const ScreenMessage SM )
* we can. */ * we can. */
this->PostScreenMessage( SM_BeginFadingOut, MINIMUM_DELAY ); this->PostScreenMessage( SM_BeginFadingOut, MINIMUM_DELAY );
SCREENMAN->PrepNewScreen( NEXT_SCREEN ); SCREENMAN->PrepareScreen( NEXT_SCREEN );
break; break;
case SM_BeginFadingOut: case SM_BeginFadingOut:
@@ -116,16 +116,14 @@ void ScreenStage::HandleScreenMessage( const ScreenMessage SM )
OFF_COMMAND( m_Artist ); OFF_COMMAND( m_Artist );
OFF_COMMAND( m_Banner ); OFF_COMMAND( m_Banner );
SCREENMAN->PlaySharedBackgroundOffCommand(); SCREENMAN->PlaySharedBackgroundOffCommand();
this->PostScreenMessage( SM_GoToNextScreen, this->GetTweenTimeLeft() ); this->PostScreenMessage( SM_GoToNextScreen, this->GetTweenTimeLeft() );
break; break;
case SM_GoToNextScreen: case SM_GoToNextScreen:
SCREENMAN->LoadPreppedScreen(); /* use prepped */ SCREENMAN->SetNewScreen( NEXT_SCREEN );
break; break;
case SM_GoToPrevScreen: case SM_GoToPrevScreen:
SCREENMAN->DeletePreppedScreen(); SCREENMAN->DeletePreparedScreens();
SCREENMAN->SetNewScreen( PREV_SCREEN ); SCREENMAN->SetNewScreen( PREV_SCREEN );
break; break;
} }
+1
View File
@@ -1289,6 +1289,7 @@ bool HandleGlobalInputs( DeviceInput DeviceI, InputEventType type, GameInput Gam
* (to prevent quitting without storing changes). */ * (to prevent quitting without storing changes). */
if( !GAMESTATE->m_bIsOnSystemMenu ) if( !GAMESTATE->m_bIsOnSystemMenu )
{ {
SCREENMAN->DeletePreparedScreens();
SCREENMAN->SystemMessage( "OPERATOR" ); SCREENMAN->SystemMessage( "OPERATOR" );
GAMESTATE->Reset(); GAMESTATE->Reset();
SCREENMAN->SetNewScreen( "ScreenOptionsMenu" ); SCREENMAN->SetNewScreen( "ScreenOptionsMenu" );