diff --git a/stepmania/src/PrefsManager.cpp b/stepmania/src/PrefsManager.cpp index d66040e590..229911938b 100644 --- a/stepmania/src/PrefsManager.cpp +++ b/stepmania/src/PrefsManager.cpp @@ -74,6 +74,7 @@ PrefsManager::PrefsManager() m_bArcadeOptionsNavigation = false; m_bSoloSingle = false; m_bDelayedTextureDelete = true; + m_bDelayedScreenLoad = false; m_MusicWheelUsesSections = ALWAYS; m_iMusicWheelSwitchSpeed = 10; m_bEasterEggs = true; @@ -166,6 +167,7 @@ void PrefsManager::ReadGlobalPrefsFromDisk( bool bSwitchToLastPlayedGame ) ini.GetValueB( "Options", "ArcadeOptionsNavigation", m_bArcadeOptionsNavigation ); ini.GetValue ( "Options", "DWIPath", m_DWIPath ); ini.GetValueB( "Options", "DelayedTextureDelete", m_bDelayedTextureDelete ); + ini.GetValueB( "Options", "DelayedScreenLoad", m_bDelayedScreenLoad ); ini.GetValueI( "Options", "MusicWheelUsesSections", (int&)m_MusicWheelUsesSections ); ini.GetValueI( "Options", "MusicWheelSwitchSpeed", m_iMusicWheelSwitchSpeed ); ini.GetValue ( "Options", "SoundDrivers", m_sSoundDrivers ); @@ -249,6 +251,7 @@ void PrefsManager::SaveGlobalPrefsToDisk() ini.SetValueB( "Options", "ArcadeOptionsNavigation", m_bArcadeOptionsNavigation ); ini.SetValue ( "Options", "DWIPath", m_DWIPath ); ini.SetValueB( "Options", "DelayedTextureDelete", m_bDelayedTextureDelete ); + ini.SetValueB( "Options", "DelayedScreenLoad", m_bDelayedScreenLoad ); ini.SetValueI( "Options", "MusicWheelUsesSections", m_MusicWheelUsesSections ); ini.SetValueI( "Options", "MusicWheelSwitchSpeed", m_iMusicWheelSwitchSpeed ); ini.SetValueB( "Options", "EasterEggs", m_bEasterEggs ); diff --git a/stepmania/src/PrefsManager.h b/stepmania/src/PrefsManager.h index 10932e2299..bc227b2de0 100644 --- a/stepmania/src/PrefsManager.h +++ b/stepmania/src/PrefsManager.h @@ -34,6 +34,7 @@ public: bool m_bHiddenSongs; bool m_bVsync; bool m_bDelayedTextureDelete; + bool m_bDelayedScreenLoad; bool m_bIgnoreJoyAxes; bool m_bOnlyDedicatedMenuButtons; diff --git a/stepmania/src/ScreenManager.cpp b/stepmania/src/ScreenManager.cpp index 68da5e2ad8..f8381b6b90 100644 --- a/stepmania/src/ScreenManager.cpp +++ b/stepmania/src/ScreenManager.cpp @@ -315,6 +315,7 @@ void ScreenManager::EmptyDeleteQueue() * change state!). Only do this when we have to, so we don't double * the number of updates. */ static bool g_TopNeedsNeedsNullUpdate = false; +static bool g_SkipRendering = false; void ScreenManager::Update( float fDeltaTime ) { @@ -331,25 +332,54 @@ void ScreenManager::Update( float fDeltaTime ) * If we cap that large update delta from the screen load, the update * to load the new screen will come after 4 seconds plus the load time. * - * So, let's just drop the first update for every screen. + * So, let's just zero the first update for every screen. + * + * XXX: If a new Screen is set during this Update, that new screen is Drawn + * before it's first Update. */ - ASSERT( !m_ScreenStack.empty() ); // Why play the game if there is nothing showing? - Screen* pScreen = m_ScreenStack[m_ScreenStack.size()-1]; - if( pScreen->IsFirstUpdate() ) - pScreen->Update( 0 ); - else - pScreen->Update( fDeltaTime ); + ASSERT( !m_ScreenStack.empty() || m_DelayedScreen != "" ); // Why play the game if there is nothing showing? + + if( !m_ScreenStack.empty() ) + { + Screen* pScreen = m_ScreenStack[m_ScreenStack.size()-1]; + if( pScreen->IsFirstUpdate() ) + pScreen->Update( 0 ); + else + pScreen->Update( fDeltaTime ); + } - // TODO: If a new Screen is set during this Update, that new screen is Drawn - // before it's first Update. m_SystemLayer->Update( fDeltaTime ); EmptyDeleteQueue(); + + if(m_DelayedScreen.size() != 0) + { + LOG->Trace("loading"); + /* We have a screen to display. Delete the current screens and load it. */ + m_ScreensToDelete.insert(m_ScreensToDelete.end(), m_ScreenStack.begin(), m_ScreenStack.end()); + m_ScreenStack.clear(); + EmptyDeleteQueue(); + LoadDelayedScreen(); + + /* Ack. We can't Update(0), since we want to skip the *next* update + * (which is the one that will have all this load time in it). We + * can't draw it until we've updated it. Let's simply not render + * the next frame, so we'll come around quickly and handle it correctly. */ + g_SkipRendering = true; + } } void ScreenManager::Draw() { + DISPLAY->Clear(); + + if(g_SkipRendering) + { + /* Leave the frame there (if any). */ + g_SkipRendering = false; + return; + } if(g_TopNeedsNeedsNullUpdate) { g_TopNeedsNeedsNullUpdate = false; @@ -362,6 +392,8 @@ void ScreenManager::Draw() for( unsigned i=0; iDraw(); m_SystemLayer->Draw(); + + DISPLAY->Flip(); } @@ -422,18 +454,33 @@ void ScreenManager::SetNewScreen( Screen *pNewScreen ) // move current screen(s) to ScreenToDelete m_ScreensToDelete.insert(m_ScreensToDelete.end(), m_ScreenStack.begin(), m_ScreenStack.end()); - m_ScreenStack.clear(); + m_ScreenStack.push_back( pNewScreen ); } void ScreenManager::SetNewScreen( CString sClassName ) { + m_DelayedScreen = sClassName; + + /* 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 + * loaded; otherwise, there's no reason to delay. */ + if(!PREFSMAN->m_bDelayedScreenLoad) // || m_ScreenStack.empty() ) + LoadDelayedScreen(); +} + +void ScreenManager::LoadDelayedScreen() +{ +retry: + CString sClassName = m_DelayedScreen; + m_DelayedScreen = ""; + /* If we prepped a screen but didn't use it, nuke it. */ SAFE_DELETE( m_ScreenBuffered ); RageTimer t; - + Screen* pOldTopScreen = m_ScreenStack.empty() ? NULL : m_ScreenStack.back(); // It makes sense that ScreenManager should allocate memory for a new screen since it @@ -451,6 +498,13 @@ void ScreenManager::SetNewScreen( CString sClassName ) return; } + if( PREFSMAN->m_bDelayedScreenLoad && m_DelayedScreen != "" ) + { + /* Same deal: the ctor called SetNewScreen again. Delete the screen + * we just made, but don't delay again. */ + SAFE_DELETE( pNewScreen ); + goto retry; + } SetNewScreen( pNewScreen ); /* If this is a system menu, don't let the operator key touch it! diff --git a/stepmania/src/ScreenManager.h b/stepmania/src/ScreenManager.h index 24b1f6d19f..112633b9fb 100644 --- a/stepmania/src/ScreenManager.h +++ b/stepmania/src/ScreenManager.h @@ -53,6 +53,8 @@ public: void EmptyDeleteQueue(); + void LoadDelayedScreen(); + private: vector m_ScreenStack; // bottommost to topmost vector m_ScreensToDelete; @@ -61,6 +63,7 @@ private: Screen* MakeNewScreen( CString sClassName ); void SetNewScreen( Screen *pNewScreen ); + CString m_DelayedScreen; }; diff --git a/stepmania/src/StepMania.cpp b/stepmania/src/StepMania.cpp index 193524e06c..e577708b0c 100644 --- a/stepmania/src/StepMania.cpp +++ b/stepmania/src/StepMania.cpp @@ -574,9 +574,7 @@ static void GameLoop() /* * Render */ - DISPLAY->Clear(); SCREENMAN->Draw(); - DISPLAY->Flip(); if(g_bHasFocus) SDL_Delay( 1 ); // give some time to other processes and threads