Autosave completed but not tested.

This commit is contained in:
Kyzentun
2015-03-09 19:47:44 -06:00
parent 064aead73c
commit ddb1683bb7
12 changed files with 127 additions and 30 deletions
+1
View File
@@ -97,6 +97,7 @@ Create=Create New
Delete=Delete Existing Delete=Delete Existing
Edit=Edit Existing Edit=Edit Existing
Practice=Practice Practice=Practice
LoadAutosave=Load Autosave
[EditMenu] [EditMenu]
Blank=Blank Blank=Blank
+7
View File
@@ -31,6 +31,7 @@ static const char *EditMenuActionNames[] = {
"Delete", "Delete",
"Create", "Create",
"Practice", "Practice",
"LoadAutosave",
}; };
XToString( EditMenuAction ); XToString( EditMenuAction );
XToLocalizedString( EditMenuAction ); XToLocalizedString( EditMenuAction );
@@ -659,6 +660,12 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
m_StepsDisplaySource.SetVisible( !(bHideMeter || GetSelectedSteps()) ); m_StepsDisplaySource.SetVisible( !(bHideMeter || GetSelectedSteps()) );
m_Actions.clear(); m_Actions.clear();
// Stick autosave in the list first so that people will see it. -Kyz
Song* cur_song= GetSelectedSong();
if(cur_song != NULL && cur_song->HasAutosaveFile() && !cur_song->WasLoadedFromAutosave())
{
m_Actions.push_back(EditMenuAction_LoadAutosave);
}
if( GetSelectedSteps() ) if( GetSelectedSteps() )
{ {
switch( mode ) switch( mode )
+1
View File
@@ -42,6 +42,7 @@ enum EditMenuAction
EditMenuAction_Delete, /**< Remove the current step from the Song. */ EditMenuAction_Delete, /**< Remove the current step from the Song. */
EditMenuAction_Create, /**< Create a new step for the Song. */ EditMenuAction_Create, /**< Create a new step for the Song. */
EditMenuAction_Practice, /**< Practice the current step for the Song. */ EditMenuAction_Practice, /**< Practice the current step for the Song. */
EditMenuAction_LoadAutosave,
NUM_EditMenuAction, /**< The number of MenuActions available to choose from. */ NUM_EditMenuAction, /**< The number of MenuActions available to choose from. */
EditMenuAction_Invalid EditMenuAction_Invalid
}; };
+3 -3
View File
@@ -25,16 +25,16 @@ void NotesLoader::GetMainAndSubTitlesFromFullTitle( const RString &sFullTitle, R
sSubTitleOut = ""; sSubTitleOut = "";
}; };
bool NotesLoader::LoadFromDir( const RString &sPath, Song &out, set<RString> &BlacklistedImages ) bool NotesLoader::LoadFromDir( const RString &sPath, Song &out, set<RString> &BlacklistedImages, bool load_autosave )
{ {
vector<RString> list; vector<RString> list;
BlacklistedImages.clear(); BlacklistedImages.clear();
SSCLoader loaderSSC; SSCLoader loaderSSC;
loaderSSC.GetApplicableFiles( sPath, list ); loaderSSC.GetApplicableFiles( sPath, list, load_autosave );
if( !list.empty() ) if( !list.empty() )
{ {
if( !loaderSSC.LoadFromDir( sPath, out ) ) if( !loaderSSC.LoadFromDir( sPath, out, load_autosave ) )
return false; return false;
loaderSSC.TidyUpData( out, false ); loaderSSC.TidyUpData( out, false );
return true; return true;
+1 -1
View File
@@ -21,7 +21,7 @@ namespace NotesLoader
* @param out the Song in question. * @param out the Song in question.
* @param BlacklistedImages images to exclude (DWI files only for some reason). * @param BlacklistedImages images to exclude (DWI files only for some reason).
* @return its success or failure. */ * @return its success or failure. */
bool LoadFromDir( const RString &sPath, Song &out, set<RString> &BlacklistedImages ); bool LoadFromDir( const RString &sPath, Song &out, set<RString> &BlacklistedImages, bool load_autosave= false );
} }
#endif #endif
+9 -3
View File
@@ -23,10 +23,10 @@ RString SMLoader::GetSongTitle() const
return this->songTitle; return this->songTitle;
} }
bool SMLoader::LoadFromDir( const RString &sPath, Song &out ) bool SMLoader::LoadFromDir( const RString &sPath, Song &out, bool load_autosave )
{ {
vector<RString> aFileNames; vector<RString> aFileNames;
GetApplicableFiles( sPath, aFileNames ); GetApplicableFiles( sPath, aFileNames, load_autosave );
return LoadFromSimfile( sPath + aFileNames[0], out ); return LoadFromSimfile( sPath + aFileNames[0], out );
} }
@@ -1217,11 +1217,17 @@ bool SMLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath
return false; return false;
} }
void SMLoader::GetApplicableFiles( const RString &sPath, vector<RString> &out ) void SMLoader::GetApplicableFiles( const RString &sPath, vector<RString> &out, bool load_autosave )
{
if(load_autosave)
{ {
GetDirListing( sPath + RString("*.ats" ), out ); GetDirListing( sPath + RString("*.ats" ), out );
}
else
{
GetDirListing( sPath + RString("*" + this->GetFileExtension() ), out ); GetDirListing( sPath + RString("*" + this->GetFileExtension() ), out );
} }
}
void SMLoader::TidyUpData( Song &song, bool bFromCache ) void SMLoader::TidyUpData( Song &song, bool bFromCache )
{ {
+2 -2
View File
@@ -34,7 +34,7 @@ struct SMLoader
* @param out a reference to the Song that will retrieve the song information. * @param out a reference to the Song that will retrieve the song information.
* @return its success or failure. * @return its success or failure.
*/ */
virtual bool LoadFromDir( const RString &sPath, Song &out ); virtual bool LoadFromDir( const RString &sPath, Song &out, bool load_autosave= false );
/** /**
* @brief Perform some cleanup on the loaded song. * @brief Perform some cleanup on the loaded song.
* @param song a reference to the song that may need cleaning up. * @param song a reference to the song that may need cleaning up.
@@ -61,7 +61,7 @@ struct SMLoader
* @param sPath a const reference to the path on the hard drive to check. * @param sPath a const reference to the path on the hard drive to check.
* @param out a vector of files found in the path. * @param out a vector of files found in the path.
*/ */
virtual void GetApplicableFiles( const RString &sPath, vector<RString> &out ); virtual void GetApplicableFiles( const RString &sPath, vector<RString> &out, bool load_autosave= false );
virtual bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong=NULL ); virtual bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong=NULL );
virtual bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot, Song *givenSong=NULL ); virtual bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot, Song *givenSong=NULL );
virtual bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong=NULL ); virtual bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong=NULL );
+4
View File
@@ -724,6 +724,10 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
bHasOwnTiming = false; bHasOwnTiming = false;
pNewNotes->SetSMNoteData( sParams[1] ); pNewNotes->SetSMNoteData( sParams[1] );
pNewNotes->TidyUpData(); pNewNotes->TidyUpData();
// Unlike the song and timing filenames, the steps filenames do
// need to point to the autosave file if that's where they were
// loaded from, because that's where the actual steps data is.
// -Kyz
pNewNotes->SetFilename(sPath); pNewNotes->SetFilename(sPath);
out.AddSteps( pNewNotes ); out.AddSteps( pNewNotes );
} }
+1
View File
@@ -4187,6 +4187,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
return; return;
case ANSWER_NO: case ANSWER_NO:
// Don't save; just exit. // Don't save; just exit.
m_pSong->RemoveAutosave();
SCREENMAN->SendMessageToTopScreen( SM_DoExit ); SCREENMAN->SendMessageToTopScreen( SM_DoExit );
return; return;
case ANSWER_CANCEL: case ANSWER_CANCEL:
+13
View File
@@ -266,6 +266,18 @@ bool ScreenEditMenu::MenuStart( const InputEventPlus & )
ScreenPrompt::Prompt( SM_None, STEPS_WILL_BE_LOST.GetValue() + "\n\n" + CONTINUE_WITH_DELETE.GetValue(), ScreenPrompt::Prompt( SM_None, STEPS_WILL_BE_LOST.GetValue() + "\n\n" + CONTINUE_WITH_DELETE.GetValue(),
PROMPT_YES_NO, ANSWER_NO ); PROMPT_YES_NO, ANSWER_NO );
break; break;
case EditMenuAction_LoadAutosave:
if(pSong)
{
FOREACH_PlayerNumber(pn)
{
GAMESTATE->m_pCurSteps[pn].Set(NULL);
}
pSong->LoadAutosaveFile();
SONGMAN->Invalidate(pSong);
SCREENMAN->SendMessageToTopScreen( SM_RefreshSelector );
}
break;
case EditMenuAction_Create: case EditMenuAction_Create:
ASSERT( !pSteps ); ASSERT( !pSteps );
{ {
@@ -344,6 +356,7 @@ bool ScreenEditMenu::MenuStart( const InputEventPlus & )
} }
return true; return true;
case EditMenuAction_Delete: case EditMenuAction_Delete:
case EditMenuAction_LoadAutosave:
return true; return true;
default: default:
FAIL_M(ssprintf("Invalid edit menu action: %i", action)); FAIL_M(ssprintf("Invalid edit menu action: %i", action));
+72 -13
View File
@@ -83,6 +83,7 @@ Song::Song()
m_bHasMusic = false; m_bHasMusic = false;
m_bHasBanner = false; m_bHasBanner = false;
m_bHasBackground = false; m_bHasBackground = false;
m_loaded_from_autosave= false;
} }
Song::~Song() Song::~Song()
@@ -266,7 +267,7 @@ static set<RString> BlacklistedImages;
* HasMusic(), HasBanner() or GetHashForDirectory(). * HasMusic(), HasBanner() or GetHashForDirectory().
* If true, check the directory hash and reload the song from scratch if it's changed. * If true, check the directory hash and reload the song from scratch if it's changed.
*/ */
bool Song::LoadFromSongDir( RString sDir ) bool Song::LoadFromSongDir( RString sDir, bool load_autosave )
{ {
// LOG->Trace( "Song::LoadFromSongDir(%s)", sDir.c_str() ); // LOG->Trace( "Song::LoadFromSongDir(%s)", sDir.c_str() );
ASSERT_M( sDir != "", "Songs can't be loaded from an empty directory!" ); ASSERT_M( sDir != "", "Songs can't be loaded from an empty directory!" );
@@ -294,6 +295,8 @@ bool Song::LoadFromSongDir( RString sDir )
bUseCache = false; bUseCache = false;
if( !PREFSMAN->m_bFastLoad && GetHashForDirectory(m_sSongDir) != uCacheHash ) if( !PREFSMAN->m_bFastLoad && GetHashForDirectory(m_sSongDir) != uCacheHash )
bUseCache = false; // this cache is out of date bUseCache = false; // this cache is out of date
if(load_autosave)
{ bUseCache= false; }
if( bUseCache ) if( bUseCache )
{ {
@@ -317,7 +320,7 @@ bool Song::LoadFromSongDir( RString sDir )
// There was no entry in the cache for this song, or it was out of date. // There was no entry in the cache for this song, or it was out of date.
// Let's load it from a file, then write a cache entry. // Let's load it from a file, then write a cache entry.
if( !NotesLoader::LoadFromDir(sDir, *this, BlacklistedImages) ) if(!NotesLoader::LoadFromDir(sDir, *this, BlacklistedImages, load_autosave))
{ {
LOG->UserLog( "Song", sDir, "has no SSC, SM, SMA, DWI, BMS, or KSF files." ); LOG->UserLog( "Song", sDir, "has no SSC, SM, SMA, DWI, BMS, or KSF files." );
@@ -341,9 +344,14 @@ bool Song::LoadFromSongDir( RString sDir )
} }
TidyUpData(false, true); TidyUpData(false, true);
// Don't save a cache file if the autosave is being loaded, because the
// cache file would contain the autosave filename. -Kyz
if(!load_autosave)
{
// save a cache file so we don't have to parse it all over again next time // save a cache file so we don't have to parse it all over again next time
if(!SaveToCacheFile()) if(!SaveToCacheFile())
sCacheFilePath = RString(); { sCacheFilePath = RString(); }
}
} }
FOREACH( Steps*, m_vpSteps, s ) FOREACH( Steps*, m_vpSteps, s )
@@ -461,6 +469,43 @@ bool Song::ReloadFromSongDir( RString sDir )
return true; return true;
} }
bool Song::HasAutosaveFile()
{
if(m_sSongFileName.empty())
{
return false;
}
RString autosave_path= SetExtension(m_sSongFileName, "ats");
return FILEMAN->DoesFileExist(autosave_path);
}
bool Song::LoadAutosaveFile()
{
if(m_sSongFileName.empty())
{
return false;
}
// Save these strings because they need to be restored after the reset.
// The filenames need to point to the original instead of the autosave for
// things like load from disk to work. -Kyz
RString dir= GetSongDir();
RString song_timing_file= m_SongTiming.m_sFile;
RString song_file= m_sSongFileName;
// Reset needs to be used to remove all the steps and other things that
// will be loaded from the autosave. -Kyz
Reset();
if(LoadFromSongDir(dir, true))
{
m_loaded_from_autosave= true;
m_sSongFileName= song_file;
m_SongTiming.m_sFile= song_timing_file;
return true;
}
// Loading the autosave failed, reload the original. -Kyz
LoadFromSongDir(dir, false);
return false;
}
static void GetImageDirListing( RString sPath, vector<RString> &AddTo ) static void GetImageDirListing( RString sPath, vector<RString> &AddTo )
{ {
GetDirListing( sPath + ".png", AddTo, false, false ); GetDirListing( sPath + ".png", AddTo, false, false );
@@ -1001,12 +1046,13 @@ void Song::Save(bool autosave)
// Save the new files. These calls make backups on their own. // Save the new files. These calls make backups on their own.
if( !SaveToSSCFile(GetSongFilePath(), false, autosave) ) if( !SaveToSSCFile(GetSongFilePath(), false, autosave) )
return; return;
SaveToCacheFile(); // Skip saving the cache, sm, and .old files if we are autosaving. The
// Skip saving the sm and .old files if we are autosaving. -Kyz // cache file should not contain the autosave filename. -Kyz
if(autosave) if(autosave)
{ {
return; return;
} }
SaveToCacheFile();
SaveToSMFile(); SaveToSMFile();
//SaveToDWIFile(); //SaveToDWIFile();
@@ -1107,14 +1153,7 @@ bool Song::SaveToSSCFile( RString sPath, bool bSavingCache, bool autosave )
if( !NotesWriterSSC::Write(path, *this, vpStepsToSave, bSavingCache) ) if( !NotesWriterSSC::Write(path, *this, vpStepsToSave, bSavingCache) )
return false; return false;
// Remove the autosave file so that edit mode won't auto load it. -Kyz RemoveAutosave();
RString autosave_path= sPath;
SetExtension(autosave_path, "ats");
if(FILEMAN->DoesFileExist(autosave_path))
{
FILEMAN->Remove(autosave_path);
}
if( g_BackUpAllSongSaves.Get() ) if( g_BackUpAllSongSaves.Get() )
{ {
@@ -1169,6 +1208,26 @@ bool Song::SaveToDWIFile()
return NotesWriterDWI::Write( sPath, *this ); return NotesWriterDWI::Write( sPath, *this );
} }
void Song::RemoveAutosave()
{
RString autosave_path= SetExtension(m_sSongFileName, "ats");
if(FILEMAN->DoesFileExist(autosave_path))
{
// Change all the steps to point to the actual file, not the autosave
// file. -Kyz
RString extension= GetExtension(m_sSongFileName);
for(size_t i= 0; i < m_vpSteps.size(); ++i)
{
if(!m_vpSteps[i]->IsAutogen())
{
m_vpSteps[i]->SetFilename(
SetExtension(m_vpSteps[i]->GetFilename(), extension));
}
}
FILEMAN->Remove(autosave_path);
m_loaded_from_autosave= false;
}
}
void Song::AddAutoGenNotes() void Song::AddAutoGenNotes()
{ {
+7 -2
View File
@@ -87,10 +87,13 @@ public:
* *
* This assumes that there is no song present right now. * This assumes that there is no song present right now.
* @param sDir the song directory from which to load. */ * @param sDir the song directory from which to load. */
bool LoadFromSongDir( RString sDir ); bool LoadFromSongDir( RString sDir, bool load_autosave= false );
// This one takes the effort to reuse Steps pointers as best as it can // This one takes the effort to reuse Steps pointers as best as it can
bool ReloadFromSongDir( RString sDir ); bool ReloadFromSongDir( RString sDir );
bool HasAutosaveFile();
bool LoadAutosaveFile();
/** /**
* @brief Call this after loading a song to clean up invalid data. * @brief Call this after loading a song to clean up invalid data.
* @param fromCache was this data loaded from the cache file? * @param fromCache was this data loaded from the cache file?
@@ -133,8 +136,9 @@ public:
* @return its success or failure. */ * @return its success or failure. */
bool SaveToDWIFile(); bool SaveToDWIFile();
void RemoveAutosave();
bool WasLoadedFromAutosave() const bool WasLoadedFromAutosave() const
{ return GetExtension(m_sSongFileName) == "ats"; } { return m_loaded_from_autosave; }
const RString &GetSongFilePath() const; const RString &GetSongFilePath() const;
RString GetCacheFilePath() const; RString GetCacheFilePath() const;
@@ -450,6 +454,7 @@ public:
void PushSelf( lua_State *L ); void PushSelf( lua_State *L );
private: private:
bool m_loaded_from_autosave;
/** @brief the Steps that belong to this Song. */ /** @brief the Steps that belong to this Song. */
vector<Steps*> m_vpSteps; vector<Steps*> m_vpSteps;
/** @brief the Steps of a particular StepsType that belong to this Song. */ /** @brief the Steps of a particular StepsType that belong to this Song. */