diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 4fa86c1003..60b0d9b6be 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -832,7 +832,7 @@ void NoteField::DrawPrimitives() //LOG->Trace( "start = %f.1, end = %f.1", fFirstBeatToDraw-fSongBeat, fLastBeatToDraw-fSongBeat ); //LOG->Trace( "Drawing elements %d through %d", iFirstRowToDraw, iLastRowToDraw ); -#define IS_ON_SCREEN( fBeat ) IsOnScreen( fBeat, 0, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels ) +#define IS_ON_SCREEN( fBeat ) ( fFirstBeatToDraw <= (fBeat) && (fBeat) <= fLastBeatToDraw && IsOnScreen( fBeat, 0, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels ) ) // Draw board if( SHOW_BOARD ) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 4248085f67..f18c556056 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -932,7 +932,7 @@ void SMLoader::TidyUpData( Song &song, bool bFromCache ) bg.push_back( BackgroundChange(song.m_fLastBeat,song.m_sBackgroundFile) ); } while(0); } - song.TidyUpData(); + song.TidyUpData( bFromCache ); } /* diff --git a/src/Song.cpp b/src/Song.cpp index de09e5ffa3..1e737ef182 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -236,9 +236,7 @@ bool Song::LoadFromSongDir( RString sDir ) { // LOG->Trace( "Loading '%s' from cache file '%s'.", m_sSongDir.c_str(), GetCacheFilePath().c_str() ); bool bLoadedFromSSC = SSCLoader::LoadFromSSCFile( sCacheFilePath, *this, true ); - if( bLoadedFromSSC ) - SSCLoader::TidyUpData( *this, true ); - else + if( !bLoadedFromSSC ) { // load from .sm SMLoader::LoadFromSMFile( sCacheFilePath, *this, true ); @@ -390,7 +388,7 @@ void FixupPath( RString &path, const RString &sSongPath ) } // Songs in BlacklistImages will never be autodetected as song images. -void Song::TidyUpData() +void Song::TidyUpData( bool bFromCache ) { // We need to do this before calling any of HasMusic, HasHasCDTitle, etc. ASSERT_M( m_sSongDir.Left(3) != "../", m_sSongDir ); // meaningless @@ -481,7 +479,7 @@ void Song::TidyUpData() /* Generate these before we autogen notes, so the new notes can inherit * their source's values. */ - ReCalculateRadarValuesAndLastBeat(); + ReCalculateRadarValuesAndLastBeat( bFromCache ); Trim( m_sMainTitle ); Trim( m_sSubTitle ); @@ -791,8 +789,16 @@ void Song::TranslateTitles() title.SaveToStrings( m_sMainTitle, m_sSubTitle, m_sArtist, m_sMainTitleTranslit, m_sSubTitleTranslit, m_sArtistTranslit ); } -void Song::ReCalculateRadarValuesAndLastBeat() +void Song::ReCalculateRadarValuesAndLastBeat( bool bFromCache ) { + if( bFromCache && m_fFirstBeat >= 0 && m_fLastBeat > 0 ) + { + // this is loaded from cache, then we just have to calculate the radar values. + for( unsigned i=0; iCalculateRadarValues( m_fMusicLengthSeconds ); + return; + } + float fFirstBeat = FLT_MAX; // inf float fLastBeat = m_fSpecifiedLastBeat; // Make sure we're at least as long as the specified amount. diff --git a/src/Song.h b/src/Song.h index 0539cddff5..cbe6e5ddf4 100644 --- a/src/Song.h +++ b/src/Song.h @@ -97,13 +97,13 @@ public: bool ReloadFromSongDir( RString sDir ); /** @brief Call this after loading a song to clean up invalid data. */ - void TidyUpData(); + void TidyUpData( bool bFromCache = false ); /** * @brief Get the new radar values, and determine the last beat at the same time. * * This is called by TidyUpData, after saving the Song. */ - void ReCalculateRadarValuesAndLastBeat(); + void ReCalculateRadarValuesAndLastBeat( bool bFromCache = false ); /** * @brief Translate any titles that aren't in english. * diff --git a/src/Steps.cpp b/src/Steps.cpp index de2634e83c..c1a79064f5 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -31,7 +31,8 @@ Steps::Steps(): m_StepsType(StepsType_Invalid), m_sNoteDataCompressed(""), m_sFilename(""), m_bSavedToDisk(false), m_LoadedFromProfile(ProfileSlot_Invalid), m_iHash(0), m_sDescription(""), m_sChartStyle(""), - m_Difficulty(Difficulty_Invalid), m_iMeter(0), m_sCredit("") {} + m_Difficulty(Difficulty_Invalid), m_iMeter(0), m_sCredit(""), + m_bAreCachedRadarValuesJustLoaded(false) {} Steps::~Steps() { @@ -171,6 +172,12 @@ void Steps::CalculateRadarValues( float fMusicLengthSeconds ) if( parent != NULL ) return; + if( m_bAreCachedRadarValuesJustLoaded ) + { + m_bAreCachedRadarValuesJustLoaded = false; + return; + } + // Do write radar values, and leave it up to the reading app whether they want to trust // the cached values without recalculating them. /* @@ -422,6 +429,7 @@ void Steps::SetCachedRadarValues( const RadarValues v[NUM_PLAYERS] ) { DeAutogen(); copy( v, v + NUM_PLAYERS, m_CachedRadarValues ); + m_bAreCachedRadarValuesJustLoaded = true; } bool Steps::UsesSplitTiming() const diff --git a/src/Steps.h b/src/Steps.h index 1e107f7db4..8ba508b9d2 100644 --- a/src/Steps.h +++ b/src/Steps.h @@ -180,6 +180,7 @@ private: int m_iMeter; /** @brief The radar values used for each player. */ RadarValues m_CachedRadarValues[NUM_PLAYERS]; + bool m_bAreCachedRadarValuesJustLoaded; /** @brief The name of the person who created the Steps. */ RString m_sCredit; }; diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 0f70041bc8..1e57e455ac 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -1003,14 +1003,19 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const float TimingData::GetDisplayedBeat( float fBeat ) const { - unsigned index = GetScrollSegmentIndexAtBeat(fBeat); - const ScrollSegment &s = m_ScrollSegments[index]; - float fOutBeat = ( fBeat - s.GetBeat() ) * s.GetRatio(); - for( unsigned i = 0; i < index; i ++ ) + vector::const_iterator it = m_ScrollSegments.begin(), end = m_ScrollSegments.end(); + float fOutBeat = 0.0; + for( ; it != end; it++ ) { - const ScrollSegment &future = m_ScrollSegments[i+1]; - const ScrollSegment ¤t = m_ScrollSegments[i]; - fOutBeat += ( future.GetBeat() - current.GetBeat() ) * current.GetRatio(); + if( it+1 == end || fBeat <= (it+1)->GetBeat() ) + { + fOutBeat += ( fBeat - (it)->GetBeat() ) * (it)->GetRatio(); + break; + } + else + { + fOutBeat += ( (it+1)->GetBeat() - (it)->GetBeat() ) * (it)->GetRatio(); + } } return fOutBeat; }