revert. Need a better approach.
This commit is contained in:
@@ -235,7 +235,7 @@ void SongManager::LoadStepManiaSongDir( RString sDir, LoadingWindow *ld )
|
||||
ld->Paint();
|
||||
}
|
||||
Song* pNewSong = new Song;
|
||||
if( !pNewSong->LoadFromSongDir( sSongDirName, false ) ) // don't ignore cache
|
||||
if( !pNewSong->LoadFromSongDir( sSongDirName ) )
|
||||
{
|
||||
/* The song failed to load. */
|
||||
delete pNewSong;
|
||||
@@ -277,7 +277,7 @@ void SongManager::LoadGroupSymLinks(RString sDir, RString sGroupFolder)
|
||||
RString sSymDestination = msdF.GetParam(0,1); // Should only be 1 vale¶m...period.
|
||||
|
||||
Song* pNewSong = new Song;
|
||||
if( !pNewSong->LoadFromSongDir( sSymDestination, false ) ) // don't ignore cache
|
||||
if( !pNewSong->LoadFromSongDir( sSymDestination ) )
|
||||
{
|
||||
delete pNewSong; // The song failed to load.
|
||||
}
|
||||
@@ -859,6 +859,169 @@ void SongManager::Cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush all Song*, Steps* and Course* caches. This is called on reload, and when
|
||||
* any of those are removed or changed. This doesn't touch GAMESTATE and StageStats
|
||||
* pointers, which are updated explicitly in Song::RevertFromDisk. */
|
||||
void SongManager::Invalidate( Song *pStaleSong )
|
||||
{
|
||||
//
|
||||
// Save list of all old Course and Trail pointers
|
||||
//
|
||||
map<Course*,CourseID> mapOldCourseToCourseID;
|
||||
typedef pair<TrailID,Course*> TrailIDAndCourse;
|
||||
map<Trail*,TrailIDAndCourse> mapOldTrailToTrailIDAndCourse;
|
||||
FOREACH_CONST( Course*, this->m_pCourses, pCourse )
|
||||
{
|
||||
CourseID id;
|
||||
id.FromCourse( *pCourse );
|
||||
mapOldCourseToCourseID[*pCourse] = id;
|
||||
vector<Trail *> Trails;
|
||||
(*pCourse)->GetAllCachedTrails( Trails );
|
||||
FOREACH_CONST( Trail*, Trails, pTrail )
|
||||
{
|
||||
TrailID id;
|
||||
id.FromTrail( *pTrail );
|
||||
mapOldTrailToTrailIDAndCourse[*pTrail] = TrailIDAndCourse(id, *pCourse);
|
||||
}
|
||||
}
|
||||
|
||||
// It's a real pain to selectively invalidate only those Courses with
|
||||
// dependencies on the stale Song. So, instead, just reload all Courses.
|
||||
// It doesn't take very long.
|
||||
FreeCourses();
|
||||
InitCoursesFromDisk( NULL );
|
||||
InitAutogenCourses();
|
||||
|
||||
// invalidate cache
|
||||
StepsID::ClearCache();
|
||||
|
||||
#define CONVERT_COURSE_POINTER( pCourse ) do { \
|
||||
CourseID id = mapOldCourseToCourseID[pCourse]; /* this will always succeed */ \
|
||||
pCourse = id.ToCourse(); \
|
||||
} while(false)
|
||||
|
||||
/* Ugly: We need the course pointer to restore a trail pointer, and both have
|
||||
* been invalidated. We need to go through our mapping, and update the course
|
||||
* pointers, so we can use that to update trail pointers. */
|
||||
{
|
||||
map<Trail*,TrailIDAndCourse>::iterator it;
|
||||
for( it = mapOldTrailToTrailIDAndCourse.begin(); it != mapOldTrailToTrailIDAndCourse.end(); ++it )
|
||||
{
|
||||
TrailIDAndCourse &tidc = it->second;
|
||||
CONVERT_COURSE_POINTER( tidc.second );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
CourseID id = mapOldCourseToCourseID[GAMESTATE->m_pCurCourse]; /* this will always succeed */
|
||||
GAMESTATE->m_pCurCourse.Set( id.ToCourse() );
|
||||
}
|
||||
CONVERT_COURSE_POINTER( GAMESTATE->m_pPreferredCourse );
|
||||
|
||||
#define CONVERT_TRAIL_POINTER( pTrail ) do { \
|
||||
if( pTrail != NULL ) { \
|
||||
map<Trail*,TrailIDAndCourse>::iterator it; \
|
||||
it = mapOldTrailToTrailIDAndCourse.find(pTrail); \
|
||||
ASSERT_M( it != mapOldTrailToTrailIDAndCourse.end(), ssprintf("%p", pTrail.Get()) ); \
|
||||
const TrailIDAndCourse &tidc = it->second; \
|
||||
const TrailID &id = tidc.first; \
|
||||
const Course *pCourse = tidc.second; \
|
||||
pTrail.Set( id.ToTrail( pCourse, true ) ); \
|
||||
} \
|
||||
} while(false)
|
||||
|
||||
FOREACH_PlayerNumber( pn )
|
||||
{
|
||||
CONVERT_TRAIL_POINTER( GAMESTATE->m_pCurTrail[pn] );
|
||||
}
|
||||
}
|
||||
|
||||
/* If bAllowNotesLoss is true, any global notes pointers which no longer exist
|
||||
* (or exist but couldn't be matched) will be set to NULL. This is used when
|
||||
* reverting out of the editor. If false, this is unexpected and will assert.
|
||||
* This is used when reverting out of gameplay, in which case we may have StageStats,
|
||||
* etc. which may cause hard-to-trace crashes down the line if we set them to NULL. */
|
||||
void CONVERT_STEPS_POINTER( Steps *&pSteps, const map<Steps*,StepsID> &mapOldStepsToStepsID, const Song *pSong, bool bAllowNotesLoss )
|
||||
{
|
||||
if( pSteps == NULL )
|
||||
return;
|
||||
|
||||
map<Steps*,StepsID>::const_iterator it = mapOldStepsToStepsID.find(pSteps);
|
||||
if( it != mapOldStepsToStepsID.end() )
|
||||
pSteps = it->second.ToSteps(pSong, bAllowNotesLoss);
|
||||
}
|
||||
void CONVERT_STEPS_POINTER( BroadcastOnChangePtr<Steps> &pSteps, const map<Steps*,StepsID> &mapOldStepsToStepsID, const Song *pSong, bool bAllowNotesLoss )
|
||||
{
|
||||
if( pSteps == NULL )
|
||||
return;
|
||||
|
||||
map<Steps*,StepsID>::const_iterator it = mapOldStepsToStepsID.find(pSteps);
|
||||
if( it != mapOldStepsToStepsID.end() )
|
||||
pSteps.Set( it->second.ToSteps(pSong, bAllowNotesLoss) );
|
||||
}
|
||||
void SongManager::RevertFromDisk( Song *pSong, bool bAllowNotesLoss )
|
||||
{
|
||||
/* Reverting from disk is brittle, and touches a lot of tricky and rarely-
|
||||
* used code paths. If it's ever used during a game, log it. */
|
||||
LOG->MapLog( "RevertFromDisk", "Reverted \"%s\" from disk", pSong->GetTranslitMainTitle().c_str() );
|
||||
|
||||
// Ugly: When we re-load the song, the Steps* will change.
|
||||
// Fix GAMESTATE->m_CurSteps, STATSMAN->m_CurStageStats, STATSMAN->m_vPlayedStageStats[] after reloading.
|
||||
/* XXX: This is very brittle. However, we must know about all globals uses of Steps*,
|
||||
* so we can check to make sure we didn't lose any steps which are referenced ... */
|
||||
|
||||
|
||||
//
|
||||
// Save list of all old Steps pointers for the song
|
||||
//
|
||||
map<Steps*,StepsID> mapOldStepsToStepsID;
|
||||
FOREACH_CONST( Steps*, pSong->GetAllSteps(), pSteps )
|
||||
{
|
||||
StepsID id;
|
||||
id.FromSteps( *pSteps );
|
||||
mapOldStepsToStepsID[*pSteps] = id;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Reload the song
|
||||
//
|
||||
const RString dir = pSong->GetSongDir();
|
||||
FILEMAN->FlushDirCache( dir );
|
||||
|
||||
/* Erase existing data and reload. */
|
||||
pSong->Reset();
|
||||
const bool OldVal = PREFSMAN->m_bFastLoad;
|
||||
PREFSMAN->m_bFastLoad.Set( false );
|
||||
pSong->LoadFromSongDir( dir );
|
||||
/* XXX: reload edits? */
|
||||
PREFSMAN->m_bFastLoad.Set( OldVal );
|
||||
|
||||
|
||||
/* Courses cache Steps pointers. On the off chance that this isn't the last
|
||||
* thing this screen does, clear that cache. */
|
||||
/* TODO: Don't make Song depend on SongManager. This is breaking
|
||||
* encapsulation and placing confusing limitation on what can be done in
|
||||
* SONGMAN->Invalidate(). -Chris */
|
||||
this->Invalidate( pSong );
|
||||
StepsID::ClearCache();
|
||||
|
||||
|
||||
FOREACH_PlayerNumber( p )
|
||||
{
|
||||
CONVERT_STEPS_POINTER( GAMESTATE->m_pCurSteps[p], mapOldStepsToStepsID, pSong, bAllowNotesLoss );
|
||||
|
||||
FOREACH( Steps*, STATSMAN->m_CurStageStats.m_player[p].vpPlayedSteps, pSteps )
|
||||
CONVERT_STEPS_POINTER( *pSteps, mapOldStepsToStepsID, pSong, bAllowNotesLoss );
|
||||
|
||||
FOREACH( StageStats, STATSMAN->m_vPlayedStageStats, ss )
|
||||
FOREACH( Steps*, ss->m_player[p].vpPlayedSteps, pSteps )
|
||||
CONVERT_STEPS_POINTER( *pSteps, mapOldStepsToStepsID, pSong, bAllowNotesLoss );
|
||||
}
|
||||
|
||||
CONVERT_STEPS_POINTER( GAMESTATE->m_pEditSourceSteps, mapOldStepsToStepsID, pSong, bAllowNotesLoss );
|
||||
}
|
||||
|
||||
void SongManager::RegenerateNonFixedCourses()
|
||||
{
|
||||
for( unsigned i=0; i < m_pCourses.size(); i++ )
|
||||
@@ -981,7 +1144,7 @@ bool SongManager::GetExtraStageInfoFromCourse( bool bExtra2, RString sPreferredG
|
||||
}
|
||||
|
||||
pSongOut = pTrail->m_vEntries[0].pSong;
|
||||
pStepsOut = pTrail->m_vEntries[0].GetSteps();
|
||||
pStepsOut = pTrail->m_vEntries[0].pSteps;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user