diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 74c2f514e9..0907970741 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -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; iUserLog( "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; } diff --git a/src/NotesLoaderSM.h b/src/NotesLoaderSM.h index 2cca76804d..358515ec51 100644 --- a/src/NotesLoaderSM.h +++ b/src/NotesLoaderSM.h @@ -62,9 +62,9 @@ struct SMLoader * @param out a vector of files found in the path. */ virtual void GetApplicableFiles( const RString &sPath, vector &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 ); diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 400ec8a525..9f4be80a2c 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -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; } diff --git a/src/NotesLoaderSSC.h b/src/NotesLoaderSSC.h index b344ac6451..9de3383061 100644 --- a/src/NotesLoaderSSC.h +++ b/src/NotesLoaderSSC.h @@ -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. diff --git a/src/Song.cpp b/src/Song.cpp index 2e8b5cf3ca..ef590b7f2a 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -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 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(); diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 622dca3358..551f22ee60 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -1713,26 +1713,80 @@ void SongManager::LoadStepEditsFromProfileDir( const RString &sProfileDir, Profi { // Load all edit steps RString sDir = sProfileDir + EDIT_STEPS_SUBDIR; - - vector 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 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 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 vsGroups; + GetDirListing( sDir+"*", vsGroups, true, false ); + + // XXX: Same as above, edits may be skipped in error in some cases + for( int i=0; i vsSongs; + GetDirListing(sDir+sGroupDir+"*", vsSongs, true, false ); + + for( int j=0; j 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 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 ) diff --git a/src/Steps.cpp b/src/Steps.cpp index 40c9258665..6a64c1da92 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -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; }