Add sorting by Block level

(cherry picked from commit e1c8326a6a71f4a15c3f123391dc3f3331ee4a7b)
This commit is contained in:
Crash Cringle
2024-02-25 09:36:21 -08:00
committed by teejusb
parent 3fd0bd8ade
commit d788071d4d
9 changed files with 125 additions and 47 deletions
@@ -0,0 +1 @@
Common fallback banner
+1
View File
@@ -170,6 +170,7 @@ static const char *SortOrderNames[] = {
"TopP2Grades", "TopP2Grades",
"Artist", "Artist",
"Genre", "Genre",
"Meter",
"BeginnerMeter", "BeginnerMeter",
"EasyMeter", "EasyMeter",
"MediumMeter", "MediumMeter",
+1
View File
@@ -170,6 +170,7 @@ enum SortOrder
SORT_TOP_GRADES_P2, /**< Sort by the highest grades earned on a Song for P2. */ SORT_TOP_GRADES_P2, /**< Sort by the highest grades earned on a Song for P2. */
SORT_ARTIST, /**< Sort by the name of the artist of the Song. */ SORT_ARTIST, /**< Sort by the name of the artist of the Song. */
SORT_GENRE, /**< Sort by the Song's genre. */ SORT_GENRE, /**< Sort by the Song's genre. */
SORT_METER, /**< Sort by the difficulty of all meters */
SORT_BEGINNER_METER, /**< Sort by the difficulty of the single beginner meter. */ SORT_BEGINNER_METER, /**< Sort by the difficulty of the single beginner meter. */
SORT_EASY_METER, /**< Sort by the difficulty of the single easy meter. */ SORT_EASY_METER, /**< Sort by the difficulty of the single easy meter. */
SORT_MEDIUM_METER, /**< Sort by the difficulty of the single medium meter. */ SORT_MEDIUM_METER, /**< Sort by the difficulty of the single medium meter. */
+70 -46
View File
@@ -537,6 +537,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector<MusicWheelItemData *> &arrayWh
} }
break; break;
} }
case SORT_METER:
case SORT_PREFERRED: case SORT_PREFERRED:
case SORT_ROULETTE: case SORT_ROULETTE:
case SORT_GROUP: case SORT_GROUP:
@@ -569,6 +570,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector<MusicWheelItemData *> &arrayWh
// sort the songs // sort the songs
switch( so ) switch( so )
{ {
case SORT_METER:
case SORT_PREFERRED: case SORT_PREFERRED:
// obey order specified by the preferred sort list // obey order specified by the preferred sort list
break; break;
@@ -674,6 +676,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector<MusicWheelItemData *> &arrayWh
/* We're using sections, so use the section name as the top-level sort. */ /* We're using sections, so use the section name as the top-level sort. */
switch( so ) switch( so )
{ {
case SORT_METER:
case SORT_PREFERRED: case SORT_PREFERRED:
case SORT_TOP_GRADES: case SORT_TOP_GRADES:
case SORT_TOP_GRADES_P1: case SORT_TOP_GRADES_P1:
@@ -689,58 +692,79 @@ void MusicWheel::BuildWheelItemDatas( std::vector<MusicWheelItemData *> &arrayWh
// make WheelItemDatas with sections // make WheelItemDatas with sections
RString sLastSection = ""; RString sLastSection = "";
int iSectionColorIndex = 0; int iSectionColorIndex = 0;
switch (so) {
// If the sort order is Preferred handle it differently because we already know the sections case SORT_PREFERRED:
if( so == SORT_PREFERRED ) // If the sort order is Preferred handle it differently because we already know the sections
{
if( bUseSections )
{
// Get mappping of section names to songs
std::map<RString, std::vector<Song*>> preferredSortSongsMap = SONGMAN->GetPreferredSortSongsMap();
for (auto const& [sectionName, songs] : SONGMAN->GetPreferredSortSongsMap())
{
// todo: preferred sort section color handling? -aj
RageColor colorSection = SECTION_COLORS.GetValue(iSectionColorIndex);
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
// Add the section item
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sectionName, nullptr, colorSection, songs.size()) );
// Add all the songs in this section
for (auto const& song : songs)
{
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, sectionName, nullptr, SONGMAN->GetSongColor(song), 0) );
}
}
}
} else {
for( unsigned i=0; i< arraySongs.size(); i++ )
{
Song* pSong = arraySongs[i];
if( bUseSections ) if( bUseSections )
{ {
RString sThisSection = SongUtil::GetSectionNameFromSongAndSort( pSong, so ); // Get mappping of section names to songs
std::map<RString, std::vector<Song*>> preferredSortSongsMap = SONGMAN->GetPreferredSortSongsMap();
if( sThisSection != sLastSection ) for (auto const& [sectionName, songs] : SONGMAN->GetPreferredSortSongsMap())
{ {
int iSectionCount = 0; // todo: preferred sort section color handling? -aj
// Count songs in this section RageColor colorSection = SECTION_COLORS.GetValue(iSectionColorIndex);
unsigned j;
for( j=i; j < arraySongs.size(); j++ )
{
if( SongUtil::GetSectionNameFromSongAndSort( arraySongs[j], so ) != sThisSection )
break;
}
iSectionCount = j-i;
// new section, make a section item
RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(pSong->m_sGroupName) : SECTION_COLORS.GetValue(iSectionColorIndex);
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS; iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, colorSection, iSectionCount) ); // Add the section item
sLastSection = sThisSection; arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sectionName, nullptr, colorSection, songs.size()) );
// Add all the songs in this section
for (auto const& song : songs)
{
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, sectionName, nullptr, SONGMAN->GetSongColor(song), 0) );
}
} }
} }
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, pSong, sLastSection, nullptr, SONGMAN->GetSongColor(pSong), 0) ); break;
} case SORT_METER:
// If the sort order is Preferred handle it differently because we already know the sections
if( bUseSections )
{
int iSectionCount = 0;
// // Get all section names
std::map<int, std::vector<Song*>> meterSortSongsMap = SONGMAN->GetMeterToSongsMap();
for (auto const& [sectionName, songs] : SONGMAN->GetMeterToSongsMap()) {
RageColor colorSection = SECTION_COLORS.GetValue(iSectionColorIndex);
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
// Add the section item
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, ssprintf("%d",sectionName), nullptr, colorSection, songs.size()) );
// Add all the songs in this section
for (auto const& song : songs)
{
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, ssprintf("%d",sectionName), nullptr, SONGMAN->GetSongColor(song), 0) );
}
}
}
break;
default:
for( unsigned i=0; i< arraySongs.size(); i++ )
{
Song* pSong = arraySongs[i];
if( bUseSections )
{
RString sThisSection = SongUtil::GetSectionNameFromSongAndSort( pSong, so );
if( sThisSection != sLastSection )
{
int iSectionCount = 0;
// Count songs in this section
unsigned j;
for( j=i; j < arraySongs.size(); j++ )
{
if( SongUtil::GetSectionNameFromSongAndSort( arraySongs[j], so ) != sThisSection )
break;
}
iSectionCount = j-i;
// new section, make a section item
// todo: preferred sort section color handling? -aj
RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(pSong->m_sGroupName) : SECTION_COLORS.GetValue(iSectionColorIndex);
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, colorSection, iSectionCount) );
sLastSection = sThisSection;
}
}
arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, pSong, sLastSection, nullptr, SONGMAN->GetSongColor(pSong), 0) );
}
break;
} }
if( so != SORT_ROULETTE ) if( so != SORT_ROULETTE )
+40
View File
@@ -214,6 +214,7 @@ void SongManager::Reload( bool bAllowFastLoad, LoadingWindow *ld )
PREFSMAN->m_bFastLoad.Set( oldVal ); PREFSMAN->m_bFastLoad.Set( oldVal );
UpdatePreferredSort(); UpdatePreferredSort();
UpdateMeterSort();
} }
void SongManager::LoadAdditions( LoadingWindow *ld ) void SongManager::LoadAdditions( LoadingWindow *ld )
@@ -227,6 +228,7 @@ void SongManager::LoadAdditions( LoadingWindow *ld )
UNLOCKMAN->Reload(); UNLOCKMAN->Reload();
UpdatePreferredSort(); UpdatePreferredSort();
UpdateMeterSort();
} }
void SongManager::InitSongsFromDisk( LoadingWindow *ld, bool onlyAdditions ) void SongManager::InitSongsFromDisk( LoadingWindow *ld, bool onlyAdditions )
@@ -889,6 +891,16 @@ void SongManager::GetPreferredSortCourses( CourseType ct, std::vector<Course*> &
} }
} }
std::vector<Song*> SongManager::GetSongsByMeter(const int iMeter) const {
std::vector<Song*> AddTo;
auto iter = m_mapSongsByDifficulty.find(iMeter);
if (iter != m_mapSongsByDifficulty.end()) {
// Found the level, add the songs to AddTo
AddTo.insert(AddTo.end(), iter->second.begin(), iter->second.end());
}
return AddTo;
}
int SongManager::GetNumSongs() const int SongManager::GetNumSongs() const
{ {
return m_pSongs.size(); return m_pSongs.size();
@@ -1225,6 +1237,7 @@ void SongManager::Invalidate( const Song *pStaleSong )
UpdatePopular(); UpdatePopular();
UpdateShuffled(); UpdateShuffled();
UpdateMeterSort();
RefreshCourseGroupInfo(); RefreshCourseGroupInfo();
} }
@@ -1617,6 +1630,33 @@ void SongManager::UpdatePopular()
} }
} }
void SongManager::UpdateMeterSort() {
std::vector<Song*> apDifficultSongs = m_pSongs;
// For each song, for each step
for( unsigned i = 0; i < apDifficultSongs.size(); ++i )
{
const std::vector<Steps*> &vSteps = apDifficultSongs[i]->GetAllSteps();
for( unsigned j = 0; j < vSteps.size(); ++j )
{
Steps *pSteps = vSteps[j];
// Check if the meter is already in m_mapSongsByDifficulty
if (std::find(m_mapSongsByDifficulty[pSteps->GetMeter()].begin(), m_mapSongsByDifficulty[pSteps->GetMeter()].end(), apDifficultSongs[i]) != m_mapSongsByDifficulty[pSteps->GetMeter()].end())
continue;
else {
m_mapSongsByDifficulty[pSteps->GetMeter()].push_back(apDifficultSongs[i]);
}
}
}
// For each meter in m_mapSongsByDifficulty, sort the songs by title
for( unsigned i = 0; i < m_mapSongsByDifficulty.size(); ++i )
{
SongUtil::SortSongPointerArrayByTitle( m_mapSongsByDifficulty[i] );
}
}
void SongManager::UpdateShuffled() void SongManager::UpdateShuffled()
{ {
// update shuffled // update shuffled
+7 -1
View File
@@ -142,13 +142,14 @@ public:
* @return the songs within the game that have at least one valid Step. */ * @return the songs within the game that have at least one valid Step. */
const std::vector<Song *> &GetAllSongsOfCurrentGame() const; const std::vector<Song *> &GetAllSongsOfCurrentGame() const;
std::map<int, std::vector<Song*>> GetMeterToSongsMap() const { return m_mapSongsByDifficulty; }
void GetPreferredSortSongs( std::vector<Song*> &AddTo ) const; void GetPreferredSortSongs( std::vector<Song*> &AddTo ) const;
std::map<RString, std::vector<Song*>> GetPreferredSortSongsMap() const { return m_mapPreferredSectionToSongs;}; std::map<RString, std::vector<Song*>> GetPreferredSortSongsMap() const { return m_mapPreferredSectionToSongs;};
RString SongToPreferredSortSectionName( const Song *pSong ) const; RString SongToPreferredSortSectionName( const Song *pSong ) const;
std::vector<RString> GetPreferredSortSectionNames() const; std::vector<RString> GetPreferredSortSectionNames() const;
std::vector<Song*> GetPreferredSortSongsBySectionName( const RString &sSectionName ) const; std::vector<Song*> GetPreferredSortSongsBySectionName( const RString &sSectionName ) const;
void GetPreferredSortSongsBySectionName( const RString &sSectionName, std::vector<Song*> &AddTo ) const; void GetPreferredSortSongsBySectionName( const RString &sSectionName, std::vector<Song*> &AddTo ) const;
std::vector<Song*> GetSongsByMeter( int iMeter ) const;
const std::vector<Course*> &GetPopularCourses( CourseType ct ) const { return m_pPopularCourses[ct]; } const std::vector<Course*> &GetPopularCourses( CourseType ct ) const { return m_pPopularCourses[ct]; }
Song *FindSong( RString sPath ) const; Song *FindSong( RString sPath ) const;
Song *FindSong( RString sGroup, RString sSong ) const; Song *FindSong( RString sGroup, RString sSong ) const;
@@ -188,6 +189,7 @@ public:
void UpdatePopular(); void UpdatePopular();
void UpdateShuffled(); // re-shuffle songs and courses void UpdateShuffled(); // re-shuffle songs and courses
void UpdateMeterSort();
void SetPreferredSongs(RString sPreferredSongs, bool bIsAbsolute = false); void SetPreferredSongs(RString sPreferredSongs, bool bIsAbsolute = false);
void SetPreferredCourses(RString sPreferredCourses, bool bIsAbsolute = false); void SetPreferredCourses(RString sPreferredCourses, bool bIsAbsolute = false);
void UpdatePreferredSort(RString sPreferredSongs = "PreferredSongs.txt", RString sPreferredCourses = "PreferredCourses.txt"); void UpdatePreferredSort(RString sPreferredSongs = "PreferredSongs.txt", RString sPreferredCourses = "PreferredCourses.txt");
@@ -225,6 +227,10 @@ protected:
/** @brief The most popular songs ranked by number of plays. */ /** @brief The most popular songs ranked by number of plays. */
std::vector<Song*> m_pPopularSongs; std::vector<Song*> m_pPopularSongs;
std::vector<Song*> m_pShuffledSongs; // used by GetRandomSong std::vector<Song*> m_pShuffledSongs; // used by GetRandomSong
/** @brief Meter numbers and the songs with Steps that are within.*/
std::map<int, std::vector<Song*>> m_mapSongsByDifficulty;
struct PreferredSortSection struct PreferredSortSection
{ {
RString sName; RString sName;
+3
View File
@@ -543,6 +543,7 @@ void SongUtil::SortSongPointerArrayByDisplayArtist( std::vector<Song*> &vpSongsI
stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending ); stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending );
} }
static int CompareSongPointersByGenre(const Song *pSong1, const Song *pSong2) static int CompareSongPointersByGenre(const Song *pSong1, const Song *pSong2)
{ {
return pSong1->m_sGenre < pSong2->m_sGenre; return pSong1->m_sGenre < pSong2->m_sGenre;
@@ -720,6 +721,8 @@ RString SongUtil::GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so
return ssprintf("%02d", pSteps->GetMeter() ); return ssprintf("%02d", pSteps->GetMeter() );
return SORT_NOT_AVAILABLE.GetValue(); return SORT_NOT_AVAILABLE.GetValue();
} }
case SORT_METER:
return RString();
case SORT_MODE_MENU: case SORT_MODE_MENU:
return RString(); return RString();
case SORT_ALL_COURSES: case SORT_ALL_COURSES:
+1
View File
@@ -146,6 +146,7 @@ namespace SongUtil
void SortSongPointerArrayByNumPlays( std::vector<Song*> &vpSongsInOut, ProfileSlot slot, bool bDescending ); void SortSongPointerArrayByNumPlays( std::vector<Song*> &vpSongsInOut, ProfileSlot slot, bool bDescending );
void SortSongPointerArrayByNumPlays( std::vector<Song*> &vpSongsInOut, const Profile* pProfile, bool bDescending ); void SortSongPointerArrayByNumPlays( std::vector<Song*> &vpSongsInOut, const Profile* pProfile, bool bDescending );
void SortSongPointerArrayByStepsTypeAndMeter( std::vector<Song*> &vpSongsInOut, StepsType st, Difficulty dc ); void SortSongPointerArrayByStepsTypeAndMeter( std::vector<Song*> &vpSongsInOut, StepsType st, Difficulty dc );
void SortSongPointerArrayByStepsTypeAndLevel( std::vector<Song*> &vpSongsInOut, StepsType st, int iMeter );
RString GetSectionNameFromSongAndSort( const Song *pSong, SortOrder so ); RString GetSectionNameFromSongAndSort( const Song *pSong, SortOrder so );
void SortSongPointerArrayBySectionName( std::vector<Song*> &vpSongsInOut, SortOrder so ); void SortSongPointerArrayBySectionName( std::vector<Song*> &vpSongsInOut, SortOrder so );
void SortByMostRecentlyPlayedForMachine( std::vector<Song*> &vpSongsInOut ); void SortByMostRecentlyPlayedForMachine( std::vector<Song*> &vpSongsInOut );
+1
View File
@@ -1006,6 +1006,7 @@ int sm_main(int argc, char* argv[])
UNLOCKMAN = new UnlockManager; UNLOCKMAN = new UnlockManager;
SONGMAN->UpdatePopular(); SONGMAN->UpdatePopular();
SONGMAN->UpdatePreferredSort(); SONGMAN->UpdatePreferredSort();
SONGMAN->UpdateMeterSort();
NETWORK = new NetworkManager; NETWORK = new NetworkManager;
STATSMAN = new StatsManager; STATSMAN = new StatsManager;