fix crash on exiting editor
clean up invalidation of Song and Courses
This commit is contained in:
@@ -258,6 +258,9 @@ void Course::LoadFromCRSFile( CString sPath )
|
|||||||
|
|
||||||
void Course::RevertFromDisk()
|
void Course::RevertFromDisk()
|
||||||
{
|
{
|
||||||
|
// trying to catch invalid an Course
|
||||||
|
ASSERT( !m_sPath.empty() );
|
||||||
|
|
||||||
LoadFromCRSFile( m_sPath );
|
LoadFromCRSFile( m_sPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +271,7 @@ void Course::Init()
|
|||||||
m_bRandomize = false;
|
m_bRandomize = false;
|
||||||
m_iLives = -1;
|
m_iLives = -1;
|
||||||
m_bSortByMeter = false;
|
m_bSortByMeter = false;
|
||||||
|
m_entries.clear();
|
||||||
FOREACH_Difficulty(dc)
|
FOREACH_Difficulty(dc)
|
||||||
m_iCustomMeter[dc] = -1;
|
m_iCustomMeter[dc] = -1;
|
||||||
m_entries.clear();
|
m_entries.clear();
|
||||||
|
|||||||
@@ -1337,9 +1337,11 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
|
|||||||
case SM_GoToNextScreen:
|
case SM_GoToNextScreen:
|
||||||
// Reload song from disk to discard changes.
|
// Reload song from disk to discard changes.
|
||||||
SONGMAN->RevertFromDisk( GAMESTATE->m_pCurSong, true );
|
SONGMAN->RevertFromDisk( GAMESTATE->m_pCurSong, true );
|
||||||
|
|
||||||
/* We might do something with m_pSteps (eg. UpdateTextInfo) before we end up
|
/* We might do something with m_pSteps (eg. UpdateTextInfo) before we end up
|
||||||
* in ScreenEditMenu, and m_pSteps might be invalid due to RevertFromDisk. */
|
* in ScreenEditMenu, and m_pSteps might be invalid due to RevertFromDisk. */
|
||||||
m_pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
|
m_pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
|
||||||
|
|
||||||
SCREENMAN->SetNewScreen( "ScreenEditMenu" );
|
SCREENMAN->SetNewScreen( "ScreenEditMenu" );
|
||||||
break;
|
break;
|
||||||
case SM_BackFromMainMenu:
|
case SM_BackFromMainMenu:
|
||||||
|
|||||||
+9
-11
@@ -8,7 +8,6 @@
|
|||||||
#include "RageSoundReader_FileReader.h"
|
#include "RageSoundReader_FileReader.h"
|
||||||
#include "RageSurface_Load.h"
|
#include "RageSurface_Load.h"
|
||||||
#include "RageException.h"
|
#include "RageException.h"
|
||||||
#include "SongManager.h"
|
|
||||||
#include "SongCacheIndex.h"
|
#include "SongCacheIndex.h"
|
||||||
#include "GameManager.h"
|
#include "GameManager.h"
|
||||||
#include "PrefsManager.h"
|
#include "PrefsManager.h"
|
||||||
@@ -78,29 +77,28 @@ Song::Song()
|
|||||||
|
|
||||||
Song::~Song()
|
Song::~Song()
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<m_vpSteps.size(); i++ )
|
FOREACH( Steps*, m_vpSteps, s )
|
||||||
SAFE_DELETE( m_vpSteps[i] );
|
SAFE_DELETE( *s );
|
||||||
|
|
||||||
m_vpSteps.clear();
|
m_vpSteps.clear();
|
||||||
|
|
||||||
/* We deleted some Steps*; clear stuff that used it. */
|
// It's the responsibility of the owner of this Song to make sure
|
||||||
/* TODO: Don't make Song depend on SongManager. This is breaking
|
// that all pointers to this Song and its Steps are invalidated.
|
||||||
* encapsulation and placing confusing limitation on what can be done in
|
|
||||||
* SONGMAN->Invalidate(). -Chris */
|
|
||||||
SONGMAN->Invalidate( this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset to an empty song. */
|
/* Reset to an empty song. */
|
||||||
void Song::Reset()
|
void Song::Reset()
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<m_vpSteps.size(); i++ )
|
FOREACH( Steps*, m_vpSteps, s )
|
||||||
SAFE_DELETE( m_vpSteps[i] );
|
SAFE_DELETE( *s );
|
||||||
m_vpSteps.clear();
|
m_vpSteps.clear();
|
||||||
FOREACH_StepsType( st )
|
FOREACH_StepsType( st )
|
||||||
m_vpStepsByType[st].clear();
|
m_vpStepsByType[st].clear();
|
||||||
|
|
||||||
Song empty;
|
Song empty;
|
||||||
*this = empty;
|
*this = empty;
|
||||||
|
|
||||||
|
// It's the responsibility of the owner of this Song to make sure
|
||||||
|
// that all pointers to this Song and its Steps are invalidated.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -671,10 +671,14 @@ void SongManager::Cleanup()
|
|||||||
* pointers, which are updated explicitly in Song::RevertFromDisk. */
|
* pointers, which are updated explicitly in Song::RevertFromDisk. */
|
||||||
void SongManager::Invalidate( Song *pStaleSong )
|
void SongManager::Invalidate( Song *pStaleSong )
|
||||||
{
|
{
|
||||||
/* Erase cached course info. */
|
// It's a real pain to selectively invalidate only those Courses with
|
||||||
FOREACH_CONST( Course*, m_pCourses, c )
|
// dependencies on the stale Song. So, instead, just reload all Courses.
|
||||||
(*c)->Invalidate( pStaleSong );
|
// It doesn't take very long.
|
||||||
|
FreeCourses();
|
||||||
|
InitCoursesFromDisk( NULL );
|
||||||
|
InitAutogenCourses();
|
||||||
|
|
||||||
|
// invalidate cache
|
||||||
StepsID::Invalidate( pStaleSong );
|
StepsID::Invalidate( pStaleSong );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ void Steps::Decompress() const
|
|||||||
StepsID ID;
|
StepsID ID;
|
||||||
ID.FromSteps( this );
|
ID.FromSteps( this );
|
||||||
|
|
||||||
Steps *pSteps = ID.ToSteps( &s, true );
|
Steps *pSteps = ID.ToSteps( &s, true, false ); // don't use cache
|
||||||
if( pSteps == NULL )
|
if( pSteps == NULL )
|
||||||
{
|
{
|
||||||
LOG->Warn( "Couldn't find %s in \"%s\"", ID.ToString().c_str(), m_sFilename.c_str() );
|
LOG->Warn( "Couldn't find %s in \"%s\"", ID.ToString().c_str(), m_sFilename.c_str() );
|
||||||
|
|||||||
@@ -142,14 +142,17 @@ void StepsID::FromSteps( const Steps *p )
|
|||||||
* to have access to Song::m_LoadedFromProfile. */
|
* to have access to Song::m_LoadedFromProfile. */
|
||||||
|
|
||||||
static map<StepsID,Steps *> g_StepsIDCache;
|
static map<StepsID,Steps *> g_StepsIDCache;
|
||||||
Steps *StepsID::ToSteps( const Song *p, bool bAllowNull ) const
|
Steps *StepsID::ToSteps( const Song *p, bool bAllowNull, bool bUseCache ) const
|
||||||
{
|
{
|
||||||
if( st == STEPS_TYPE_INVALID || dc == DIFFICULTY_INVALID )
|
if( st == STEPS_TYPE_INVALID || dc == DIFFICULTY_INVALID )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if( bUseCache )
|
||||||
|
{
|
||||||
map<StepsID,Steps *>::iterator it = g_StepsIDCache.find( *this );
|
map<StepsID,Steps *>::iterator it = g_StepsIDCache.find( *this );
|
||||||
if( it != g_StepsIDCache.end() )
|
if( it != g_StepsIDCache.end() )
|
||||||
return it->second;
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
vector<Steps*> vNotes;
|
vector<Steps*> vNotes;
|
||||||
if( dc == DIFFICULTY_EDIT )
|
if( dc == DIFFICULTY_EDIT )
|
||||||
@@ -163,7 +166,9 @@ Steps *StepsID::ToSteps( const Song *p, bool bAllowNull ) const
|
|||||||
else if( !bAllowNull )
|
else if( !bAllowNull )
|
||||||
RageException::Throw( "%i, %i, \"%s\"", st, dc, sDescription.c_str() );
|
RageException::Throw( "%i, %i, \"%s\"", st, dc, sDescription.c_str() );
|
||||||
|
|
||||||
|
if( bUseCache )
|
||||||
g_StepsIDCache[*this] = ret;
|
g_StepsIDCache[*this] = ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public:
|
|||||||
StepsID() { Unset(); }
|
StepsID() { Unset(); }
|
||||||
void Unset() { FromSteps(NULL); }
|
void Unset() { FromSteps(NULL); }
|
||||||
void FromSteps( const Steps *p );
|
void FromSteps( const Steps *p );
|
||||||
Steps *ToSteps( const Song *p, bool bAllowNull ) const;
|
Steps *ToSteps( const Song *p, bool bAllowNull, bool bUseCache = true ) const;
|
||||||
bool operator<( const StepsID &rhs ) const;
|
bool operator<( const StepsID &rhs ) const;
|
||||||
bool MatchesStepsType( StepsType s ) const { return st == s; }
|
bool MatchesStepsType( StepsType s ) const { return st == s; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user