Edit loading overhaul: Load edits from song folders; Allow a songfolder-style hierarchy in profile edit folders; Make the #SONG tag optional if we can infer the intended song from the directory hierarchy.

This commit is contained in:
Ben "root" Anderson
2013-11-14 13:29:00 -06:00
parent 5124186c42
commit a16a42cb02
7 changed files with 119 additions and 28 deletions
+15 -9
View File
@@ -829,6 +829,10 @@ bool SMLoader::LoadNoteDataFromSimfile( const RString &path, Steps &out )
RString stepsType = sParams[1];
RString description = sParams[2];
RString difficulty = sParams[3];
// HACK?: If this is a .edit fudge the edit difficulty
if(path.Right(5).CompareNoCase(".edit") == 0) difficulty = "edit";
Trim(stepsType);
Trim(description);
Trim(difficulty);
@@ -1108,7 +1112,7 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache
return true;
}
bool SMLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong )
bool SMLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong /* =NULL */ )
{
LOG->Trace( "SMLoader::LoadEditFromFile(%s)", sEditFilePath.c_str() );
@@ -1126,19 +1130,19 @@ bool SMLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool b
return false;
}
return LoadEditFromMsd( msd, sEditFilePath, slot, bAddStepsToSong );
return LoadEditFromMsd( msd, sEditFilePath, slot, bAddStepsToSong, givenSong );
}
bool SMLoader::LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot )
bool SMLoader::LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot, Song *givenSong )
{
MsdFile msd;
msd.ReadFromString( sBuffer, true ); // unescape
return LoadEditFromMsd( msd, sEditFilePath, slot, true );
return LoadEditFromMsd( msd, sEditFilePath, slot, true, givenSong );
}
bool SMLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong )
bool SMLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong /* =NULL */ )
{
Song* pSong = NULL;
Song* pSong = givenSong;
for( unsigned i=0; i<msd.GetNumValues(); i++ )
{
@@ -1152,8 +1156,10 @@ bool SMLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath
{
if( pSong )
{
LOG->UserLog( "Edit file", sEditFilePath, "has more than one #SONG tag." );
return false;
/* LOG->UserLog( "Edit file", sEditFilePath, "has more than one #SONG tag." );
return false; */
// May have been given the song from outside the file. Not worth checking for.
continue;
}
RString sSongFullTitle = sParams[1];
@@ -1178,7 +1184,7 @@ bool SMLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath
{
if( pSong == NULL )
{
LOG->UserLog( "Edit file", sEditFilePath, "doesn't have a #SONG tag preceeding the first #NOTES tag." );
LOG->UserLog( "Edit file", sEditFilePath, "doesn't have a #SONG tag preceeding the first #NOTES tag, and is not in a valid song-specific folder." );
return false;
}
+3 -3
View File
@@ -62,9 +62,9 @@ struct SMLoader
* @param out a vector of files found in the path.
*/
virtual void GetApplicableFiles( const RString &sPath, vector<RString> &out );
virtual bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
virtual bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot );
virtual bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
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 LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong=NULL );
virtual bool LoadFromBGChangesString(BackgroundChange &change,
const RString &sBGChangeExpression );
+9 -7
View File
@@ -874,7 +874,7 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
return true;
}
bool SSCLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong )
bool SSCLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong /* =NULL */ )
{
LOG->Trace( "SSCLoader::LoadEditFromFile(%s)", sEditFilePath.c_str() );
@@ -896,15 +896,16 @@ bool SSCLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool
return false;
}
return LoadEditFromMsd( msd, sEditFilePath, slot, bAddStepsToSong );
return LoadEditFromMsd( msd, sEditFilePath, slot, bAddStepsToSong, givenSong );
}
bool SSCLoader::LoadEditFromMsd(const MsdFile &msd,
const RString &sEditFilePath,
ProfileSlot slot,
bool bAddStepsToSong )
bool bAddStepsToSong,
Song *givenSong /* =NULL */ )
{
Song* pSong = NULL;
Song* pSong = givenSong;
Steps* pNewNotes = NULL;
bool bSSCFormat = false;
bool bHasOwnTiming = false;
@@ -927,8 +928,9 @@ bool SSCLoader::LoadEditFromMsd(const MsdFile &msd,
{
if( pSong )
{
LOG->UserLog( "Edit file", sEditFilePath, "has more than one #SONG tag." );
return false;
/* LOG->UserLog( "Edit file", sEditFilePath, "has more than one #SONG tag." );
return false; */
continue;
}
RString sSongFullTitle = sParams[1];
@@ -1086,7 +1088,7 @@ bool SSCLoader::LoadEditFromMsd(const MsdFile &msd,
{
LOG->UserLog("Edit file",
sEditFilePath,
"doesn't have a #SONG tag preceeding the first #NOTES tag." );
"doesn't have a #SONG tag preceeding the first #NOTES tag, and is not in a valid song-specific folder." );
return false;
}
+2 -2
View File
@@ -56,7 +56,7 @@ struct SSCLoader : public SMLoader
* @param bAddStepsToSong a flag to determine if we add the edit steps to the song file.
* @return its success or failure.
*/
bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong=NULL );
/**
* @brief Attempt to parse the edit file in question.
* @param msd the edit file itself.
@@ -65,7 +65,7 @@ struct SSCLoader : public SMLoader
* @param bAddStepsToSong a flag to determine if we add the edit steps to the song file.
* @return its success or failure.
*/
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong, Song *givenSong=NULL );
/**
* @brief Retrieve the specific NoteData from the file.
+18
View File
@@ -349,6 +349,24 @@ bool Song::LoadFromSongDir( RString sDir )
if( PREFSMAN->m_BackgroundCache == BGCACHE_LOW_RES_PRELOAD && m_bHasBackground )
BACKGROUNDCACHE->LoadBackground( GetBackgroundPath() );
*/
// Load any .edit files in the song folder.
// Doing this BEFORE setting up AutoGen just in case.
vector<RString> vs;
GetDirListing( sDir + "*.edit", vs, false, false);
// XXX: I'm sure there's a StepMania way of doing this, but familiar with this codebase I am not.
for(unsigned int i = 0; i < vs.size(); ++i) {
// Try SSCLoader
SSCLoader ldSSC;
if( ldSSC.LoadEditFromFile(sDir + vs[i], ProfileSlot_Invalid, true, this) != true )
{
// No dice? Try SMLoader then. If SMLoader fails too, well whatever.
// We don't have to do anything to fail gracefully.
SMLoader ldSM;
ldSM.LoadEditFromFile(sDir + vs[i], ProfileSlot_Invalid, true, this);
}
}
// Note: If vs.empty() then this loop is skipped entirely (vs.size() == 0)
// Add AutoGen pointers. (These aren't cached.)
AddAutoGenNotes();
+61 -7
View File
@@ -1713,26 +1713,80 @@ void SongManager::LoadStepEditsFromProfileDir( const RString &sProfileDir, Profi
{
// Load all edit steps
RString sDir = sProfileDir + EDIT_STEPS_SUBDIR;
vector<RString> vsFiles;
GetDirListing( sDir+"*.edit", vsFiles, false, true );
SSCLoader loaderSSC;
SMLoader loaderSM;
int iNumEditsLoaded = GetNumEditsLoadedFromProfile( slot );
int size = min( (int) vsFiles.size(), MAX_EDIT_STEPS_PER_PROFILE - iNumEditsLoaded );
// Pass 1: Flat folder (old style)
vector<RString> vsFiles;
int size = min( (int) vsFiles.size(), MAX_EDIT_STEPS_PER_PROFILE - iNumEditsLoaded );
GetDirListing( sDir+"*.edit", vsFiles, false, true );
// XXX: If some edits are invalid and they're close to the edit limit, this may erroneously skip some edits, and won't warn.
for( int i=0; i<size; i++ )
{
RString fn = vsFiles[i];
SSCLoader loaderSSC;
bool bLoadedFromSSC = loaderSSC.LoadEditFromFile( fn, slot, true );
// If we don't load the edit from a .ssc-style .edit, then we should
// also try the .sm-style edit file. -aj
if( !bLoadedFromSSC )
{
SMLoader loaderSM;
loaderSM.LoadEditFromFile( fn, slot, true );
}
}
if( vsFiles.size() > MAX_EDIT_STEPS_PER_PROFILE - iNumEditsLoaded )
{
LOG->Warn("Profile %s has too many edits; some have been skipped.", ProfileSlotToString( slot ).c_str() );
return;
}
// Some .edit files may have been invalid, so re-query instead of just += size.
iNumEditsLoaded = GetNumEditsLoadedFromProfile( slot );
// Pass 2: Group and song folders with #SONG inferred from folder (optional new style)
vector<RString> vsGroups;
GetDirListing( sDir+"*", vsGroups, true, false );
// XXX: Same as above, edits may be skipped in error in some cases
for( int i=0; i<vsGroups.size(); i++ )
{
RString sGroupDir = vsGroups[i]+"/";
vector<RString> vsSongs;
GetDirListing(sDir+sGroupDir+"*", vsSongs, true, false );
for( int j=0; j<vsSongs.size(); j++ )
{
vector<RString> vsEdits;
RString sSongDir = sGroupDir+vsSongs[j]+"/";
// XXX There doesn't appear to be a songdir const?
Song *given = GetSongFromDir( "/Songs/"+sSongDir );
// NOTE: We don't have to check the return value of GetSongFromDir here,
// because if it fails, it returns NULL, which is then passed to NotesLoader*.LoadEditFromFile(),
// which will interpret that as "we couldn't infer the song from the path",
// which is what we want in that case anyway.
GetDirListing(sDir+sSongDir+"/*.edit", vsEdits, false, true );
size = min( (int) vsEdits.size(), MAX_EDIT_STEPS_PER_PROFILE - iNumEditsLoaded );
for( int k=0; k<size; k++ )
{
RString fn = vsEdits[k];
bool bLoadedFromSSC = loaderSSC.LoadEditFromFile( fn, slot, true, given );
// And try again with SM
if( !bLoadedFromSSC )
loaderSM.LoadEditFromFile( fn, slot, true, given );
}
if( vsEdits.size() > MAX_EDIT_STEPS_PER_PROFILE - iNumEditsLoaded )
{
LOG->Warn("Profile %s has too many edits; some have been skipped.", ProfileSlotToString( slot ).c_str() );
return;
}
// Some .edit files may have been invalid, so re-query instead of just += size.
iNumEditsLoaded = GetNumEditsLoadedFromProfile( slot );
}
}
}
void SongManager::LoadCourseEditsFromProfileDir( const RString &sProfileDir, ProfileSlot slot )
+11
View File
@@ -152,6 +152,17 @@ bool Steps::GetNoteDataFromSimfile()
{
return BMSLoader::LoadNoteDataFromSimfile(stepFile, *this);
}
else if (extension == "edit")
{
// Try SSC, then fallback to SM.
SSCLoader ldSSC;
if(ldSSC.LoadNoteDataFromSimfile(stepFile, *this) != true)
{
SMLoader ldSM;
return ldSM.LoadNoteDataFromSimfile(stepFile, *this);
}
else return true;
}
return false;
}