From d788071d4ddf1eff91b60a3d949383f9fdf9566c Mon Sep 17 00:00:00 2001 From: Crash Cringle <30600688+CrashCringle12@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:56:44 -0500 Subject: [PATCH] Add sorting by Block level (cherry picked from commit e1c8326a6a71f4a15c3f123391dc3f3331ee4a7b) --- Themes/_fallback/Graphics/Banner Meter.redir | 1 + src/GameConstantsAndTypes.cpp | 1 + src/GameConstantsAndTypes.h | 1 + src/MusicWheel.cpp | 116 +++++++++++-------- src/SongManager.cpp | 40 +++++++ src/SongManager.h | 8 +- src/SongUtil.cpp | 3 + src/SongUtil.h | 1 + src/StepMania.cpp | 1 + 9 files changed, 125 insertions(+), 47 deletions(-) create mode 100644 Themes/_fallback/Graphics/Banner Meter.redir diff --git a/Themes/_fallback/Graphics/Banner Meter.redir b/Themes/_fallback/Graphics/Banner Meter.redir new file mode 100644 index 0000000000..507050cda9 --- /dev/null +++ b/Themes/_fallback/Graphics/Banner Meter.redir @@ -0,0 +1 @@ +Common fallback banner \ No newline at end of file diff --git a/src/GameConstantsAndTypes.cpp b/src/GameConstantsAndTypes.cpp index 795f4b45cc..7b0f904865 100644 --- a/src/GameConstantsAndTypes.cpp +++ b/src/GameConstantsAndTypes.cpp @@ -170,6 +170,7 @@ static const char *SortOrderNames[] = { "TopP2Grades", "Artist", "Genre", + "Meter", "BeginnerMeter", "EasyMeter", "MediumMeter", diff --git a/src/GameConstantsAndTypes.h b/src/GameConstantsAndTypes.h index 0b8dd09465..3172e6ce4a 100644 --- a/src/GameConstantsAndTypes.h +++ b/src/GameConstantsAndTypes.h @@ -170,6 +170,7 @@ enum SortOrder 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_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_EASY_METER, /**< Sort by the difficulty of the single easy meter. */ SORT_MEDIUM_METER, /**< Sort by the difficulty of the single medium meter. */ diff --git a/src/MusicWheel.cpp b/src/MusicWheel.cpp index 6679929fcf..08ace5f89a 100644 --- a/src/MusicWheel.cpp +++ b/src/MusicWheel.cpp @@ -537,6 +537,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh } break; } + case SORT_METER: case SORT_PREFERRED: case SORT_ROULETTE: case SORT_GROUP: @@ -569,6 +570,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh // sort the songs switch( so ) { + case SORT_METER: case SORT_PREFERRED: // obey order specified by the preferred sort list break; @@ -674,6 +676,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh /* We're using sections, so use the section name as the top-level sort. */ switch( so ) { + case SORT_METER: case SORT_PREFERRED: case SORT_TOP_GRADES: case SORT_TOP_GRADES_P1: @@ -689,58 +692,79 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh // make WheelItemDatas with sections RString sLastSection = ""; int iSectionColorIndex = 0; - - // If the sort order is Preferred handle it differently because we already know the sections - if( so == SORT_PREFERRED ) - { - if( bUseSections ) - { - // Get mappping of section names to songs - std::map> 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]; + switch (so) { + case SORT_PREFERRED: + // If the sort order is Preferred handle it differently because we already know the sections if( bUseSections ) { - RString sThisSection = SongUtil::GetSectionNameFromSongAndSort( pSong, so ); - - if( sThisSection != sLastSection ) + // Get mappping of section names to songs + std::map> preferredSortSongsMap = SONGMAN->GetPreferredSortSongsMap(); + for (auto const& [sectionName, songs] : SONGMAN->GetPreferredSortSongsMap()) { - 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 - RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(pSong->m_sGroupName) : SECTION_COLORS.GetValue(iSectionColorIndex); + // todo: preferred sort section color handling? -aj + RageColor colorSection = SECTION_COLORS.GetValue(iSectionColorIndex); iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS; - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, colorSection, iSectionCount) ); - sLastSection = sThisSection; + // 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) ); + } } } - 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> 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 ) diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 03dfa68cae..d5d99ba11d 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -214,6 +214,7 @@ void SongManager::Reload( bool bAllowFastLoad, LoadingWindow *ld ) PREFSMAN->m_bFastLoad.Set( oldVal ); UpdatePreferredSort(); + UpdateMeterSort(); } void SongManager::LoadAdditions( LoadingWindow *ld ) @@ -227,6 +228,7 @@ void SongManager::LoadAdditions( LoadingWindow *ld ) UNLOCKMAN->Reload(); UpdatePreferredSort(); + UpdateMeterSort(); } void SongManager::InitSongsFromDisk( LoadingWindow *ld, bool onlyAdditions ) @@ -889,6 +891,16 @@ void SongManager::GetPreferredSortCourses( CourseType ct, std::vector & } } +std::vector SongManager::GetSongsByMeter(const int iMeter) const { + std::vector 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 { return m_pSongs.size(); @@ -1225,6 +1237,7 @@ void SongManager::Invalidate( const Song *pStaleSong ) UpdatePopular(); UpdateShuffled(); + UpdateMeterSort(); RefreshCourseGroupInfo(); } @@ -1617,6 +1630,33 @@ void SongManager::UpdatePopular() } } +void SongManager::UpdateMeterSort() { + std::vector apDifficultSongs = m_pSongs; + // For each song, for each step + for( unsigned i = 0; i < apDifficultSongs.size(); ++i ) + { + const std::vector &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() { // update shuffled diff --git a/src/SongManager.h b/src/SongManager.h index ada2313131..a9b21b0be2 100644 --- a/src/SongManager.h +++ b/src/SongManager.h @@ -142,13 +142,14 @@ public: * @return the songs within the game that have at least one valid Step. */ const std::vector &GetAllSongsOfCurrentGame() const; + std::map> GetMeterToSongsMap() const { return m_mapSongsByDifficulty; } void GetPreferredSortSongs( std::vector &AddTo ) const; std::map> GetPreferredSortSongsMap() const { return m_mapPreferredSectionToSongs;}; RString SongToPreferredSortSectionName( const Song *pSong ) const; std::vector GetPreferredSortSectionNames() const; std::vector GetPreferredSortSongsBySectionName( const RString &sSectionName ) const; void GetPreferredSortSongsBySectionName( const RString &sSectionName, std::vector &AddTo ) const; - + std::vector GetSongsByMeter( int iMeter ) const; const std::vector &GetPopularCourses( CourseType ct ) const { return m_pPopularCourses[ct]; } Song *FindSong( RString sPath ) const; Song *FindSong( RString sGroup, RString sSong ) const; @@ -188,6 +189,7 @@ public: void UpdatePopular(); void UpdateShuffled(); // re-shuffle songs and courses + void UpdateMeterSort(); void SetPreferredSongs(RString sPreferredSongs, bool bIsAbsolute = false); void SetPreferredCourses(RString sPreferredCourses, bool bIsAbsolute = false); 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. */ std::vector m_pPopularSongs; std::vector m_pShuffledSongs; // used by GetRandomSong + + /** @brief Meter numbers and the songs with Steps that are within.*/ + std::map> m_mapSongsByDifficulty; + struct PreferredSortSection { RString sName; diff --git a/src/SongUtil.cpp b/src/SongUtil.cpp index 75c061d0d5..578aa82f8a 100644 --- a/src/SongUtil.cpp +++ b/src/SongUtil.cpp @@ -543,6 +543,7 @@ void SongUtil::SortSongPointerArrayByDisplayArtist( std::vector &vpSongsI stable_sort( vpSongsInOut.begin(), vpSongsInOut.end(), CompareSongPointersBySortValueAscending ); } + static int CompareSongPointersByGenre(const Song *pSong1, const Song *pSong2) { 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 SORT_NOT_AVAILABLE.GetValue(); } + case SORT_METER: + return RString(); case SORT_MODE_MENU: return RString(); case SORT_ALL_COURSES: diff --git a/src/SongUtil.h b/src/SongUtil.h index 7d921c61ec..d3ee9d85ee 100644 --- a/src/SongUtil.h +++ b/src/SongUtil.h @@ -146,6 +146,7 @@ namespace SongUtil void SortSongPointerArrayByNumPlays( std::vector &vpSongsInOut, ProfileSlot slot, bool bDescending ); void SortSongPointerArrayByNumPlays( std::vector &vpSongsInOut, const Profile* pProfile, bool bDescending ); void SortSongPointerArrayByStepsTypeAndMeter( std::vector &vpSongsInOut, StepsType st, Difficulty dc ); + void SortSongPointerArrayByStepsTypeAndLevel( std::vector &vpSongsInOut, StepsType st, int iMeter ); RString GetSectionNameFromSongAndSort( const Song *pSong, SortOrder so ); void SortSongPointerArrayBySectionName( std::vector &vpSongsInOut, SortOrder so ); void SortByMostRecentlyPlayedForMachine( std::vector &vpSongsInOut ); diff --git a/src/StepMania.cpp b/src/StepMania.cpp index 9facfefd6c..dc8b072962 100644 --- a/src/StepMania.cpp +++ b/src/StepMania.cpp @@ -1006,6 +1006,7 @@ int sm_main(int argc, char* argv[]) UNLOCKMAN = new UnlockManager; SONGMAN->UpdatePopular(); SONGMAN->UpdatePreferredSort(); + SONGMAN->UpdateMeterSort(); NETWORK = new NetworkManager; STATSMAN = new StatsManager;