diff --git a/src/Course.cpp b/src/Course.cpp index 5a2fe64921..fc4bd97454 100644 --- a/src/Course.cpp +++ b/src/Course.cpp @@ -56,8 +56,8 @@ RString CourseEntry::GetTextDescription() const vsEntryDescription.push_back( pSong->GetTranslitFullTitle() ); else vsEntryDescription.push_back( "Random" ); - if( !songCriteria.m_sGroupName.empty() ) - vsEntryDescription.push_back( songCriteria.m_sGroupName ); + if( !songCriteria.m_vsGroupNames.size() > 0 ) + vsEntryDescription.push_back( join(",", songCriteria.m_vsGroupNames) ); if( songCriteria.m_bUseSongGenreAllowedList ) vsEntryDescription.push_back( join(",",songCriteria.m_vsSongGenreAllowedList) ); if( stepsCriteria.m_difficulty != Difficulty_Invalid && stepsCriteria.m_difficulty != Difficulty_Medium ) diff --git a/src/CourseLoaderCRS.cpp b/src/CourseLoaderCRS.cpp index 2676375bc9..d6221a7b3f 100644 --- a/src/CourseLoaderCRS.cpp +++ b/src/CourseLoaderCRS.cpp @@ -356,8 +356,6 @@ bool CourseLoaderCRS::ParseCourseMods( const MsdFile::value_t &sParams, AttackAr bool CourseLoaderCRS::ParseCourseSong( const MsdFile::value_t &sParams, CourseEntry &new_entry, const RString &sPath ) { - LOG->Trace("CourseLoaderCRS::ParseCourseSong parsing song %s", sPath.c_str()); - LOG->Trace("CourseLoaderCRS::ParseCourseSong sParams[1] = %s", sParams[1].c_str()); // infer entry::Type from the first param // todo: make sure these aren't generating bogus entries due // to a lack of songs. -aj @@ -443,7 +441,7 @@ bool CourseLoaderCRS::ParseCourseSong( const MsdFile::value_t &sParams, CourseEn split( sSong, "/", bits ); if( bits.size() == 2 ) { - new_entry.songCriteria.m_sGroupName = bits[0]; + new_entry.songCriteria.m_vsGroupNames.push_back(bits[0]); } else { @@ -451,7 +449,7 @@ bool CourseLoaderCRS::ParseCourseSong( const MsdFile::value_t &sParams, CourseEn "Song should be in the format \"/*\".", sSong.c_str() ); } - if( !SONGMAN->DoesSongGroupExist(new_entry.songCriteria.m_sGroupName) ) + if( !SONGMAN->DoesSongGroupExist(bits[0]) ) { LOG->UserLog( "Course file", sPath, "random_within_group entry \"%s\" specifies a group that doesn't exist. " "This entry will be ignored.", sSong.c_str() ); @@ -468,8 +466,8 @@ bool CourseLoaderCRS::ParseCourseSong( const MsdFile::value_t &sParams, CourseEn Song *pSong = nullptr; if( bits.size() == 2 ) { - new_entry.songCriteria.m_sGroupName = bits[0]; - pSong = SONGMAN->FindSong( bits[0], bits[1] ); + new_entry.songCriteria.m_vsGroupNames.push_back(bits[0]); + pSong = SONGMAN->FindSong(bits[0], bits[1]); } else if( bits.size() == 1 ) { diff --git a/src/CourseUtil.cpp b/src/CourseUtil.cpp index be425160be..177bfbcc31 100644 --- a/src/CourseUtil.cpp +++ b/src/CourseUtil.cpp @@ -255,7 +255,7 @@ void CourseUtil::AutogenEndlessFromGroup( const RString &sGroupName, Difficulty // gameplay. (We might still get a repeat at the repeat boundary, // but that'd be rare.) -glenn CourseEntry e; - e.songCriteria.m_sGroupName = sGroupName; + e.songCriteria.m_vsGroupNames.push_back(sGroupName); e.stepsCriteria.m_difficulty = diff; e.bSecret = true; diff --git a/src/CourseWriterCRS.cpp b/src/CourseWriterCRS.cpp index af72517d96..dc0b3f9361 100644 --- a/src/CourseWriterCRS.cpp +++ b/src/CourseWriterCRS.cpp @@ -142,13 +142,13 @@ bool CourseWriterCRS::Write( const Course &course, RageFileBasic &f, bool bSavin const RString &sSong = Basename( pSong->GetSongDir() ); f.Write( "#SONG:" ); - if( !entry.songCriteria.m_sGroupName.empty() ) - f.Write( entry.songCriteria.m_sGroupName + '/' ); + if( entry.songCriteria.m_vsGroupNames.size() > 0 ) + f.Write( entry.songCriteria.m_vsGroupNames[0] + '/' ); f.Write( sSong ); } - else if( !entry.songCriteria.m_sGroupName.empty() ) + else if( entry.songCriteria.m_vsGroupNames.size() > 0 ) { - f.Write( ssprintf( "#SONG:%s/*", entry.songCriteria.m_sGroupName.c_str() ) ); + f.Write( ssprintf( "#SONG:%s/*", entry.songCriteria.m_vsGroupNames[0].c_str() ) ); } else { diff --git a/src/SongUtil.cpp b/src/SongUtil.cpp index 35dbdde09c..77bbe9e3c4 100644 --- a/src/SongUtil.cpp +++ b/src/SongUtil.cpp @@ -32,8 +32,10 @@ ThemeMetric SHOW_SECTIONS_IN_LENGTH_SORT ( "MusicWheel", "ShowSectionsInLe bool SongCriteria::Matches( const Song *pSong ) const { - if( !m_sGroupName.empty() && m_sGroupName != pSong->m_sGroupName ) + if( !m_vsGroupNames.size() > 0 && std::find(m_vsGroupNames.begin(), m_vsGroupNames.end(), pSong->m_sGroupName) == m_vsGroupNames.end() ) + { return false; + } if( UNLOCKMAN->SongIsLocked(pSong) & LOCKED_DISABLED ) return false; diff --git a/src/SongUtil.h b/src/SongUtil.h index 02c7451db5..b86651a4a0 100644 --- a/src/SongUtil.h +++ b/src/SongUtil.h @@ -25,7 +25,7 @@ public: * @brief What group name are we searching for for Songs? * * If an empty string, don't bother using this for searching. */ - RString m_sGroupName; + std::vector m_vsGroupNames; bool m_bUseSongGenreAllowedList; std::vector m_vsSongGenreAllowedList; enum Selectable { Selectable_Yes, Selectable_No, Selectable_DontCare } m_Selectable; @@ -51,7 +51,7 @@ public: } m_Locked; /** @brief Set up some initial song criteria. */ - SongCriteria(): m_sGroupName(""), m_bUseSongGenreAllowedList(false), + SongCriteria(): m_vsGroupNames(), m_bUseSongGenreAllowedList(false), m_vsSongGenreAllowedList(), m_Selectable(Selectable_DontCare), m_bUseSongAllowedList(false), m_vpSongAllowedList(), m_iMaxStagesForSong(-1), m_fMinBPM(-1), m_fMaxBPM(-1), m_Tutorial(Tutorial_DontCare), @@ -77,7 +77,7 @@ public: /** @brief A quick way to match every part of the song criterium. */ #define X(x) (x == other.x) return - X(m_sGroupName) && + X(m_vsGroupNames) && X(m_bUseSongGenreAllowedList) && X(m_vsSongGenreAllowedList) && X(m_Selectable) && diff --git a/src/StepsUtil.cpp b/src/StepsUtil.cpp index ec4497ab94..9ffeb6b6f4 100644 --- a/src/StepsUtil.cpp +++ b/src/StepsUtil.cpp @@ -44,8 +44,18 @@ bool StepsCriteria::Matches( const Song *pSong, const Steps *pSteps ) const void StepsUtil::GetAllMatching( const SongCriteria &soc, const StepsCriteria &stc, std::vector &out ) { - const RString &sGroupName = soc.m_sGroupName.empty()? GROUP_ALL:soc.m_sGroupName; - const std::vector &songs = SONGMAN->GetSongs( sGroupName ); + + std::vector groupNames = soc.m_vsGroupNames; + if( groupNames.size() == 0 ) + { + groupNames.push_back(GROUP_ALL); + } + std::vector songs; + for (unsigned i = 0; i < groupNames.size(); i++) + { + const std::vector &groupSongs = SONGMAN->GetSongs(groupNames[i]); + songs.insert(songs.end(), groupSongs.begin(), groupSongs.end()); + } for (Song *so : songs) { @@ -103,8 +113,17 @@ void StepsUtil::GetAllMatchingEndless( Song *pSong, const StepsCriteria &stc, st bool StepsUtil::HasMatching( const SongCriteria &soc, const StepsCriteria &stc ) { - const RString &sGroupName = soc.m_sGroupName.empty()? GROUP_ALL:soc.m_sGroupName; - const std::vector &songs = SONGMAN->GetSongs( sGroupName ); + std::vector groupNames = soc.m_vsGroupNames; + if( groupNames.size() == 0 ) + { + groupNames.push_back(GROUP_ALL); + } + std::vector songs; + for (unsigned i = 0; i < groupNames.size(); i++) + { + const std::vector &groupSongs = SONGMAN->GetSongs(groupNames[i]); + songs.insert(songs.end(), groupSongs.begin(), groupSongs.end()); + } return std::any_of(songs.begin(), songs.end(), [&](Song const *so) { return soc.Matches(so) && HasMatching(so, stc);