Autosave completed but not tested.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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 )
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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 );
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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. */
|
||||||
|
|||||||
Reference in New Issue
Block a user