diff --git a/stepmania/Themes/default/Other/SongManager PreferredCourses.txt b/stepmania/Themes/default/Other/SongManager PreferredCourses.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/stepmania/Themes/default/Other/SongManager PreferredSongs.txt b/stepmania/Themes/default/Other/SongManager PreferredSongs.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index f09f36bd8f..ba84283125 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -884,6 +884,27 @@ void Course::CalculateRadarValues() } } +bool Course::Matches( RString sGroup, RString sCourse ) const +{ + if( sGroup.size() && sGroup.CompareNoCase(this->m_sGroupName) != 0) + return false; + + RString sFile = m_sPath; + sFile.Replace("\\","/"); + vector bits; + split( sFile, "/", bits ); + ASSERT(bits.size() >= 2); /* should always have at least two parts */ + const RString &sLastBit = bits[bits.size()-1]; + + if( sCourse.EqualsNoCase(sLastBit) ) + return true; + if( sCourse.EqualsNoCase(this->GetTranslitFullTitle()) ) + return true; + + return false; +} + + // lua start #include "LuaBinding.h" diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index 588f0f41a4..b22c39ce9a 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -186,6 +186,8 @@ public: ProfileSlot GetLoadedFromProfileSlot() const { return m_LoadedFromProfile; } void SetLoadedFromProfile( ProfileSlot slot ) { m_LoadedFromProfile = slot; } + bool Matches(RString sGroup, RString sCourse) const; + // Lua void PushSelf( lua_State *L ); diff --git a/stepmania/src/GameCommand.cpp b/stepmania/src/GameCommand.cpp index aeef50a1f4..ee2a93b0af 100644 --- a/stepmania/src/GameCommand.cpp +++ b/stepmania/src/GameCommand.cpp @@ -261,7 +261,7 @@ void GameCommand::LoadOne( const Command& cmd ) else if( sName == "course" ) { - m_pCourse = SONGMAN->FindCourse( sValue ); + m_pCourse = SONGMAN->FindCourse( "", sValue ); if( m_pCourse == NULL ) { m_sInvalidReason = ssprintf( "Course \"%s\" not found", sValue.c_str() ); diff --git a/stepmania/src/MusicWheel.cpp b/stepmania/src/MusicWheel.cpp index ecb01b2327..80777990fd 100644 --- a/stepmania/src/MusicWheel.cpp +++ b/stepmania/src/MusicWheel.cpp @@ -624,14 +624,14 @@ void MusicWheel::BuildWheelItemDatas( vector &arrayWheelItemDatas switch( so ) { case SORT_NONSTOP_COURSES: - SONGMAN->GetCourses( COURSE_TYPE_NONSTOP, apCourses, PREFSMAN->m_bAutogenGroupCourses ); + SONGMAN->GetPreferredSortCourses( COURSE_TYPE_NONSTOP, apCourses, PREFSMAN->m_bAutogenGroupCourses ); break; case SORT_ONI_COURSES: - SONGMAN->GetCourses( COURSE_TYPE_ONI, apCourses, PREFSMAN->m_bAutogenGroupCourses ); - SONGMAN->GetCourses( COURSE_TYPE_SURVIVAL, apCourses, PREFSMAN->m_bAutogenGroupCourses ); + SONGMAN->GetPreferredSortCourses( COURSE_TYPE_ONI, apCourses, PREFSMAN->m_bAutogenGroupCourses ); + SONGMAN->GetPreferredSortCourses( COURSE_TYPE_SURVIVAL, apCourses, PREFSMAN->m_bAutogenGroupCourses ); break; case SORT_ENDLESS_COURSES: - SONGMAN->GetCourses( COURSE_TYPE_ENDLESS, apCourses, PREFSMAN->m_bAutogenGroupCourses ); + SONGMAN->GetPreferredSortCourses( COURSE_TYPE_ENDLESS, apCourses, PREFSMAN->m_bAutogenGroupCourses ); break; case SORT_ALL_COURSES: SONGMAN->GetAllCourses( apCourses, PREFSMAN->m_bAutogenGroupCourses ); @@ -647,6 +647,8 @@ void MusicWheel::BuildWheelItemDatas( vector &arrayWheelItemDatas { switch( PREFSMAN->m_CourseSortOrder ) { + case PrefsManager::COURSE_SOFT_PREFERRED: + break; case PrefsManager::COURSE_SORT_METER: CourseUtil::SortCoursePointerArrayByAvgDifficulty( apCourses ); break; @@ -684,7 +686,7 @@ void MusicWheel::BuildWheelItemDatas( vector &arrayWheelItemDatas { switch( pCourse->GetPlayMode() ) { - case PLAY_MODE_ONI: sThisSection = "Oni"; break; + case PLAY_MODE_ONI: sThisSection = "Oni"; break; case PLAY_MODE_NONSTOP: sThisSection = "Nonstop"; break; case PLAY_MODE_ENDLESS: sThisSection = "Endless"; break; } @@ -702,7 +704,7 @@ void MusicWheel::BuildWheelItemDatas( vector &arrayWheelItemDatas sLastSection = sThisSection; } - RageColor c = ( pCourse->m_sGroupName.size() == 0 ) ? pCourse->GetColor() : pCourse->GetColor() * SONGMAN->GetCourseColor(pCourse); + RageColor c = ( pCourse->m_sGroupName.size() == 0 ) ? pCourse->GetColor() : SONGMAN->GetCourseColor(pCourse); arrayWheelItemDatas.push_back( WheelItemData(TYPE_COURSE, NULL, sThisSection, pCourse, c) ); } break; diff --git a/stepmania/src/PrefsManager.h b/stepmania/src/PrefsManager.h index 1f38229a3d..64917824e1 100644 --- a/stepmania/src/PrefsManager.h +++ b/stepmania/src/PrefsManager.h @@ -190,7 +190,7 @@ public: Preference m_bSignProfileData; // course ranking - enum CourseSortOrders { COURSE_SORT_SONGS, COURSE_SORT_METER, COURSE_SORT_METER_SUM, COURSE_SORT_RANK }; + enum CourseSortOrders { COURSE_SOFT_PREFERRED, COURSE_SORT_SONGS, COURSE_SORT_METER, COURSE_SORT_METER_SUM, COURSE_SORT_RANK }; Preference m_CourseSortOrder; Preference m_bSubSortByNumSteps; enum GetRankingName { RANKING_OFF, RANKING_ON, RANKING_LIST }; diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index cefc677a13..447614ea5b 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -355,19 +355,19 @@ RageColor SongManager::GetSongColor( const Song* pSong ) if( USE_PREFERRED_SORT_COLOR ) { - FOREACH_CONST( SongPointerVector, m_vPreferredSortGroups, v ) + FOREACH_CONST( SongPointerVector, m_vPreferredSongSort, v ) { FOREACH_CONST( Song*, *v, s ) { if( *s == pSong ) { - int i = v - m_vPreferredSortGroups.begin(); + int i = v - m_vPreferredSongSort.begin(); return SONG_GROUP_COLOR.GetValue( i%NUM_SONG_GROUP_COLORS ); } } } - int i = m_vPreferredSortGroups.size(); + int i = m_vPreferredSongSort.size(); return SONG_GROUP_COLOR.GetValue( i%NUM_SONG_GROUP_COLORS ); } else @@ -449,7 +449,33 @@ RageColor SongManager::GetCourseGroupColor( const RString &sCourseGroup ) RageColor SongManager::GetCourseColor( const Course* pCourse ) { - return GetCourseGroupColor( pCourse->m_sGroupName ); + // Use unlock color if applicable + const UnlockEntry *pUE = UNLOCKMAN->FindCourse( pCourse ); + if( pUE ) + return UNLOCK_COLOR; + + + if( USE_PREFERRED_SORT_COLOR ) + { + FOREACH_CONST( CoursePointerVector, m_vPreferredCourseSort, v ) + { + FOREACH_CONST( Course*, *v, s ) + { + if( *s == pCourse ) + { + int i = v - m_vPreferredCourseSort.begin(); + return COURSE_GROUP_COLOR.GetValue( i%NUM_COURSE_GROUP_COLORS ); + } + } + } + + int i = m_vPreferredCourseSort.size(); + return COURSE_GROUP_COLOR.GetValue( i%NUM_COURSE_GROUP_COLORS ); + } + else + { + return GetCourseGroupColor( pCourse->m_sGroupName ); + } } static void GetSongsFromVector( const vector &Songs, vector &AddTo, RString sGroupName, int iMaxStages ) @@ -474,17 +500,31 @@ void SongManager::GetPopularSongs( vector &AddTo, RString sGroupName, int void SongManager::GetPreferredSortSongs( vector &AddTo, int iMaxStages ) const { - if( m_vPreferredSortGroups.empty() ) + if( m_vPreferredSongSort.empty() ) { GetSongs( AddTo, iMaxStages ); return; } - FOREACH_CONST( SongPointerVector, m_vPreferredSortGroups, v ) + FOREACH_CONST( SongPointerVector, m_vPreferredSongSort, v ) FOREACH_CONST( Song*, *v, s ) AddTo.push_back( *s ); } +void SongManager::GetPreferredSortCourses( CourseType ct, vector &AddTo, bool bIncludeAutogen ) const +{ + if( m_vPreferredCourseSort.empty() ) + { + GetCourses( ct, AddTo, bIncludeAutogen ); + return; + } + + FOREACH_CONST( CoursePointerVector, m_vPreferredCourseSort, v ) + FOREACH_CONST( Course*, *v, c ) + if( (*c)->GetCourseType() == ct ) + AddTo.push_back( *c ); +} + int SongManager::GetNumSongs() const { return m_pSongs.size(); @@ -957,7 +997,7 @@ void SongManager::GetAllCourses( vector &AddTo, bool bIncludeAutogen ) AddTo.push_back( m_pCourses[i] ); } -void SongManager::GetCourses( CourseType ct, vector &AddTo, bool bIncludeAutogen ) +void SongManager::GetCourses( CourseType ct, vector &AddTo, bool bIncludeAutogen ) const { for( unsigned i=0; iGetCourseType() == ct ) @@ -1234,21 +1274,35 @@ Song *SongManager::FindSong( RString sPath ) Song *SongManager::FindSong( RString sGroup, RString sSong ) { // foreach song - for( unsigned i = 0; i < m_pSongs.size(); i++ ) + FOREACH_CONST( Song*, m_pSongs, s ) { - if( m_pSongs[i]->Matches(sGroup, sSong) ) - return m_pSongs[i]; + if( (*s)->Matches(sGroup, sSong) ) + return *s; } return NULL; } -Course *SongManager::FindCourse( RString sName ) +Course *SongManager::FindCourse( RString sPath ) { - for( unsigned i = 0; i < m_pCourses.size(); i++ ) + sPath.Replace( '\\', '/' ); + vector bits; + split( sPath, "/", bits ); + + if( bits.size() == 1 ) + return FindCourse( "", bits[0] ); + else if( bits.size() == 2 ) + return FindCourse( bits[0], bits[1] ); + + return NULL; +} + +Course *SongManager::FindCourse( RString sGroup, RString sName ) +{ + FOREACH_CONST( Course*, m_pCourses, c ) { - if( !sName.CompareNoCase(m_pCourses[i]->GetDisplayFullTitle()) ) - return m_pCourses[i]; + if( (*c)->Matches(sGroup, sName) ) + return *c; } return NULL; @@ -1314,64 +1368,127 @@ void SongManager::UpdatePreferredSort() { ASSERT( UNLOCKMAN ); - m_vPreferredSortGroups.clear(); - - RString sFile = THEME->GetPathO( "SongManager", "PreferredSort.txt" ); - RageFile file; - if( !file.Open( sFile ) ) - return; - - vector vpSongs; - - RString sLine; - while( file.GetLine(sLine) ) { - bool bSectionDivider = sLine.find("---") != RString::npos; - if( bSectionDivider ) + m_vPreferredSongSort.clear(); + + RString sFile = THEME->GetPathO( "SongManager", "PreferredSongs.txt" ); + RageFile file; + if( !file.Open( sFile ) ) + return; + + vector vpSongs; + + RString sLine; + while( file.GetLine(sLine) ) { - if( !vpSongs.empty() ) + bool bSectionDivider = sLine.find("---") != RString::npos; + if( bSectionDivider ) { - m_vPreferredSortGroups.push_back( vpSongs ); - vpSongs.clear(); + if( !vpSongs.empty() ) + { + m_vPreferredSongSort.push_back( vpSongs ); + vpSongs.clear(); + } + } + else + { + Song *pSong = NULL; + if( !sLine.empty() ) + pSong = FindSong( sLine ); + if( pSong ) + vpSongs.push_back( pSong ); } } - else + + if( !vpSongs.empty() ) { - Song *pSong = NULL; - if( !sLine.empty() ) - pSong = FindSong( sLine ); - if( pSong ) - vpSongs.push_back( pSong ); + m_vPreferredSongSort.push_back( vpSongs ); + vpSongs.clear(); } - } - if( !vpSongs.empty() ) - { - m_vPreferredSortGroups.push_back( vpSongs ); - vpSongs.clear(); - } - - // move all unlock songs to a group at the bottom - vector vpUnlockSongs; - FOREACH( UnlockEntry, UNLOCKMAN->m_UnlockEntries, ue ) - { - if( ue->m_Type == UnlockRewardType_Song ) - vpUnlockSongs.push_back( ue->m_pSong ); - } - - FOREACH( SongPointerVector, m_vPreferredSortGroups, v ) - { - for( int i=v->size()-1; i>=0; i-- ) + // move all unlock songs to a group at the bottom + vector vpUnlockSongs; + FOREACH( UnlockEntry, UNLOCKMAN->m_UnlockEntries, ue ) { - Song *pSong = (*v)[i]; - if( find(vpUnlockSongs.begin(),vpUnlockSongs.end(),pSong) != vpUnlockSongs.end() ) + if( ue->m_Type == UnlockRewardType_Song ) + vpUnlockSongs.push_back( ue->m_pSong ); + } + + FOREACH( SongPointerVector, m_vPreferredSongSort, v ) + { + for( int i=v->size()-1; i>=0; i-- ) { - v->erase( v->begin()+i ); + Song *pSong = (*v)[i]; + if( find(vpUnlockSongs.begin(),vpUnlockSongs.end(),pSong) != vpUnlockSongs.end() ) + { + v->erase( v->begin()+i ); + } } } + + m_vPreferredSongSort.push_back( vpUnlockSongs ); } - m_vPreferredSortGroups.push_back( vpUnlockSongs ); + { + m_vPreferredCourseSort.clear(); + + RString sFile = THEME->GetPathO( "SongManager", "PreferredCourses.txt" ); + RageFile file; + if( !file.Open( sFile ) ) + return; + + vector vpCourses; + + RString sLine; + while( file.GetLine(sLine) ) + { + bool bSectionDivider = sLine.find("---") != RString::npos; + if( bSectionDivider ) + { + if( !vpCourses.empty() ) + { + m_vPreferredCourseSort.push_back( vpCourses ); + vpCourses.clear(); + } + } + else + { + Course *pCourse = NULL; + if( !sLine.empty() ) + pCourse = FindCourse( sLine ); + if( pCourse ) + vpCourses.push_back( pCourse ); + } + } + + if( !vpCourses.empty() ) + { + m_vPreferredCourseSort.push_back( vpCourses ); + vpCourses.clear(); + } + + // move all unlock Courses to a group at the bottom + vector vpUnlockCourses; + FOREACH( UnlockEntry, UNLOCKMAN->m_UnlockEntries, ue ) + { + if( ue->m_Type == UnlockRewardType_Course ) + vpUnlockCourses.push_back( ue->m_pCourse ); + } + + FOREACH( CoursePointerVector, m_vPreferredCourseSort, v ) + { + for( int i=v->size()-1; i>=0; i-- ) + { + Course *pCourse = (*v)[i]; + if( find(vpUnlockCourses.begin(),vpUnlockCourses.end(),pCourse) != vpUnlockCourses.end() ) + { + v->erase( v->begin()+i ); + } + } + } + + m_vPreferredCourseSort.push_back( vpUnlockCourses ); + } } void SongManager::SortSongs() diff --git a/stepmania/src/SongManager.h b/stepmania/src/SongManager.h index 412a8ce993..b681dbbbfc 100644 --- a/stepmania/src/SongManager.h +++ b/stepmania/src/SongManager.h @@ -83,7 +83,8 @@ public: void GetSongs( vector &AddTo ) const { GetSongs(AddTo,GROUP_ALL,INT_MAX); } Song *FindSong( RString sPath ); Song *FindSong( RString sGroup, RString sSong ); - Course *FindCourse( RString sName ); + Course *FindCourse( RString sPath ); + Course *FindCourse( RString sGroup, RString sName ); int GetNumSongs() const; int GetNumSongGroups() const; int GetNumCourses() const; @@ -98,8 +99,9 @@ public: bool WasLoadedFromAdditionalSongs( const Song *pSong ) const; void GetAllCourses( vector &AddTo, bool bIncludeAutogen ); - void GetCourses( CourseType ct, vector &AddTo, bool bIncludeAutogen ); + void GetCourses( CourseType ct, vector &AddTo, bool bIncludeAutogen ) const; void GetCoursesInGroup( vector &AddTo, const RString &sCourseGroup, bool bIncludeAutogen ); + void GetPreferredSortCourses( CourseType ct, vector &AddTo, bool bIncludeAutogen ) const; void GetExtraStageInfo( bool bExtra2, const Style *s, Song*& pSongOut, Steps*& pStepsOut, PlayerOptions *pPlayerOptionsOut, SongOptions *pSongOptionsOut ); @@ -132,7 +134,7 @@ protected: vector m_pPopularSongs[NUM_ProfileSlot]; vector m_pShuffledSongs; // used by GetRandomSong typedef vector SongPointerVector; - vector m_vPreferredSortGroups; + vector m_vPreferredSongSort; vector m_sSongGroupNames; vector m_sSongGroupBannerPaths; // each song group may have a banner associated with it @@ -144,6 +146,8 @@ protected: RString m_sBannerPath; }; map m_mapCourseGroupToInfo; + typedef vector CoursePointerVector; + vector m_vPreferredCourseSort; RageTexturePreloader m_TexturePreload;