cache Course::GetCourseInfo results
This commit is contained in:
@@ -548,29 +548,42 @@ static vector<Song*> GetFilteredBestSongs( StepsType nt )
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This is called by many simple functions, like Course::GetTotalSeconds, and may
|
||||
* be called on all songs to sort. It can take time to execute, so we cache the
|
||||
* results. */
|
||||
void Course::GetCourseInfo( StepsType nt, vector<Course::Info> &ci, int Difficult ) const
|
||||
{
|
||||
vector<CourseEntry> entries = m_entries;
|
||||
const InfoParams params( nt, IsDifficult(Difficult) );
|
||||
InfoCache::const_iterator it = m_InfoCache.find( params );
|
||||
if( it != m_InfoCache.end() )
|
||||
{
|
||||
ci = it->second;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Different seed for each course, but the same for the whole round: */
|
||||
RandomGen rnd( GAMESTATE->m_iRoundSeed + GetHashForString(m_sName) );
|
||||
|
||||
vector<CourseEntry> tmp_entries;
|
||||
if( m_bRandomize )
|
||||
{
|
||||
/* Always randomize the same way per round. Otherwise, the displayed course
|
||||
* will change every time it's viewed, and the displayed order will have no
|
||||
* bearing on what you'll actually play. */
|
||||
random_shuffle( entries.begin(), entries.end(), rnd );
|
||||
tmp_entries = m_entries;
|
||||
random_shuffle( tmp_entries.begin(), tmp_entries.end(), rnd );
|
||||
}
|
||||
|
||||
const vector<CourseEntry> &entries = m_bRandomize? tmp_entries:m_entries;
|
||||
|
||||
/* This can take some time, so don't fill it out unless we need it. */
|
||||
bool bMostPlayedSet = false;
|
||||
vector<Song*> vSongsByMostPlayed;
|
||||
|
||||
vector<Song*> AllSongsShuffled = SONGMAN->GetAllSongs();
|
||||
random_shuffle( AllSongsShuffled.begin(), AllSongsShuffled.end(), rnd );
|
||||
int CurSong = 0; /* Current offset into AllSongsShuffled */
|
||||
bool bShuffledSet = false;
|
||||
vector<Song*> AllSongsShuffled;
|
||||
|
||||
int CurSong = 0; /* Current offset into AllSongsShuffled */
|
||||
ci.clear();
|
||||
|
||||
for( unsigned i=0; i<entries.size(); i++ )
|
||||
@@ -602,6 +615,13 @@ void Course::GetCourseInfo( StepsType nt, vector<Course::Info> &ci, int Difficul
|
||||
case COURSE_ENTRY_RANDOM:
|
||||
case COURSE_ENTRY_RANDOM_WITHIN_GROUP:
|
||||
{
|
||||
if( !bShuffledSet )
|
||||
{
|
||||
AllSongsShuffled = SONGMAN->GetAllSongs();
|
||||
random_shuffle( AllSongsShuffled.begin(), AllSongsShuffled.end(), rnd );
|
||||
bShuffledSet = true;
|
||||
}
|
||||
|
||||
// find a song with the notes we want
|
||||
for( unsigned j=0; j<AllSongsShuffled.size(); j++ )
|
||||
{
|
||||
@@ -695,6 +715,14 @@ void Course::GetCourseInfo( StepsType nt, vector<Course::Info> &ci, int Difficul
|
||||
cinfo.Difficult = IsDifficult(Difficult);
|
||||
ci.push_back( cinfo );
|
||||
}
|
||||
|
||||
/* Cache results. */
|
||||
m_InfoCache[params] = ci;
|
||||
}
|
||||
|
||||
void Course::ClearCache()
|
||||
{
|
||||
m_InfoCache.clear();
|
||||
}
|
||||
|
||||
RageColor Course::GetColor() const
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "PlayerNumber.h"
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "Attack.h"
|
||||
#include <map>
|
||||
|
||||
struct PlayerOptions;
|
||||
struct SongOptions;
|
||||
@@ -196,8 +197,16 @@ public:
|
||||
|
||||
void UpdateCourseStats();
|
||||
|
||||
/* Call per-screen, and if song or notes pointers change: */
|
||||
void ClearCache();
|
||||
|
||||
private:
|
||||
void GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut, int Difficult = -1 ) const;
|
||||
|
||||
typedef pair<StepsType,bool> InfoParams;
|
||||
typedef vector<Course::Info> InfoData;
|
||||
typedef map<InfoParams, InfoData> InfoCache;
|
||||
mutable InfoCache m_InfoCache;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -477,6 +477,10 @@ Screen* ScreenManager::MakeNewScreen( CString sClassName )
|
||||
* screens turn this off in their ctor if they handle timers themselves (gameplay, edit). */
|
||||
SOUND->HandleSongTimer( true );
|
||||
|
||||
/* Cleanup song data. This can free up a fair bit of memory, so do it before
|
||||
* creating the new screen, to lower peak memory usage slightly. */
|
||||
SONGMAN->Cleanup();
|
||||
|
||||
Screen *ret = Screen::Create( sClassName );
|
||||
|
||||
/* Loading probably took a little while. Let's reset stats. This prevents us
|
||||
@@ -485,9 +489,6 @@ Screen* ScreenManager::MakeNewScreen( CString sClassName )
|
||||
* apparent. */
|
||||
DISPLAY->ResetStats();
|
||||
|
||||
/* This is a convenient time to clean up our song cache. */
|
||||
SONGMAN->CompressSongs();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "NoteData.h"
|
||||
#include "RageSound.h"
|
||||
#include "RageException.h"
|
||||
#include "SongManager.h"
|
||||
#include "SongCacheIndex.h"
|
||||
#include "GameManager.h"
|
||||
#include "PrefsManager.h"
|
||||
@@ -100,6 +101,10 @@ void Song::Reset()
|
||||
|
||||
Song empty;
|
||||
*this = empty;
|
||||
|
||||
/* Courses cache Notes* pointers. On the off chance that this isn't the last
|
||||
* thing this screen does, clear that cache. */
|
||||
SONGMAN->Cleanup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -567,9 +567,10 @@ void SongManager::FreeCourses()
|
||||
|
||||
/* Called periodically to wipe out cached NoteData. This is called when we change
|
||||
* screens. */
|
||||
void SongManager::CompressSongs()
|
||||
void SongManager::Cleanup()
|
||||
{
|
||||
for( unsigned i=0; i<m_pSongs.size(); i++ )
|
||||
unsigned i;
|
||||
for( i=0; i<m_pSongs.size(); i++ )
|
||||
{
|
||||
Song* pSong = m_pSongs[i];
|
||||
for( unsigned n=0; n<pSong->m_apNotes.size(); n++ )
|
||||
@@ -578,6 +579,10 @@ void SongManager::CompressSongs()
|
||||
pNotes->Compress();
|
||||
}
|
||||
}
|
||||
|
||||
/* Erase cached course info. */
|
||||
for( i=0; i < m_pCourses.size(); i++ )
|
||||
m_pCourses[i]->ClearCache();
|
||||
}
|
||||
|
||||
void SongManager::GetAllCourses( vector<Course*> &AddTo, bool bIncludeAutogen )
|
||||
|
||||
@@ -34,7 +34,8 @@ public:
|
||||
|
||||
void InitSongsFromDisk( LoadingWindow *ld );
|
||||
void FreeSongs();
|
||||
void CompressSongs();
|
||||
void Cleanup();
|
||||
|
||||
void LoadGroupSymLinks( CString sDir, CString sGroupFolder );
|
||||
|
||||
void InitCoursesFromDisk( LoadingWindow *ld );
|
||||
|
||||
Reference in New Issue
Block a user