diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index be4b9313e2..d91d223a63 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -23,6 +23,17 @@ #include +static const CString SongSortNames[] = { + "Randomize", + "MostPlays", + "FewestPlays", + "TopGrades", + "LowestGrades", +}; +XToString( SongSort, NUM_SongSort ); +XToThemedString( SongSort, NUM_SongSort ); + + /* Maximum lower value of ranges when difficult: */ const int MAX_BOTTOM_RANGE = 10; @@ -44,7 +55,7 @@ CourseType Course::GetCourseType() const return COURSE_TYPE_ENDLESS; if( m_iLives > 0 ) return COURSE_TYPE_ONI; - FOREACH_CONST( CourseEntry, m_entries, e ) + FOREACH_CONST( CourseEntry, m_vEntries, e ) { if( e->fGainSeconds > 0 ) return COURSE_TYPE_SURVIVAL; @@ -211,13 +222,15 @@ void Course::LoadFromCRSFile( CString sPath ) // infer entry::Type from the first param if( sParams[1].Left(strlen("BEST")) == "BEST" ) { - new_entry.iMostPopularIndex = atoi( sParams[1].Right(sParams[1].size()-strlen("BEST")) ) - 1; - CLAMP( new_entry.iMostPopularIndex, 0, 500 ); + new_entry.iChooseIndex = atoi( sParams[1].Right(sParams[1].size()-strlen("BEST")) ) - 1; + CLAMP( new_entry.iChooseIndex, 0, 500 ); + new_entry.songSort = SongSort_MostPlays; } else if( sParams[1].Left(strlen("WORST")) == "WORST" ) { - new_entry.iLeastPopularIndex = atoi( sParams[1].Right(sParams[1].size()-strlen("WORST")) ) - 1; - CLAMP( new_entry.iLeastPopularIndex, 0, 500 ); + new_entry.iChooseIndex = atoi( sParams[1].Right(sParams[1].size()-strlen("WORST")) ) - 1; + CLAMP( new_entry.iChooseIndex, 0, 500 ); + new_entry.songSort = SongSort_FewestPlays; } else if( sParams[1] == "*" ) { @@ -231,11 +244,16 @@ void Course::LoadFromCRSFile( CString sPath ) CStringArray bits; split( sSong, "/", bits ); if( bits.size() == 2 ) + { new_entry.sSongGroup = bits[0]; + } else + { LOG->Warn( "Course file '%s' contains a random_within_group entry '%s' that is invalid. " "Song should be in the format '/*'.", sPath.c_str(), sSong.c_str()); + } + if( !SONGMAN->DoesSongGroupExist(new_entry.sSongGroup) ) { /* XXX: We need a place to put "user warnings". This is too loud for info.txt-- @@ -304,7 +322,7 @@ void Course::LoadFromCRSFile( CString sPath ) new_entry.fGainSeconds = fGainSeconds; attacks.clear(); - m_entries.push_back( new_entry ); + m_vEntries.push_back( new_entry ); } else if( bUseCache && !stricmp(sValueName, "RADAR") ) { @@ -331,7 +349,7 @@ void Course::LoadFromCRSFile( CString sPath ) /* Cache and load the course banner. Only bother doing this if at least one * song was found in the course. */ - if( m_sBannerPath != "" && !m_entries.empty() ) + if( m_sBannerPath != "" && !m_vEntries.empty() ) BANNERCACHE->CacheBanner( m_sBannerPath ); /* Cache each trail RadarValues that's slow to load, so we @@ -371,10 +389,10 @@ void Course::Init() m_bRandomize = false; m_iLives = -1; m_bSortByMeter = false; - m_entries.clear(); + m_vEntries.clear(); FOREACH_Difficulty(dc) m_iCustomMeter[dc] = -1; - m_entries.clear(); + m_vEntries.clear(); m_sPath = ""; m_sGroupName = ""; m_sMainTitle = ""; @@ -439,9 +457,9 @@ void Course::Save( CString sPath, bool bSavingCache ) f.PutLine( "// end cache tags" ); } - for( unsigned i=0; i 0 ) f.PutLine( ssprintf("#GAINSECONDS:%f;", entry.fGainSeconds) ); - if( entry.iMostPopularIndex != -1 ) + if( entry.songSort == SongSort_MostPlays && entry.iChooseIndex != -1 ) { - f.Write( ssprintf( "#SONG:BEST%d", entry.iMostPopularIndex+1 ) ); + f.Write( ssprintf( "#SONG:BEST%d", entry.iChooseIndex+1 ) ); } - else if( entry.iLeastPopularIndex != -1 ) + else if( entry.songSort == SongSort_FewestPlays && entry.iChooseIndex != -1 ) { - f.Write( ssprintf( "#SONG:WORST%d", entry.iLeastPopularIndex+1 ) ); + f.Write( ssprintf( "#SONG:WORST%d", entry.iChooseIndex+1 ) ); } else if( entry.pSong ) { @@ -550,7 +568,7 @@ void Course::AutogenEndlessFromGroup( CString sGroupName, Difficulty diff ) vector vSongs; SONGMAN->GetSongs( vSongs, e.sSongGroup ); for( unsigned i = 0; i < vSongs.size(); ++i) - m_entries.push_back( e ); + m_vEntries.push_back( e ); } void Course::AutogenNonstopFromGroup( CString sGroupName, Difficulty diff ) @@ -562,10 +580,10 @@ void Course::AutogenNonstopFromGroup( CString sGroupName, Difficulty diff ) m_sMainTitle += " Random"; // resize to 4 - while( m_entries.size() < 4 ) - m_entries.push_back( m_entries[0] ); - while( m_entries.size() > 4 ) - m_entries.pop_back(); + while( m_vEntries.size() < 4 ) + m_vEntries.push_back( m_vEntries[0] ); + while( m_vEntries.size() > 4 ) + m_vEntries.pop_back(); } void Course::AutogenOniFromArtist( CString sArtistName, CString sArtistNameTranslit, vector aSongs, Difficulty dc ) @@ -608,7 +626,7 @@ void Course::AutogenOniFromArtist( CString sArtistName, CString sArtistNameTrans for( unsigned i = 0; i < aSongs.size(); ++i ) { e.pSong = aSongs[i]; - m_entries.push_back( e ); + m_vEntries.push_back( e ); } } @@ -672,7 +690,7 @@ Trail* Course::GetTrail( StepsType st, CourseDifficulty cd ) const { /* If we have any random entries (so that the seed matters), invalidate the cache. */ bool bHaveRandom = false; - FOREACH_CONST( CourseEntry, m_entries, e ) + FOREACH_CONST( CourseEntry, m_vEntries, e ) { if( e->IsRandomSong() ) { @@ -792,11 +810,11 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail ) /* Always randomize the same way per round. Otherwise, the displayed course * will change every time it's viewed, and the displayed order will have no * bearing on what you'll actually play. */ - tmp_entries = m_entries; + tmp_entries = m_vEntries; random_shuffle( tmp_entries.begin(), tmp_entries.end(), rnd ); } - const vector &entries = m_bRandomize? tmp_entries:m_entries; + const vector &entries = m_bRandomize? tmp_entries:m_vEntries; /* This can take some time, so don't fill it out unless we need it. */ bool bMostPlayedSet = false; @@ -936,39 +954,36 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail ) // TODO: Move Course initialization after PROFILEMAN is created - if( PROFILEMAN && e->iMostPopularIndex != -1 ) + switch( e->songSort ) { - SongUtil::SortSongPointerArrayByNumPlays( vpPossibleSongs, PROFILEMAN->GetMachineProfile(), true ); // descending - if( e->iMostPopularIndex < vpPossibleSongs.size() ) - { - pResolvedSong = vpPossibleSongs[e->iMostPopularIndex]; - vector &vpPossibleSteps = mapSongToSteps[pResolvedSong]; - pResolvedSteps = vpPossibleSteps[0]; - } + default: + ASSERT(0); + case SongSort_Randomize: + random_shuffle( vpPossibleSongs.begin(), vpPossibleSongs.end(), rnd ); + break; + case SongSort_MostPlays: + if( PROFILEMAN ) + SongUtil::SortSongPointerArrayByNumPlays( vpPossibleSongs, PROFILEMAN->GetMachineProfile(), true ); // descending + break; + case SongSort_FewestPlays: + if( PROFILEMAN ) + SongUtil::SortSongPointerArrayByNumPlays( vpPossibleSongs, PROFILEMAN->GetMachineProfile(), false ); // ascending + break; + case SongSort_TopGrades: + SongUtil::SortSongPointerArrayByGrades( vpPossibleSongs, true ); // descending + break; + case SongSort_LowestGrades: + SongUtil::SortSongPointerArrayByGrades( vpPossibleSongs, false ); // ascending + break; } - else if( PROFILEMAN && e->iLeastPopularIndex != -1 ) + + if( e->iChooseIndex < vpPossibleSongs.size() ) { - SongUtil::SortSongPointerArrayByNumPlays( vpPossibleSongs, PROFILEMAN->GetMachineProfile(), false ); // ascending - if( e->iLeastPopularIndex < vpPossibleSongs.size() ) - { - pResolvedSong = vpPossibleSongs[e->iLeastPopularIndex]; - vector &vpPossibleSteps = mapSongToSteps[pResolvedSong]; - pResolvedSteps = vpPossibleSteps[0]; - } - } - else - { - if( !vpPossibleSongs.empty() ) - { - random_shuffle( vpPossibleSongs.begin(), vpPossibleSongs.end(), rnd ); - pResolvedSong = vpPossibleSongs[0]; - vector &vpPossibleSteps = mapSongToSteps[pResolvedSong]; - if( !vpPossibleSteps.empty() ) - { - random_shuffle( vpPossibleSteps.begin(), vpPossibleSteps.end(), rnd ); - pResolvedSteps = vpPossibleSteps[0]; - } - } + pResolvedSong = vpPossibleSongs[e->iChooseIndex]; + vector &vpPossibleSteps = mapSongToSteps[pResolvedSong]; + ASSERT( !vpPossibleSteps.empty() ); // if no steps are playable, this shouldn't be a possible song + random_shuffle( vpPossibleSteps.begin(), vpPossibleSteps.end(), rnd ); + pResolvedSteps = vpPossibleSteps[0]; } @@ -1096,7 +1111,7 @@ void Course::GetAllTrails( vector &AddTo ) const bool Course::HasMods() const { - FOREACH_CONST( CourseEntry, m_entries, e ) + FOREACH_CONST( CourseEntry, m_vEntries, e ) { if( !e->sModifiers.empty() || !e->attacks.empty() ) return true; @@ -1107,7 +1122,7 @@ bool Course::HasMods() const bool Course::AllSongsAreFixed() const { - FOREACH_CONST( CourseEntry, m_entries, e ) + FOREACH_CONST( CourseEntry, m_vEntries, e ) { if( e->pSong == NULL ) return false; @@ -1117,7 +1132,7 @@ bool Course::AllSongsAreFixed() const void Course::Invalidate( Song *pStaleSong ) { - FOREACH_CONST( CourseEntry, m_entries, e ) + FOREACH_CONST( CourseEntry, m_vEntries, e ) { if( e->pSong == pStaleSong ) // a fixed entry that references the stale Song { @@ -1161,8 +1176,8 @@ RageColor Course::GetColor() const switch( PREFSMAN->m_CourseSortOrder ) { case PrefsManager::COURSE_SORT_SONGS: - if( m_entries.size() >= 7 ) return SORT_LEVEL2_COLOR; - else if( m_entries.size() >= 4 ) return SORT_LEVEL4_COLOR; + if( m_vEntries.size() >= 7 ) return SORT_LEVEL2_COLOR; + else if( m_vEntries.size() >= 4 ) return SORT_LEVEL4_COLOR; else return SORT_LEVEL5_COLOR; case PrefsManager::COURSE_SORT_METER: @@ -1192,9 +1207,9 @@ RageColor Course::GetColor() const bool Course::IsFixed() const { - for(unsigned i = 0; i < m_entries.size(); i++) + for(unsigned i = 0; i < m_vEntries.size(); i++) { - if ( m_entries[i].pSong == NULL ) + if ( m_vEntries[i].pSong == NULL ) continue; return false; @@ -1217,11 +1232,11 @@ bool Course::GetTotalSeconds( StepsType st, float& fSecondsOut ) const bool Course::CourseHasBestOrWorst() const { - FOREACH_CONST( CourseEntry, m_entries, e ) + FOREACH_CONST( CourseEntry, m_vEntries, e ) { - if( e->iMostPopularIndex != -1 ) + if( e->iChooseIndex == SongSort_MostPlays && e->iChooseIndex != -1 ) return true; - if( e->iLeastPopularIndex != -1 ) + if( e->iChooseIndex == SongSort_FewestPlays && e->iChooseIndex != -1 ) return true; } @@ -1238,9 +1253,9 @@ void Course::UpdateCourseStats( StepsType st ) m_SortOrder_TotalDifficulty = 0; // courses with random/players best-worst songs should go at the end - for(unsigned i = 0; i < m_entries.size(); i++) + for(unsigned i = 0; i < m_vEntries.size(); i++) { - if ( m_entries[i].pSong != NULL ) + if ( m_vEntries[i].pSong != NULL ) continue; if ( m_SortOrder_Ranking == 2 ) @@ -1277,7 +1292,7 @@ bool Course::IsRanking() const const CourseEntry *Course::FindFixedSong( const Song *pSong ) const { - FOREACH_CONST( CourseEntry, m_entries, e ) + FOREACH_CONST( CourseEntry, m_vEntries, e ) { const CourseEntry &entry = *e; if( entry.pSong == pSong ) diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index 3111a12053..cc706fb4cc 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -32,6 +32,19 @@ inline PlayMode CourseTypeToPlayMode( CourseType ct ) { return (PlayMode)(PLAY_M inline CourseType PlayModeToCourseType( PlayMode pm ) { return (CourseType)(pm-PLAY_MODE_NONSTOP); } +enum SongSort +{ + SongSort_Randomize, + SongSort_MostPlays, + SongSort_FewestPlays, + SongSort_TopGrades, + SongSort_LowestGrades, + NUM_SongSort +}; +#define FOREACH_SongSort( i ) FOREACH_ENUM( SongSort, NUM_SongSort, i ) +const CString& SongSortToString( SongSort ss ); +const CString& SongSortToThemedString( SongSort ss ); + class CourseEntry { public: @@ -44,8 +57,9 @@ public: bool bNoDifficult; // if true, CourseDifficulty doesn't affect this entry int iLowMeter; // don't filter if -1 int iHighMeter; // don't filter if -1 - int iMostPopularIndex; // don't filter if -1 - int iLeastPopularIndex; // don't filter if -1 + + SongSort songSort; // sort by this after filtering + int iChooseIndex; // CString sModifiers; // set player and song options using these AttackArray attacks; // timed sModifiers @@ -61,8 +75,9 @@ public: bNoDifficult = false; iLowMeter = -1; iHighMeter = -1; - iMostPopularIndex = -1; - iLeastPopularIndex = -1; + + songSort = SongSort_Randomize; + iChooseIndex = 0; sModifiers = ""; fGainSeconds = 0; @@ -71,8 +86,7 @@ public: bool IsRandomSong() const { return - iMostPopularIndex == -1 && - iLeastPopularIndex == -1 && + iChooseIndex == -1 && pSong == NULL; } }; @@ -101,7 +115,7 @@ public: int m_iCustomMeter[NUM_DIFFICULTIES]; // -1 = no meter specified bool m_bSortByMeter; - vector m_entries; + vector m_vEntries; /* If PREFSMAN->m_bShowNative is off, these are the same as GetTranslit* below. * Otherwise, they return the main titles. */ @@ -124,7 +138,7 @@ public: bool HasMods() const; bool AllSongsAreFixed() const; - int GetEstimatedNumStages() const { return m_entries.size(); } + int GetEstimatedNumStages() const { return m_vEntries.size(); } bool IsPlayableIn( StepsType st ) const; bool CourseHasBestOrWorst() const; RageColor GetColor() const; diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index abbef92569..1b0c5e28a0 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -75,8 +75,7 @@ GameState::GameState() : m_stEdit( MESSAGE_EDIT_STEPS_TYPE_CHANGED ), m_pEditSourceSteps( MESSAGE_EDIT_SOURCE_STEPS_CHANGED ), m_stEditSource( MESSAGE_EDIT_SOURCE_STEPS_TYPE_CHANGED ), - m_iEditCourseEntryIndex(MESSAGE_EDIT_COURSE_ENTRY_INDEX_CHANGED ), - m_EditCourseEntryAction(MESSAGE_EDIT_COURSE_ENTRY_ACTION_CHANGED ) + m_iEditCourseEntryIndex(MESSAGE_EDIT_COURSE_ENTRY_INDEX_CHANGED ) { m_pCurStyle.Set( NULL ); @@ -255,7 +254,6 @@ void GameState::Reset() m_pEditSourceSteps.Set( NULL ); m_stEditSource.Set( STEPS_TYPE_INVALID ); m_iEditCourseEntryIndex.Set( -1 ); - m_EditCourseEntryAction.Set( ACTION_EDIT ); ApplyCmdline(); } diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index 8fda23edf9..225c8d4423 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -299,8 +299,6 @@ public: BroadcastOnChangePtr m_pEditSourceSteps; BroadcastOnChange m_stEditSource; BroadcastOnChange m_iEditCourseEntryIndex; - enum EditCourseEntryAction { ACTION_EDIT, ACTION_INSERT }; - BroadcastOnChange m_EditCourseEntryAction; // Workout stuff float GetGoalPercentComplete( PlayerNumber pn ); diff --git a/stepmania/src/LifeMeterTime.cpp b/stepmania/src/LifeMeterTime.cpp index d8c65bdffe..1dfffe0bbb 100644 --- a/stepmania/src/LifeMeterTime.cpp +++ b/stepmania/src/LifeMeterTime.cpp @@ -75,7 +75,7 @@ void LifeMeterTime::OnLoadSong() Course* pCourse = GAMESTATE->m_pCurCourse; ASSERT( pCourse ); - const CourseEntry *pEntry = &pCourse->m_entries[GAMESTATE->GetCourseSongIndex()]; + const CourseEntry *pEntry = &pCourse->m_vEntries[GAMESTATE->GetCourseSongIndex()]; m_fLifeTotalGainedSeconds += pEntry->fGainSeconds; if( GAMESTATE->GetCourseSongIndex() > 0 ) diff --git a/stepmania/src/MessageManager.cpp b/stepmania/src/MessageManager.cpp index 02076e1019..ff00041530 100644 --- a/stepmania/src/MessageManager.cpp +++ b/stepmania/src/MessageManager.cpp @@ -24,7 +24,6 @@ static const CString MessageNames[] = { "EditPreferredCourseDifficutyP1Changed", "EditPreferredCourseDifficutyP2Changed", "EditCourseEntryIndexChanged", - "EditCourseEntryActionChanged", "GoalCompleteP1", "GoalCompleteP2", "NoteCrossed", diff --git a/stepmania/src/MessageManager.h b/stepmania/src/MessageManager.h index 1096f7b1e1..a5b4c09f3d 100644 --- a/stepmania/src/MessageManager.h +++ b/stepmania/src/MessageManager.h @@ -32,7 +32,6 @@ enum Message MESSAGE_EDIT_PREFERRED_COURSE_DIFFICULTY_P1_CHANGED, MESSAGE_EDIT_PREFERRED_COURSE_DIFFICULTY_P2_CHANGED, MESSAGE_EDIT_COURSE_ENTRY_INDEX_CHANGED, - MESSAGE_EDIT_COURSE_ENTRY_ACTION_CHANGED, MESSAGE_GOAL_COMPLETE_P1, MESSAGE_GOAL_COMPLETE_P2, MESSAGE_NOTE_CROSSED, diff --git a/stepmania/src/MusicWheel.cpp b/stepmania/src/MusicWheel.cpp index 019305f289..c99af816c6 100644 --- a/stepmania/src/MusicWheel.cpp +++ b/stepmania/src/MusicWheel.cpp @@ -508,7 +508,7 @@ void MusicWheel::BuildWheelItemDatas( vector &arrayWheelItemDatas bUseSections = false; break; case SORT_TOP_GRADES: - SongUtil::SortSongPointerArrayByGrade( arraySongs ); + SongUtil::SortSongPointerArrayByGrades( arraySongs, true ); break; case SORT_ARTIST: SongUtil::SortSongPointerArrayByArtist( arraySongs ); diff --git a/stepmania/src/OptionRow.cpp b/stepmania/src/OptionRow.cpp index 2bb515fb25..27ab5b7355 100644 --- a/stepmania/src/OptionRow.cpp +++ b/stepmania/src/OptionRow.cpp @@ -691,6 +691,36 @@ void OptionRow::SetOneSharedSelection( int iChoice ) SetOneSelection( pn, iChoice ); } +int OptionRow::GetChoiceInRowWithFocus( PlayerNumber pn ) const +{ + if( m_RowDef.bOneChoiceForAllPlayers ) + pn = PLAYER_1; + if( m_RowDef.choices.empty() ) + return -1; + int iChoice = m_iChoiceInRowWithFocus[pn]; + return iChoice; +} + +int OptionRow::GetChoiceInRowWithFocusShared() const +{ + return GetChoiceInRowWithFocus( (PlayerNumber)0 ); +} + +void OptionRow::SetChoiceInRowWithFocus( PlayerNumber pn, int iChoice ) +{ + if( m_RowDef.bOneChoiceForAllPlayers ) + pn = PLAYER_1; + ASSERT(iChoice >= 0 && iChoice < (int)m_RowDef.choices.size()); + m_iChoiceInRowWithFocus[pn] = iChoice; +} + +void OptionRow::SetChoiceInRowWithFocusShared( int iChoice ) +{ + FOREACH_PlayerNumber( pn ) + SetChoiceInRowWithFocus( pn, iChoice ); +} + + void OptionRow::SetExitText( CString sExitText ) { BitmapText *bt = m_textItems.back(); diff --git a/stepmania/src/OptionRow.h b/stepmania/src/OptionRow.h index ef2da51639..b98b3b639c 100644 --- a/stepmania/src/OptionRow.h +++ b/stepmania/src/OptionRow.h @@ -107,22 +107,11 @@ public: void SetOneSelection( PlayerNumber pn, int iChoice ); void SetOneSharedSelection( int iChoice ); - int GetChoiceInRowWithFocus( PlayerNumber pn ) const - { - if( m_RowDef.bOneChoiceForAllPlayers ) - pn = PLAYER_1; - if( m_RowDef.choices.empty() ) - return -1; - int iChoice = m_iChoiceInRowWithFocus[pn]; - return iChoice; - } - void SetChoiceInRowWithFocus( PlayerNumber pn, int iChoice ) - { - if( m_RowDef.bOneChoiceForAllPlayers ) - pn = PLAYER_1; - ASSERT(iChoice >= 0 && iChoice < (int)m_RowDef.choices.size()); - m_iChoiceInRowWithFocus[pn] = iChoice; - } + int GetChoiceInRowWithFocus( PlayerNumber pn ) const; + int GetChoiceInRowWithFocusShared() const; + void SetChoiceInRowWithFocus( PlayerNumber pn, int iChoice ); + void SetChoiceInRowWithFocusShared( int iChoice ); + bool GetSelected( PlayerNumber pn, int iChoice ) const { if( m_RowDef.bOneChoiceForAllPlayers ) diff --git a/stepmania/src/ScoreDisplayLifeTime.cpp b/stepmania/src/ScoreDisplayLifeTime.cpp index 4b9cbdabdc..682b59b827 100644 --- a/stepmania/src/ScoreDisplayLifeTime.cpp +++ b/stepmania/src/ScoreDisplayLifeTime.cpp @@ -78,7 +78,7 @@ void ScoreDisplayLifeTime::OnLoadSong() Course* pCourse = GAMESTATE->m_pCurCourse; ASSERT( pCourse ); - const CourseEntry *pEntry = &pCourse->m_entries[GAMESTATE->GetCourseSongIndex()]; + const CourseEntry *pEntry = &pCourse->m_vEntries[GAMESTATE->GetCourseSongIndex()]; PlayGainLoss( GAIN_LIFE_COMMAND_NAME, pEntry->fGainSeconds ); } diff --git a/stepmania/src/ScreenCourseManager.cpp b/stepmania/src/ScreenCourseManager.cpp index 4e1a52cfe0..1b61d5a315 100644 --- a/stepmania/src/ScreenCourseManager.cpp +++ b/stepmania/src/ScreenCourseManager.cpp @@ -204,6 +204,7 @@ void ScreenCourseManager::GoToNextScreen() default: ASSERT(0); case ACTION_EDIT: + GAMESTATE->m_iEditCourseEntryIndex.Set( 0 ); SCREENMAN->SetNewScreen( "ScreenEditCourse" ); break; case ACTION_DELETE: diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index 8c7888825d..83e1988bb0 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -1390,9 +1390,9 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ const Course *crs = courses[i]; bool bUsesThisSong = false; - for( unsigned e = 0; e < crs->m_entries.size(); ++e ) + for( unsigned e = 0; e < crs->m_vEntries.size(); ++e ) { - if( crs->m_entries[e].pSong != m_pSong ) + if( crs->m_vEntries[e].pSong != m_pSong ) continue; bUsesThisSong = true; } @@ -2812,12 +2812,12 @@ void ScreenEdit::SetupCourseAttacks() m_pAttacksFromCourse->LoadFromCRSFile( m_pAttacksFromCourse->m_sPath ); AttackArray Attacks; - for( unsigned e = 0; e < m_pAttacksFromCourse->m_entries.size(); ++e ) + for( unsigned e = 0; e < m_pAttacksFromCourse->m_vEntries.size(); ++e ) { - if( m_pAttacksFromCourse->m_entries[e].pSong != m_pSong ) + if( m_pAttacksFromCourse->m_vEntries[e].pSong != m_pSong ) continue; - Attacks = m_pAttacksFromCourse->m_entries[e].attacks; + Attacks = m_pAttacksFromCourse->m_vEntries[e].attacks; break; } diff --git a/stepmania/src/ScreenEditCourse.cpp b/stepmania/src/ScreenEditCourse.cpp index c7b5ec8e7d..c980f32283 100644 --- a/stepmania/src/ScreenEditCourse.cpp +++ b/stepmania/src/ScreenEditCourse.cpp @@ -17,6 +17,7 @@ enum EditCourseRow ROW_TYPE_METER, ROW_EDIT_ENTRY, ROW_INSERT_ENTRY, + ROW_DELETE_ENTRY, ROW_DONE, }; @@ -56,14 +57,18 @@ void ScreenEditCourse::Init() { ScreenOptions::Init(); + + // save a backup that we'll use if we revert. + Course *pCourse = GAMESTATE->m_pCurCourse; + m_Original = *pCourse; + + vector vDefs; vector vHands; OptionRowDefinition def; def.layoutType = LAYOUT_SHOW_ONE_IN_ROW; - Course *pCourse = GAMESTATE->m_pCurCourse; - def.name = "Title"; def.choices.clear(); def.choices.push_back( pCourse->GetTranslitFullTitle() ); @@ -94,7 +99,6 @@ void ScreenEditCourse::Init() def.name = "Type"; def.choices.clear(); - FOREACH_CONST( StepsType, STEPS_TYPES_TO_SHOW.GetValue(), st ) def.choices.push_back( GAMEMAN->StepsTypeToString(*st) ); vDefs.push_back( def ); @@ -102,19 +106,36 @@ void ScreenEditCourse::Init() def.name = "Type Meter"; def.choices.clear(); - def.choices.push_back( "" ); + for( int i=MIN_METER; i<=MAX_METER; i++ ) + def.choices.push_back( ssprintf("%d",i) ); vDefs.push_back( def ); vHands.push_back( NULL ); def.name = "Edit Entry"; def.choices.clear(); - def.choices.push_back( "" ); + for( unsigned i=0; im_vEntries.size(); i++ ) + def.choices.push_back( ssprintf("%u of %u",i+1,pCourse->m_vEntries.size()) ); vDefs.push_back( def ); vHands.push_back( NULL ); def.name = "Insert Entry"; def.choices.clear(); - def.choices.push_back( "" ); + for( unsigned i=0; i<=pCourse->m_vEntries.size(); i++ ) + { + CString s; + if( i == pCourse->m_vEntries.size() ) + s = ssprintf("After %u",i); + else + s = ssprintf("Before %u",i+1); + def.choices.push_back( s ); + } + vDefs.push_back( def ); + vHands.push_back( NULL ); + + def.name = "Delete Entry"; + def.choices.clear(); + for( unsigned i=0; im_vEntries.size(); i++ ) + def.choices.push_back( ssprintf("%u of %u",i+1,pCourse->m_vEntries.size()) ); vDefs.push_back( def ); vHands.push_back( NULL ); @@ -131,6 +152,7 @@ void ScreenEditCourse::HandleScreenMessage( const ScreenMessage SM ) void ScreenEditCourse::AfterChangeValueInRow( PlayerNumber pn ) { ScreenOptions::AfterChangeValueInRow( pn ); + Course *pCourse = GAMESTATE->m_pCurCourse; StepsType st = STEPS_TYPE_INVALID; CourseDifficulty cd = DIFFICULTY_INVALID; @@ -174,48 +196,8 @@ void ScreenEditCourse::AfterChangeValueInRow( PlayerNumber pn ) OptionRow &row = *m_pRows[ROW_TYPE_METER]; OptionRowDefinition def = row.GetRowDef(); Trail *pTrail = GAMESTATE->m_pCurTrail[GAMESTATE->m_MasterPlayerNumber]; - def.choices.clear(); - if( pTrail != NULL ) - { - for( int i=MIN_METER; i<=MAX_METER; i++ ) - def.choices.push_back( ssprintf("%d",i) ); - row.SetOneSharedSelection( pTrail->GetMeter()-MIN_METER ); - } - else - { - def.choices.push_back( "N/A" ); - } - row.Reload( def ); - } - // refresh edit entry - { - OptionRow &row = *m_pRows[ROW_EDIT_ENTRY]; - OptionRowDefinition def = row.GetRowDef(); - def.choices.clear(); - Trail *pTrail = GAMESTATE->m_pCurTrail[GAMESTATE->m_MasterPlayerNumber]; ASSERT( pTrail ); - for( unsigned i=0; im_vEntries.size(); i++ ) - def.choices.push_back( ssprintf("%u of %u",i+1,pTrail->m_vEntries.size()) ); - row.SetOneSharedSelection( 0 ); - row.Reload( def ); - } - // refresh insert entry - { - OptionRow &row = *m_pRows[ROW_INSERT_ENTRY]; - OptionRowDefinition def = row.GetRowDef(); - def.choices.clear(); - Trail *pTrail = GAMESTATE->m_pCurTrail[GAMESTATE->m_MasterPlayerNumber]; - ASSERT( pTrail ); - for( unsigned i=0; i<=pTrail->m_vEntries.size(); i++ ) - { - CString s; - if( i == pTrail->m_vEntries.size() ) - s = ssprintf("After %u",i); - else - s = ssprintf("Before %u",i+1); - def.choices.push_back( s ); - } - row.SetOneSharedSelection( 0 ); + row.SetOneSharedSelection( pTrail->GetMeter()-MIN_METER ); row.Reload( def ); } // fall through @@ -228,8 +210,6 @@ void ScreenEditCourse::AfterChangeValueInRow( PlayerNumber pn ) } // fall through case ROW_EDIT_ENTRY: - // fall through - case ROW_INSERT_ENTRY: // export entry number { EditCourseRow ecr = m_iCurrentRow[GAMESTATE->m_MasterPlayerNumber] == ROW_EDIT_ENTRY ? ROW_EDIT_ENTRY : ROW_INSERT_ENTRY; @@ -238,14 +218,28 @@ void ScreenEditCourse::AfterChangeValueInRow( PlayerNumber pn ) GAMESTATE->m_iEditCourseEntryIndex.Set( iChoice ); } // fall through + case ROW_INSERT_ENTRY: + // fall through + case ROW_DELETE_ENTRY: + // fall through case ROW_DONE: break; } } -void ScreenEditCourse::ImportOptions( int row, const vector &vpns ) +void ScreenEditCourse::ImportOptions( int iRow, const vector &vpns ) { + Course *pCourse = GAMESTATE->m_pCurCourse; + switch( iRow ) + { + case ROW_EDIT_ENTRY: + case ROW_INSERT_ENTRY: + case ROW_DELETE_ENTRY: + OptionRow &row = *m_pRows[iRow]; + row.SetChoiceInRowWithFocusShared( GAMESTATE->m_iEditCourseEntryIndex ); + break; + } } void ScreenEditCourse::ExportOptions( int row, const vector &vpns ) @@ -265,6 +259,10 @@ void ScreenEditCourse::GoToNextScreen() case ROW_TYPE: case ROW_TYPE_METER: ASSERT(0); + case ROW_INSERT_ENTRY: + case ROW_DELETE_ENTRY: + SCREENMAN->SetNewScreen( "ScreenEditCourse" ); + break; case ROW_EDIT_ENTRY: SCREENMAN->SetNewScreen( "ScreenEditCourseEntry" ); break; @@ -276,11 +274,17 @@ void ScreenEditCourse::GoToNextScreen() void ScreenEditCourse::GoToPrevScreen() { + // revert + Course *pCourse = GAMESTATE->m_pCurCourse; + *pCourse = m_Original; + SCREENMAN->SetNewScreen( "ScreenCourseManager" ); } void ScreenEditCourse::ProcessMenuStart( PlayerNumber pn, const InputEventType type ) { + Course *pCourse = GAMESTATE->m_pCurCourse; + switch( m_iCurrentRow[GAMESTATE->m_MasterPlayerNumber] ) { default: @@ -293,16 +297,23 @@ void ScreenEditCourse::ProcessMenuStart( PlayerNumber pn, const InputEventType t case ROW_TYPE_METER: SCREENMAN->PlayInvalidSound(); break; - case ROW_EDIT_ENTRY: case ROW_INSERT_ENTRY: { - Trail *pTrail = GAMESTATE->m_pCurTrail[GAMESTATE->m_MasterPlayerNumber]; - if( pTrail == NULL ) - { - SCREENMAN->PlayInvalidSound(); - return; - } + OptionRow &row = *m_pRows[ROW_INSERT_ENTRY]; + int iChoice = row.GetChoiceInRowWithFocus( GAMESTATE->m_MasterPlayerNumber ); + pCourse->m_vEntries.insert( pCourse->m_vEntries.begin()+iChoice, CourseEntry() ); + ScreenOptions::BeginFadingOut(); } + break; + case ROW_DELETE_ENTRY: + { + OptionRow &row = *m_pRows[ROW_DELETE_ENTRY]; + int iChoice = row.GetChoiceInRowWithFocus( GAMESTATE->m_MasterPlayerNumber ); + pCourse->m_vEntries.erase( pCourse->m_vEntries.begin()+iChoice ); + ScreenOptions::BeginFadingOut(); + } + break; + case ROW_EDIT_ENTRY: case ROW_DONE: ScreenOptions::BeginFadingOut(); break; diff --git a/stepmania/src/ScreenEditCourse.h b/stepmania/src/ScreenEditCourse.h index 7f0e5409a5..1fd757c470 100644 --- a/stepmania/src/ScreenEditCourse.h +++ b/stepmania/src/ScreenEditCourse.h @@ -2,6 +2,7 @@ #define ScreenEditCourse_H #include "ScreenOptions.h" +#include "Course.h" class ScreenEditCourse : public ScreenOptions { @@ -21,6 +22,8 @@ protected: virtual void AfterChangeValueInRow( PlayerNumber pn ); virtual void ProcessMenuStart( PlayerNumber pn, const InputEventType type ); + + Course m_Original; }; #endif diff --git a/stepmania/src/ScreenEditCourseEntry.cpp b/stepmania/src/ScreenEditCourseEntry.cpp index 4e4b2d5872..4e7c463637 100644 --- a/stepmania/src/ScreenEditCourseEntry.cpp +++ b/stepmania/src/ScreenEditCourseEntry.cpp @@ -14,13 +14,15 @@ enum EditCourseEntryRow ROW_BASE_DIFFICULTY, ROW_LOW_METER, ROW_HIGH_METER, - ROW_BEST_WORST_VALUE, + ROW_SORT, + ROW_CHOOSE_INDEX, ROW_SET_MODS, ROW_DONE, NUM_EditCourseEntryRow }; #define FOREACH_EditCourseEntryRow( i ) FOREACH_ENUM( EditCourseEntryRow, NUM_EditCourseEntryRow, i ) + REGISTER_SCREEN_CLASS( ScreenEditCourseEntry ); ScreenEditCourseEntry::ScreenEditCourseEntry( CString sName ) : ScreenOptions( sName ) { @@ -31,6 +33,12 @@ void ScreenEditCourseEntry::Init() { ScreenOptions::Init(); + + // save a backup that we'll use if we revert. + Course *pCourse = GAMESTATE->m_pCurCourse; + m_Original = pCourse->m_vEntries[ GAMESTATE->m_iEditCourseEntryIndex ]; + + vector vDefs; vector vHands; @@ -41,6 +49,7 @@ void ScreenEditCourseEntry::Init() def.choices.clear(); vector vsSongGroups; SONGMAN->GetSongGroupNames( vsSongGroups ); + def.choices.push_back( "(any)" ); FOREACH_CONST( CString, vsSongGroups, s ) def.choices.push_back( *s ); vDefs.push_back( def ); @@ -54,6 +63,7 @@ void ScreenEditCourseEntry::Init() def.name = "Base Difficulty"; def.choices.clear(); + def.choices.push_back( "(any)" ); FOREACH_CONST( Difficulty, DIFFICULTIES_TO_SHOW.GetValue(), dc ) def.choices.push_back( DifficultyToThemedString(*dc) ); vDefs.push_back( def ); @@ -61,6 +71,7 @@ void ScreenEditCourseEntry::Init() def.name = "Low Meter"; def.choices.clear(); + def.choices.push_back( "(any)" ); for( int i=MIN_METER; i<=MAX_METER; i++ ) def.choices.push_back( ssprintf("%i",i) ); vDefs.push_back( def ); @@ -68,15 +79,23 @@ void ScreenEditCourseEntry::Init() def.name = "High Meter"; def.choices.clear(); + def.choices.push_back( "(any)" ); for( int i=MIN_METER; i<=MAX_METER; i++ ) def.choices.push_back( ssprintf("%i",i) ); vDefs.push_back( def ); vHands.push_back( NULL ); - def.name = "Best/Worst Value"; + def.name = "Sort"; def.choices.clear(); - for( int i=1; i<=20; i++ ) - def.choices.push_back( ssprintf("%i",i) ); + FOREACH_SongSort( i ) + def.choices.push_back( SongSortToThemedString(i) ); + vDefs.push_back( def ); + vHands.push_back( NULL ); + + def.name = "Choose"; + def.choices.clear(); + for( int i=0; i<20; i++ ) + def.choices.push_back( FormatNumberAndSuffix(i+1) ); vDefs.push_back( def ); vHands.push_back( NULL ); @@ -88,7 +107,7 @@ void ScreenEditCourseEntry::Init() ScreenOptions::InitMenu( INPUTMODE_SHARE_CURSOR, vDefs, vHands ); - AfterChangeValueInRow( GAMESTATE->m_MasterPlayerNumber ); + ImportAllOptions(); } void ScreenEditCourseEntry::HandleScreenMessage( const ScreenMessage SM ) @@ -100,8 +119,7 @@ void ScreenEditCourseEntry::AfterChangeValueInRow( PlayerNumber pn ) { ScreenOptions::AfterChangeValueInRow( pn ); Course *pCourse = GAMESTATE->m_pCurCourse; - CourseEntry &ce = pCourse->m_entries[ GAMESTATE->m_iEditCourseEntryIndex ]; - CString sSongGroup; + CourseEntry &ce = pCourse->m_vEntries[ GAMESTATE->m_iEditCourseEntryIndex ]; switch( m_iCurrentRow[pn] ) { @@ -110,22 +128,29 @@ void ScreenEditCourseEntry::AfterChangeValueInRow( PlayerNumber pn ) { OptionRow &row = *m_pRows[ROW_SONG_GROUP]; int iChoice = row.GetChoiceInRowWithFocus( GAMESTATE->m_MasterPlayerNumber ); - sSongGroup = row.GetRowDef().choices[ iChoice ]; + if( iChoice == 0 ) + ce.sSongGroup = ""; + else + ce.sSongGroup = row.GetRowDef().choices[ iChoice ]; } // refresh songs { OptionRow &row = *m_pRows[ROW_SONG]; OptionRowDefinition def = row.GetRowDef(); def.choices.clear(); + def.choices.push_back( "(any)" ); vector vpSongs; - SONGMAN->GetSongs( vpSongs, sSongGroup ); + if( ce.sSongGroup.empty() ) + SONGMAN->GetSongs( vpSongs ); + else + SONGMAN->GetSongs( vpSongs, ce.sSongGroup ); FOREACH_CONST( Song*, vpSongs, s ) def.choices.push_back( (*s)->GetTranslitFullTitle() ); vector::const_iterator iter = find( vpSongs.begin(), vpSongs.end(), ce.pSong ); if( iter != vpSongs.end() ) { int iSongIndex = iter - vpSongs.begin(); - row.SetOneSharedSelection( iSongIndex ); + row.SetOneSharedSelection( iSongIndex+1 ); } else { @@ -139,7 +164,10 @@ void ScreenEditCourseEntry::AfterChangeValueInRow( PlayerNumber pn ) { OptionRow &row = *m_pRows[ROW_SONG]; int iChoice = row.GetChoiceInRowWithFocus( GAMESTATE->m_MasterPlayerNumber ); - ce.pSong = SONGMAN->GetAllSongs()[iChoice]; + if( iChoice == 0 ) + ce.pSong = NULL; + else + ce.pSong = SONGMAN->GetAllSongs()[iChoice-1]; } // fall through case ROW_BASE_DIFFICULTY: @@ -153,16 +181,39 @@ void ScreenEditCourseEntry::AfterChangeValueInRow( PlayerNumber pn ) case ROW_LOW_METER: // export low meter { + OptionRow &row = *m_pRows[ROW_LOW_METER]; + int iChoice = row.GetChoiceInRowWithFocus( GAMESTATE->m_MasterPlayerNumber ); + if( iChoice == 0 ) + ce.iLowMeter = -1; + else + ce.iLowMeter = iChoice; } // fall through case ROW_HIGH_METER: // export high meter { + OptionRow &row = *m_pRows[ROW_HIGH_METER]; + int iChoice = row.GetChoiceInRowWithFocus( GAMESTATE->m_MasterPlayerNumber ); + if( iChoice == 0 ) + ce.iHighMeter = -1; + else + ce.iHighMeter = iChoice; } // fall through - case ROW_BEST_WORST_VALUE: - // export best/worst value + case ROW_SORT: + // export sort { + OptionRow &row = *m_pRows[ROW_SORT]; + int iChoice = row.GetChoiceInRowWithFocus( GAMESTATE->m_MasterPlayerNumber ); + ce.songSort = (SongSort)iChoice; + } + // fall through + case ROW_CHOOSE_INDEX: + // export choose index + { + OptionRow &row = *m_pRows[ROW_CHOOSE_INDEX]; + int iChoice = row.GetChoiceInRowWithFocus( GAMESTATE->m_MasterPlayerNumber ); + ce.iChooseIndex = iChoice; } // fall through case ROW_SET_MODS: @@ -172,33 +223,77 @@ void ScreenEditCourseEntry::AfterChangeValueInRow( PlayerNumber pn ) } } -void ScreenEditCourseEntry::ImportOptions( int row, const vector &vpns ) +void ScreenEditCourseEntry::ImportAllOptions() { - Course *pCourse = GAMESTATE->m_pCurCourse; - CourseEntry &ce = pCourse->m_entries[ GAMESTATE->m_iEditCourseEntryIndex ]; + // fill choices before importing + AfterChangeValueInRow( GAMESTATE->m_MasterPlayerNumber ); - // import entry song + + Course *pCourse = GAMESTATE->m_pCurCourse; + CourseEntry &ce = pCourse->m_vEntries[ GAMESTATE->m_iEditCourseEntryIndex ]; + + // import song group { - int iSongIndex = -1; - vector::const_iterator iter = find( SONGMAN->GetAllSongs().begin(), SONGMAN->GetAllSongs().end(), ce.pSong ); - if( iter != SONGMAN->GetAllSongs().end() ) - iSongIndex = iter - SONGMAN->GetAllSongs().begin(); + OptionRow &row = *m_pRows[ROW_SONG_GROUP]; + FOREACH_CONST( CString, row.GetRowDef().choices, s ) + { + if( *s == ce.sSongGroup ) + { + int iChoice = s - row.GetRowDef().choices.begin(); + row.SetOneSharedSelection( iChoice ); + AfterChangeValueInRow( GAMESTATE->m_MasterPlayerNumber ); + break; + } + } + } + // import song + { + vector vpSongs; + SONGMAN->GetSongs( vpSongs, ce.sSongGroup ); + vector::const_iterator iter = find( vpSongs.begin(), vpSongs.end(), ce.pSong ); + int iChoice = 0; + if( iter != vpSongs.end() ) + iChoice = iter - vpSongs.begin() + 1; OptionRow &row = *m_pRows[ROW_SONG]; - if( iSongIndex != -1 ) - row.SetOneSharedSelection( iSongIndex ); + row.SetOneSharedSelection( iChoice ); } - /* - // import entry difficulty + // import base difficulty { - int iDifficultyIndex = -1; - vector::const_iterator iter = find( DIFFICULTIES_TO_SHOW.GetValue().begin(), DIFFICULTIES_TO_SHOW.GetValue().end(), ce.difficulty ); + vector::const_iterator iter = find( DIFFICULTIES_TO_SHOW.GetValue().begin(), DIFFICULTIES_TO_SHOW.GetValue().end(), ce.baseDifficulty ); + int iChoice = 0; if( iter != DIFFICULTIES_TO_SHOW.GetValue().end() ) - iDifficultyIndex = iter - DIFFICULTIES_TO_SHOW.GetValue().begin(); - OptionRow &row = *m_pRows[ROW_DIFFICULTY]; - if( iDifficultyIndex != -1 ) - row.SetOneSharedSelection( iDifficultyIndex ); + iChoice = iter - DIFFICULTIES_TO_SHOW.GetValue().begin() + 1; + OptionRow &row = *m_pRows[ROW_BASE_DIFFICULTY]; + row.SetOneSharedSelection( iChoice ); + } + // import low meter + { + int iChoice = 0; + if( ce.iLowMeter != -1 ) + iChoice = ce.iLowMeter; + OptionRow &row = *m_pRows[ROW_LOW_METER]; + row.SetOneSharedSelection( iChoice ); + } + // import high meter + { + int iChoice = 0; + if( ce.iHighMeter != -1 ) + iChoice = ce.iHighMeter; + OptionRow &row = *m_pRows[ROW_HIGH_METER]; + row.SetOneSharedSelection( iChoice ); + } + // import sort + { + int iChoice = ce.songSort; + OptionRow &row = *m_pRows[ROW_SORT]; + row.SetOneSharedSelection( iChoice ); + } + // import choose index + { + int iChoice = ce.iChooseIndex; + OptionRow &row = *m_pRows[ROW_CHOOSE_INDEX]; + row.SetOneSharedSelection( iChoice ); } - */ } void ScreenEditCourseEntry::ExportOptions( int row, const vector &vpns ) @@ -215,7 +310,7 @@ void ScreenEditCourseEntry::GoToNextScreen() case ROW_BASE_DIFFICULTY: case ROW_LOW_METER: case ROW_HIGH_METER: - case ROW_BEST_WORST_VALUE: + case ROW_CHOOSE_INDEX: break; case ROW_SET_MODS: SCREENMAN->SetNewScreen( "ScreenEditCourseMods" ); @@ -228,6 +323,10 @@ void ScreenEditCourseEntry::GoToNextScreen() void ScreenEditCourseEntry::GoToPrevScreen() { + // revert + Course *pCourse = GAMESTATE->m_pCurCourse; + pCourse->m_vEntries[ GAMESTATE->m_iEditCourseEntryIndex ] = m_Original; + SCREENMAN->SetNewScreen( "ScreenEditCourse" ); } @@ -240,7 +339,8 @@ void ScreenEditCourseEntry::ProcessMenuStart( PlayerNumber pn, const InputEventT case ROW_BASE_DIFFICULTY: case ROW_LOW_METER: case ROW_HIGH_METER: - case ROW_BEST_WORST_VALUE: + case ROW_SORT: + case ROW_CHOOSE_INDEX: break; case ROW_SET_MODS: case ROW_DONE: diff --git a/stepmania/src/ScreenEditCourseEntry.h b/stepmania/src/ScreenEditCourseEntry.h index 5b7e4f7300..6e4b3b5b83 100644 --- a/stepmania/src/ScreenEditCourseEntry.h +++ b/stepmania/src/ScreenEditCourseEntry.h @@ -2,6 +2,7 @@ #define ScreenEditCourseEntry_H #include "ScreenOptions.h" +#include "Course.h" class ScreenEditCourseEntry : public ScreenOptions { @@ -13,7 +14,7 @@ public: virtual void HandleScreenMessage( const ScreenMessage SM ); protected: - virtual void ImportOptions( int row, const vector &vpns ); + virtual void ImportOptions( int row, const vector &vpns ) {} virtual void ExportOptions( int row, const vector &vpns ); virtual void GoToNextScreen(); @@ -21,6 +22,10 @@ protected: virtual void AfterChangeValueInRow( PlayerNumber pn ); virtual void ProcessMenuStart( PlayerNumber pn, const InputEventType type ); + + void ImportAllOptions(); + + CourseEntry m_Original; }; #endif diff --git a/stepmania/src/ScreenJukebox.cpp b/stepmania/src/ScreenJukebox.cpp index 4a033adce4..adbf9653fb 100644 --- a/stepmania/src/ScreenJukebox.cpp +++ b/stepmania/src/ScreenJukebox.cpp @@ -34,8 +34,8 @@ void ScreenJukebox::SetSong() //then we pick a song from this course. Course *pCourse = SONGMAN->GetCourseFromName( THEME->GetCurThemeName() ); if( pCourse != NULL ) - for ( unsigned i = 0; i < pCourse->m_entries.size(); i++ ) - vSongs.push_back( pCourse->m_entries[i].pSong ); + for ( unsigned i = 0; i < pCourse->m_vEntries.size(); i++ ) + vSongs.push_back( pCourse->m_vEntries[i].pSong ); if ( vSongs.size() == 0 ) SONGMAN->GetSongs( vSongs, GAMESTATE->m_sPreferredSongGroup ); diff --git a/stepmania/src/SongUtil.cpp b/stepmania/src/SongUtil.cpp index 6b425ea01a..ccc0b6f867 100644 --- a/stepmania/src/SongUtil.cpp +++ b/stepmania/src/SongUtil.cpp @@ -107,8 +107,10 @@ void AppendOctal( int n, int digits, CString &out ) bool CompDescending( const pair &a, const pair &b ) { return a.second > b.second; } +bool CompAscending( const pair &a, const pair &b ) +{ return a.second < b.second; } -void SongUtil::SortSongPointerArrayByGrade( vector &vpSongsInOut ) +void SongUtil::SortSongPointerArrayByGrades( vector &vpSongsInOut, bool bDescending ) { /* Optimize by pre-writing a string to compare, since doing GetNumNotesWithGrade * inside the sort is too slow. */ @@ -130,7 +132,7 @@ void SongUtil::SortSongPointerArrayByGrade( vector &vpSongsInOut ) vals.push_back( val(pSong, foo) ); } - sort( vals.begin(), vals.end(), CompDescending ); + sort( vals.begin(), vals.end(), bDescending ? CompDescending : CompAscending ); for( unsigned i = 0; i < vpSongsInOut.size(); ++i ) vpSongsInOut[i] = vals[i].first; diff --git a/stepmania/src/SongUtil.h b/stepmania/src/SongUtil.h index 0454aa8833..954b76ed92 100644 --- a/stepmania/src/SongUtil.h +++ b/stepmania/src/SongUtil.h @@ -15,7 +15,7 @@ namespace SongUtil CString MakeSortString( CString s ); void SortSongPointerArrayByTitle( vector &vpSongsInOut ); void SortSongPointerArrayByBPM( vector &vpSongsInOut ); - void SortSongPointerArrayByGrade( vector &vpSongsInOut ); + void SortSongPointerArrayByGrades( vector &vpSongsInOut, bool bDescending ); void SortSongPointerArrayByArtist( vector &vpSongsInOut ); void SortSongPointerArrayByDisplayArtist( vector &vpSongsInOut ); void SortSongPointerArrayByGenre( vector &vpSongsInOut );