move Steps searching out of song into SongUtil so that it can be shared with CourseEntry

This commit is contained in:
Chris Danford
2006-06-13 01:10:37 +00:00
parent acdf036e05
commit af3e1c571c
30 changed files with 464 additions and 378 deletions
+2 -2
View File
@@ -99,7 +99,7 @@ void CatalogXml::Save( LoadingWindow *loading_window )
iNumSongsInGroup++;
FOREACH_CONST( Difficulty, CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue(), dc )
{
Steps* pSteps = pSong->GetStepsByDifficulty( *st, *dc, false ); // no autogen
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, *st, *dc, false ); // no autogen
/*
* There is no point in storing the steps if either there
@@ -193,7 +193,7 @@ void CatalogXml::Save( LoadingWindow *loading_window )
{
FOREACH_CONST( Difficulty, CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue(), dc )
{
Steps* pSteps = pSong->GetStepsByDifficulty( *st, *dc, false ); // no autogen
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, *st, *dc, false ); // no autogen
if( pSteps == NULL )
continue; // skip
if( UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
+4 -8
View File
@@ -11,6 +11,8 @@
#include <set>
#include "EnumHelper.h"
#include "RageTypes.h"
#include "SongUtil.h"
#include "StepsUtil.h"
class PlayerOptions;
class SongOptions;
@@ -59,11 +61,9 @@ public:
// filter criteria, applied from top to bottom
// TODO: change this to be a SongID
Song* pSong; // don't filter if NULL
RString sSongGroup; // don't filter if empty
Difficulty baseDifficulty; // don't filter if DIFFICULTY_INVALID
SongCriteria songCriteria;
StepsCriteria stepsCriteria;
bool bNoDifficult; // if true, CourseDifficulty doesn't affect this entry
int iLowMeter; // don't filter if -1
int iHighMeter; // don't filter if -1
SongSort songSort; // sort by this after filtering
int iChooseIndex; //
@@ -77,11 +77,7 @@ public:
bSecret = false;
pSong = NULL;
sSongGroup = "";
baseDifficulty = DIFFICULTY_INVALID;
bNoDifficult = false;
iLowMeter = -1;
iHighMeter = -1;
songSort = SongSort_Randomize;
iChooseIndex = 0;
+2 -2
View File
@@ -129,8 +129,8 @@ void CourseEntryDisplay::SetFromGameState( int iCourseEntryIndex )
if( te == NULL || ce == NULL )
continue;
int iLow = ce->iLowMeter;
int iHigh = ce->iHighMeter;
int iLow = ce->stepsCriteria.m_iLowMeter;
int iHigh = ce->stepsCriteria.m_iHighMeter;
bool bLowIsSet = iLow != -1;
bool bHighIsSet = iHigh != -1;
+5 -5
View File
@@ -192,7 +192,7 @@ void CourseUtil::SortByMostRecentlyPlayedForMachine( vector<Course*> &vpCoursesI
void CourseUtil::MakeDefaultEditCourseEntry( CourseEntry& out )
{
out.pSong = GAMESTATE->GetDefaultSong();
out.baseDifficulty = DIFFICULTY_MEDIUM;
out.stepsCriteria.m_difficulty = DIFFICULTY_MEDIUM;
}
//////////////////////////////////
@@ -223,12 +223,12 @@ 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.sSongGroup = sGroupName;
e.baseDifficulty = diff;
e.songCriteria.m_sGroupName = sGroupName;
e.stepsCriteria.m_difficulty = diff;
e.bSecret = true;
vector<Song*> vSongs;
SONGMAN->GetSongs( vSongs, e.sSongGroup );
SONGMAN->GetSongs( vSongs, e.songCriteria.m_sGroupName );
for( unsigned i = 0; i < vSongs.size(); ++i)
out.m_vEntries.push_back( e );
}
@@ -283,7 +283,7 @@ void CourseUtil::AutogenOniFromArtist( const RString &sArtistName, RString sArti
aSongs.erase( aSongs.begin()+4, aSongs.end() );
CourseEntry e;
e.baseDifficulty = dc;
e.stepsCriteria.m_difficulty = dc;
for( unsigned i = 0; i < aSongs.size(); ++i )
{
+8 -8
View File
@@ -105,13 +105,13 @@ bool CourseWriterCRS::Write( const Course &course, RageFileBasic &f, bool bSavin
const RString &sSong = Basename( entry.pSong->GetSongDir() );
f.Write( "#SONG:" );
if( !entry.sSongGroup.empty() )
f.Write( entry.sSongGroup + '/' );
if( !entry.songCriteria.m_sGroupName.empty() )
f.Write( entry.songCriteria.m_sGroupName + '/' );
f.Write( sSong );
}
else if( !entry.sSongGroup.empty() )
else if( !entry.songCriteria.m_sGroupName.empty() )
{
f.Write( ssprintf( "#SONG:%s/*", entry.sSongGroup.c_str() ) );
f.Write( ssprintf( "#SONG:%s/*", entry.songCriteria.m_sGroupName.c_str() ) );
}
else
{
@@ -119,10 +119,10 @@ bool CourseWriterCRS::Write( const Course &course, RageFileBasic &f, bool bSavin
}
f.Write( ":" );
if( entry.baseDifficulty != DIFFICULTY_INVALID )
f.Write( DifficultyToString(entry.baseDifficulty) );
else if( entry.iLowMeter != -1 && entry.iHighMeter != -1 )
f.Write( ssprintf( "%d..%d", entry.iLowMeter, entry.iHighMeter ) );
if( entry.stepsCriteria.m_difficulty != DIFFICULTY_INVALID )
f.Write( DifficultyToString(entry.stepsCriteria.m_difficulty) );
else if( entry.stepsCriteria.m_iLowMeter != -1 && entry.stepsCriteria.m_iHighMeter != -1 )
f.Write( ssprintf( "%d..%d", entry.stepsCriteria.m_iLowMeter, entry.stepsCriteria.m_iHighMeter ) );
f.Write( ":" );
RString sModifiers = entry.sModifiers;
+2 -1
View File
@@ -13,6 +13,7 @@
#include "CommonMetrics.h"
#include "Command.h"
#include "Foreach.h"
#include "SongUtil.h"
#define MAX_METERS NUM_Difficulty + MAX_EDITS_PER_SONG
@@ -276,7 +277,7 @@ void DifficultyList::SetFromGameState()
else
{
vector<Steps*> CurSteps;
pSong->GetSteps( CurSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
SongUtil::GetSteps( pSong, CurSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
/* Should match the sort in ScreenSelectMusic::AfterMusicChange. */
StepsUtil::RemoveLockedSteps( pSong, CurSteps );
+4 -4
View File
@@ -409,7 +409,7 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
case EditMode_Practice:
{
vector<Steps*> v;
GetSelectedSong()->GetSteps( v, GetSelectedStepsType(), DIFFICULTY_EDIT );
SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedStepsType(), DIFFICULTY_EDIT );
StepsUtil::SortStepsByDescription( v );
FOREACH_CONST( Steps*, v, p )
m_vpSteps.push_back( StepsAndDifficulty(*p,dc) );
@@ -437,7 +437,7 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
}
else
{
Steps *pSteps = GetSelectedSong()->GetStepsByDifficulty( GetSelectedStepsType(), dc );
Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedStepsType(), dc );
if( pSteps && UNLOCKMAN->StepsIsLocked( GetSelectedSong(), pSteps ) )
pSteps = NULL;
@@ -512,14 +512,14 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
// fill in m_vpSourceSteps
if( dc != DIFFICULTY_EDIT )
{
Steps *pSteps = GetSelectedSong()->GetStepsByDifficulty( GetSelectedSourceStepsType(), dc );
Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedSourceStepsType(), dc );
if( pSteps != NULL )
m_vpSourceSteps.push_back( StepsAndDifficulty(pSteps,dc) );
}
else
{
vector<Steps*> v;
GetSelectedSong()->GetSteps( v, GetSelectedSourceStepsType(), dc );
SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedSourceStepsType(), dc );
StepsUtil::SortStepsByDescription( v );
FOREACH_CONST( Steps*, v, pSteps )
m_vpSourceSteps.push_back( StepsAndDifficulty(*pSteps,dc) );
+2 -2
View File
@@ -254,9 +254,9 @@ void GameCommand::LoadOne( const Command& cmd )
Difficulty dc = StringToDifficulty( sSteps );
if( dc != DIFFICULTY_EDIT )
m_pSteps = pSong->GetStepsByDifficulty( pStyle->m_StepsType, dc );
m_pSteps = SongUtil::GetStepsByDifficulty( pSong, pStyle->m_StepsType, dc );
else
m_pSteps = pSong->GetStepsByDescription( pStyle->m_StepsType, sSteps );
m_pSteps = SongUtil::GetStepsByDescription( pSong, pStyle->m_StepsType, sSteps );
if( m_pSteps == NULL )
{
m_sInvalidReason = "steps not found";
+2 -1
View File
@@ -14,6 +14,7 @@
#include "song.h"
#include "Steps.h"
#include "LightsManager.h"
#include "SongUtil.h"
GameSoundManager *SOUND = NULL;
@@ -142,7 +143,7 @@ static void StartMusic( MusicToPlay &ToPlay )
ToPlay.HasTiming = true;
ToPlay.timing_data = song.m_Timing;
// get cabinet lights if any
Steps *pStepsCabinetLights = song.GetOneSteps( STEPS_TYPE_LIGHTS_CABINET );
Steps *pStepsCabinetLights = SongUtil::GetOneSteps( &song, STEPS_TYPE_LIGHTS_CABINET );
if( pStepsCabinetLights )
pStepsCabinetLights->GetNoteData( ToPlay.lights_data );
}
-8
View File
@@ -1222,14 +1222,6 @@ bool GameState::ShowW1() const
}
}
struct SongAndSteps
{
Song* pSong;
Steps* pSteps;
bool operator==( const SongAndSteps& other ) const { return pSong==other.pSong && pSteps==other.pSteps; }
bool operator<( const SongAndSteps& other ) const { return pSong<=other.pSong && pSteps<=other.pSteps; }
};
void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOut ) const
{
if( !IsHumanPlayer(pn) )
+2 -1
View File
@@ -21,6 +21,7 @@ TODO:
#include "song.h"
#include "Steps.h"
#include "ActorUtil.h"
#include "SongUtil.h"
#define BANNERSPACING THEME->GetMetricI("ScreenEz2SelectMusic","BannerSpacing")
#define MAXSONGSINBUFFER 5
@@ -68,7 +69,7 @@ MusicBannerWheel::MusicBannerWheel()
for ( unsigned i = 0; i < arraySongs.size(); i++)
{
//ONLY get non-autogenned steps
Steps* pSteps = arraySongs[i]->GetStepsByDifficulty( GAMESTATE->GetCurrentStyle()->m_StepsType, DIFFICULTY_INVALID, false );
Steps* pSteps = SongUtil::GetStepsByDifficulty( arraySongs[i], GAMESTATE->GetCurrentStyle()->m_StepsType, DIFFICULTY_INVALID, false );
if ( pSteps != NULL )
pNotAutogen.push_back( arraySongs[i] );
}
+2 -1
View File
@@ -6,6 +6,7 @@
#include "GameManager.h"
#include "RageException.h"
#include "RageFile.h"
#include "SongUtil.h"
#include "StepsUtil.h"
#include "song.h"
#include "Steps.h"
@@ -997,7 +998,7 @@ void BMSLoader::SlideDuplicateDifficulties( Song &p )
continue;
vector<Steps*> vSteps;
p.GetSteps( vSteps, st, dc );
SongUtil::GetSteps( &p, vSteps, st, dc );
StepsUtil::SortNotesArrayByDifficulty( vSteps );
for( unsigned k=1; k<vSteps.size(); k++ )
+2 -2
View File
@@ -672,10 +672,10 @@ void ProfileManager::GetHighScoreForDifficulty( const Song *s, const Style *st,
{
// return max grade of notes in difficulty class
vector<Steps*> aNotes;
s->GetSteps( aNotes, st->m_StepsType );
SongUtil::GetSteps( s, aNotes, st->m_StepsType );
StepsUtil::SortNotesArrayByDifficulty( aNotes );
const Steps* pSteps = s->GetStepsByDifficulty( st->m_StepsType, dc );
const Steps* pSteps = SongUtil::GetStepsByDifficulty( s, st->m_StepsType, dc );
if( pSteps && PROFILEMAN->IsPersistentProfile(slot) )
hsOut = PROFILEMAN->GetProfile(slot)->GetStepsHighScoreList(s,pSteps).GetTopScore();
+2 -2
View File
@@ -978,7 +978,7 @@ void ScreenEdit::UpdateTextInfo()
m_bTextInfoNeedsUpdate = false;
RString sNoteType = NoteTypeToLocalizedString(m_SnapDisplay.GetNoteType()) + " notes";
RString sNoteType = NoteTypeToLocalizedString(m_SnapDisplay.GetNoteType());
RString sText;
sText += ssprintf( "%s:\n %.3f\n", CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_fSongBeat );
@@ -1379,7 +1379,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
// Get all Steps of this StepsType
StepsType st = pSteps->m_StepsType;
vector<Steps*> vSteps;
GAMESTATE->m_pCurSong->GetSteps( vSteps, st );
SongUtil::GetSteps( GAMESTATE->m_pCurSong, vSteps, st );
// Sort them by difficulty.
StepsUtil::SortStepsByTypeAndDifficulty( vSteps );
+2 -1
View File
@@ -14,6 +14,7 @@
#include "ActorUtil.h"
#include "AnnouncerManager.h"
#include "MenuTimer.h"
#include "SongUtil.h"
#include "StepsUtil.h"
#include "ScreenDimensions.h"
#include "ScreenPrompt.h"
@@ -640,7 +641,7 @@ void ScreenEz2SelectMusic::MusicChanged()
for( pn = 0; pn < NUM_PLAYERS; ++pn)
{
pSong->GetSteps( m_arrayNotes[pn], GAMESTATE->GetCurrentStyle()->m_StepsType );
SongUtil::GetSteps( pSong, m_arrayNotes[pn], GAMESTATE->GetCurrentStyle()->m_StepsType );
StepsUtil::SortNotesArrayByDifficulty( m_arrayNotes[pn] );
}
+4 -3
View File
@@ -53,6 +53,7 @@
#include "Foreground.h"
#include "ScreenSaveSync.h"
#include "AdjustSync.h"
#include "SongUtil.h"
//
// Defines
@@ -1295,7 +1296,7 @@ void ScreenGameplay::LoadLights()
m_CabinetLightsNoteData.Init();
ASSERT( GAMESTATE->m_pCurSong );
const Steps *pSteps = GAMESTATE->m_pCurSong->GetClosestNotes( STEPS_TYPE_LIGHTS_CABINET, DIFFICULTY_MEDIUM );
const Steps *pSteps = SongUtil::GetClosestNotes( GAMESTATE->m_pCurSong, STEPS_TYPE_LIGHTS_CABINET, DIFFICULTY_MEDIUM );
if( pSteps != NULL )
{
pSteps->GetNoteData( m_CabinetLightsNoteData );
@@ -1312,7 +1313,7 @@ void ScreenGameplay::LoadLights()
Difficulty d1 = DIFFICULTY_INVALID;
if( asDifficulties.size() > 0 )
d1 = StringToDifficulty( asDifficulties[0] );
pSteps = GAMESTATE->m_pCurSong->GetClosestNotes( GAMESTATE->GetCurrentStyle()->m_StepsType, d1 );
pSteps = SongUtil::GetClosestNotes( GAMESTATE->m_pCurSong, GAMESTATE->GetCurrentStyle()->m_StepsType, d1 );
// If we can't find anything at all, stop.
if( pSteps == NULL )
@@ -1324,7 +1325,7 @@ void ScreenGameplay::LoadLights()
if( asDifficulties.size() > 1 )
{
Difficulty d2 = StringToDifficulty( asDifficulties[1] );
const Steps *pSteps2 = GAMESTATE->m_pCurSong->GetClosestNotes( GAMESTATE->GetCurrentStyle()->m_StepsType, d2 );
const Steps *pSteps2 = SongUtil::GetClosestNotes( GAMESTATE->m_pCurSong, GAMESTATE->GetCurrentStyle()->m_StepsType, d2 );
if( pSteps != NULL && pSteps2 != NULL && pSteps != pSteps2 )
{
NoteData TapNoteData2;
+2 -1
View File
@@ -7,6 +7,7 @@
#include "AdjustSync.h"
#include "ScreenDimensions.h"
#include "InputEventPlus.h"
#include "SongUtil.h"
REGISTER_SCREEN_CLASS( ScreenGameplaySyncMachine );
@@ -23,7 +24,7 @@ void ScreenGameplaySyncMachine::Init()
m_Song.TidyUpData();
GAMESTATE->m_pCurSong.Set( &m_Song );
Steps *pSteps = m_Song.GetOneSteps();
Steps *pSteps = SongUtil::GetOneSteps( &m_Song );
ASSERT( pSteps );
GAMESTATE->m_pCurSteps[0].Set( pSteps );
+2 -1
View File
@@ -19,6 +19,7 @@
#include "PrefsManager.h"
#include "CharacterManager.h"
#include "StatsManager.h"
#include "SongUtil.h"
static const ThemeMetric<RString> STEPFILE ("ScreenHowToPlay","Stepfile");
static const ThemeMetric<int> NUM_W2S ("ScreenHowToPlay","NumW2s");
@@ -142,7 +143,7 @@ void ScreenHowToPlay::Init()
const Style* pStyle = GAMESTATE->GetCurrentStyle();
Steps *pSteps = m_Song.GetStepsByDescription( pStyle->m_StepsType, "" );
Steps *pSteps = SongUtil::GetStepsByDescription( &m_Song, pStyle->m_StepsType, "" );
ASSERT_M( pSteps != NULL, ssprintf("%i", pStyle->m_StepsType) );
NoteData tempNoteData;
+2 -1
View File
@@ -20,6 +20,7 @@
#include "PrefsManager.h"
#include "InputEventPlus.h"
#include "AdjustSync.h"
#include "SongUtil.h"
#define SHOW_COURSE_MODIFIERS_PROBABILITY THEME->GetMetricF(m_sName,"ShowCourseModifiersProbability")
@@ -85,7 +86,7 @@ void ScreenJukebox::SetSong()
continue; // skip
Difficulty dc = vDifficultiesToShow[ rand()%vDifficultiesToShow.size() ];
Steps* pSteps = pSong->GetStepsByDifficulty( GAMESTATE->GetCurrentStyle()->m_StepsType, dc );
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, dc );
if( pSteps == NULL )
continue; // skip
+23 -22
View File
@@ -10,6 +10,7 @@
#include "Steps.h"
#include "OptionRowHandler.h"
#include "PlayerState.h"
#include "SongUtil.h"
enum EditCourseEntryRow
{
@@ -208,7 +209,7 @@ void ScreenOptionsEditCourseEntry::BeginScreen()
const CourseEntry &ce = pCourse->m_vEntries[ GAMESTATE->m_iEditCourseEntryIndex ];
m_Original = ce;
m_pSongHandler->m_sSongGroup = ce.sSongGroup;
m_pSongHandler->m_sSongGroup = ce.songCriteria.m_sGroupName;
if( SHOW_MODS_ROW )
m_pModChangesHandler->m_Def.m_vsChoices[0] = ssprintf( "%d mod changes", ce.GetNumModChanges() );
@@ -241,8 +242,8 @@ void ScreenOptionsEditCourseEntry::HandleScreenMessage( const ScreenMessage SM )
Song *pSong = ce.pSong;
Steps *pSteps;
StepsType st = GAMESTATE->m_stEdit;
CourseDifficulty cd = ( ce.baseDifficulty == DIFFICULTY_INVALID ?
GAMESTATE->m_cdEdit : ce.baseDifficulty );
CourseDifficulty cd = ( ce.stepsCriteria.m_difficulty == DIFFICULTY_INVALID ?
GAMESTATE->m_cdEdit : ce.stepsCriteria.m_difficulty );
if( pSong == NULL )
pSong = m_pLongSong;
@@ -273,13 +274,13 @@ void ScreenOptionsEditCourseEntry::HandleScreenMessage( const ScreenMessage SM )
}
// Try to find steps first using st and cd, then st, then cd, then any.
pSteps = pSong->GetStepsByDifficulty( st, cd, false );
pSteps = SongUtil::GetStepsByDifficulty( pSong, st, cd, false );
if( !pSteps )
pSteps = pSong->GetStepsByDifficulty( st, DIFFICULTY_INVALID, false );
pSteps = SongUtil::GetStepsByDifficulty( pSong, st, DIFFICULTY_INVALID, false );
if( !pSteps )
pSteps = pSong->GetStepsByDifficulty( STEPS_TYPE_INVALID, cd, false );
pSteps = SongUtil::GetStepsByDifficulty( pSong, STEPS_TYPE_INVALID, cd, false );
if( !pSteps )
pSteps = pSong->GetStepsByDifficulty( STEPS_TYPE_INVALID, DIFFICULTY_INVALID, false );
pSteps = SongUtil::GetStepsByDifficulty( pSong, STEPS_TYPE_INVALID, DIFFICULTY_INVALID, false );
ASSERT( pSteps );
// Set up for ScreenEdit
@@ -340,7 +341,7 @@ void ScreenOptionsEditCourseEntry::AfterChangeValueInRow( int iRow, PlayerNumber
vpns.push_back( pn );
ExportOptions( ROW_SONG_GROUP, vpns );
m_pSongHandler->m_sSongGroup = ce.sSongGroup;
m_pSongHandler->m_sSongGroup = ce.songCriteria.m_sGroupName;
OptionRow &row = *m_pRows[ROW_SONG];
row.Reload();
@@ -371,7 +372,7 @@ void ScreenOptionsEditCourseEntry::ImportOptions( int iRow, const vector<PlayerN
case ROW_SONG_GROUP:
FOREACH_CONST( RString, row.GetRowDef().m_vsChoices, s )
{
if( *s == ce.sSongGroup )
if( *s == ce.songCriteria.m_sGroupName )
{
int iChoice = s - row.GetRowDef().m_vsChoices.begin();
row.SetOneSharedSelection( iChoice );
@@ -393,7 +394,7 @@ void ScreenOptionsEditCourseEntry::ImportOptions( int iRow, const vector<PlayerN
}
case ROW_BASE_DIFFICULTY:
{
vector<Difficulty>::const_iterator iter = find( CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().begin(), CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().end(), ce.baseDifficulty );
vector<Difficulty>::const_iterator iter = find( CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().begin(), CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().end(), ce.stepsCriteria.m_difficulty );
int iChoice = 0;
if( iter != CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().end() )
iChoice = iter - CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().begin() + 1;
@@ -404,8 +405,8 @@ void ScreenOptionsEditCourseEntry::ImportOptions( int iRow, const vector<PlayerN
case ROW_LOW_METER:
{
int iChoice = 0;
if( ce.iLowMeter != -1 )
iChoice = ce.iLowMeter;
if( ce.stepsCriteria.m_iLowMeter != -1 )
iChoice = ce.stepsCriteria.m_iLowMeter;
OptionRow &row = *m_pRows[ROW_LOW_METER];
row.SetOneSharedSelection( iChoice );
break;
@@ -413,8 +414,8 @@ void ScreenOptionsEditCourseEntry::ImportOptions( int iRow, const vector<PlayerN
case ROW_HIGH_METER:
{
int iChoice = 0;
if( ce.iHighMeter != -1 )
iChoice = ce.iHighMeter;
if( ce.stepsCriteria.m_iHighMeter != -1 )
iChoice = ce.stepsCriteria.m_iHighMeter;
OptionRow &row = *m_pRows[ROW_HIGH_METER];
row.SetOneSharedSelection( iChoice );
break;
@@ -453,9 +454,9 @@ void ScreenOptionsEditCourseEntry::ExportOptions( int iRow, const vector<PlayerN
case ROW_SONG_GROUP:
{
if( iChoice == 0 )
ce.sSongGroup = "";
ce.songCriteria.m_sGroupName = "";
else
ce.sSongGroup = row.GetRowDef().m_vsChoices[ iChoice ];
ce.songCriteria.m_sGroupName = row.GetRowDef().m_vsChoices[ iChoice ];
break;
}
case ROW_SONG:
@@ -477,29 +478,29 @@ void ScreenOptionsEditCourseEntry::ExportOptions( int iRow, const vector<PlayerN
{
if( iChoice == 0 )
{
ce.baseDifficulty = DIFFICULTY_INVALID;
ce.stepsCriteria.m_difficulty = DIFFICULTY_INVALID;
}
else
{
Difficulty d = CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue()[iChoice-1];
ce.baseDifficulty = d;
ce.stepsCriteria.m_difficulty = d;
}
break;
}
case ROW_LOW_METER:
{
if( iChoice == 0 )
ce.iLowMeter = -1;
ce.stepsCriteria.m_iLowMeter = -1;
else
ce.iLowMeter = iChoice;
ce.stepsCriteria.m_iLowMeter = iChoice;
break;
}
case ROW_HIGH_METER:
{
if( iChoice == 0 )
ce.iHighMeter = -1;
ce.stepsCriteria.m_iHighMeter = -1;
else
ce.iHighMeter = iChoice;
ce.stepsCriteria.m_iHighMeter = iChoice;
break;
}
case ROW_SORT:
+1 -1
View File
@@ -277,7 +277,7 @@ void ScoreScroller::ConfigureActor( Actor *pActor, int iItem )
FOREACH_CONST( Difficulty, m_DifficultiesToShow, iter )
{
const Steps* pSteps = pSong->GetStepsByDifficulty( m_StepsType, *iter, false );
const Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, m_StepsType, *iter, false );
if( pSteps && UNLOCKMAN->StepsIsLocked(pSong, pSteps) )
pSteps = NULL;
BitmapText* pTextStepsScore = &item.m_textScore[*iter];
+1 -1
View File
@@ -1521,7 +1521,7 @@ void ScreenSelectMusic::AfterMusicChange()
m_textNumSongs.SetText( ssprintf("%d", SongManager::GetNumStagesForSong(pSong) ) );
m_textTotalTime.SetText( SecondsToMMSSMsMs(pSong->m_fMusicLengthSeconds) );
pSong->GetSteps( m_vpSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
SongUtil::GetSteps( pSong, m_vpSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
StepsUtil::RemoveLockedSteps( pSong, m_vpSteps );
StepsUtil::SortNotesArrayByDifficulty( m_vpSteps );
+12 -254
View File
@@ -19,9 +19,9 @@
#include "RageFileManager.h"
#include "RageSurface.h"
#include "NoteDataUtil.h"
#include "SongUtil.h"
#include "StepsUtil.h"
#include "Foreach.h"
#include "UnlockManager.h"
#include "BackgroundUtil.h"
#include "SpecialFiles.h"
@@ -319,114 +319,6 @@ static void GetImageDirListing( RString sPath, vector<RString> &AddTo, bool bRet
GetDirListing( sPath + ".gif", AddTo, false, bReturnPathToo );
}
static RString RemoveInitialWhitespace( RString s )
{
size_t i = s.find_first_not_of(" \t\r\n");
if( i != s.npos )
s.erase( 0, i );
return s;
}
/* This is called within TidyUpData, before autogen notes are added. */
void Song::DeleteDuplicateSteps( vector<Steps*> &vSteps )
{
/* vSteps have the same StepsType and Difficulty. Delete them if they have the
* same m_sDescription, m_iMeter and SMNoteData. */
CHECKPOINT;
for( unsigned i=0; i<vSteps.size(); i++ )
{
CHECKPOINT;
const Steps *s1 = vSteps[i];
for( unsigned j=i+1; j<vSteps.size(); j++ )
{
CHECKPOINT;
const Steps *s2 = vSteps[j];
if( s1->GetDescription() != s2->GetDescription() )
continue;
if( s1->GetMeter() != s2->GetMeter() )
continue;
/* Compare, ignoring whitespace. */
RString sSMNoteData1;
s1->GetSMNoteData( sSMNoteData1 );
RString sSMNoteData2;
s2->GetSMNoteData( sSMNoteData2 );
if( RemoveInitialWhitespace(sSMNoteData1) != RemoveInitialWhitespace(sSMNoteData2) )
continue;
LOG->Trace("Removed %p duplicate steps in song \"%s\" with description \"%s\" and meter \"%i\"",
s2, this->GetSongDir().c_str(), s1->GetDescription().c_str(), s1->GetMeter() );
/* Don't use RemoveSteps; autogen notes havn't yet been created and it'll
* create them. */
FOREACH_StepsType( st )
{
for( int k=this->m_vpStepsByType[st].size()-1; k>=0; k-- )
{
if( this->m_vpStepsByType[st][k] == s2 )
{
// delete this->m_vpStepsByType[k]; // delete below
this->m_vpStepsByType[st].erase( this->m_vpStepsByType[st].begin()+k );
break;
}
}
}
for( int k=this->m_vpSteps.size()-1; k>=0; k-- )
{
if( this->m_vpSteps[k] == s2 )
{
delete this->m_vpSteps[k];
this->m_vpSteps.erase( this->m_vpSteps.begin()+k );
break;
}
}
vSteps.erase(vSteps.begin()+j);
--j;
}
}
}
/* Make any duplicate difficulties edits. (Note that BMS files do a first pass
* on this; see BMSLoader::SlideDuplicateDifficulties.) */
void Song::AdjustDuplicateSteps()
{
FOREACH_StepsType( st )
{
FOREACH_Difficulty( dc )
{
if( dc == DIFFICULTY_EDIT )
continue;
vector<Steps*> vSteps;
this->GetSteps( vSteps, st, dc );
/* Delete steps that are completely identical. This happened due to a
* bug in an earlier version. */
DeleteDuplicateSteps( vSteps );
CHECKPOINT;
StepsUtil::SortNotesArrayByDifficulty( vSteps );
CHECKPOINT;
for( unsigned k=1; k<vSteps.size(); k++ )
{
vSteps[k]->SetDifficulty( DIFFICULTY_EDIT );
if( vSteps[k]->GetDescription() == "" )
{
/* "Hard Edit" */
RString EditName = Capitalize( DifficultyToString(dc) ) + " Edit";
vSteps[k]->SetDescription( EditName );
}
}
}
/* XXX: Don't allow edits to have descriptions that look like regular difficulties.
* These are confusing, and they're ambiguous when passed to GetStepsByID. */
}
}
/* Fix up song paths. If there's a leading "./", be sure to keep it: it's
* a signal that the path is from the root directory, not the song directory.
* Other than a leading "./", song paths must never contain "." or "..". */
@@ -738,7 +630,7 @@ void Song::TidyUpData()
/* Don't allow multiple Steps of the same StepsType and Difficulty (except for edits).
* We should be able to use difficulty names as unique identifiers for steps. */
AdjustDuplicateSteps();
SongUtil::AdjustDuplicateSteps( this );
{
/* Generated filename; this doesn't always point to a loadable file,
@@ -835,142 +727,6 @@ void Song::ReCalculateRadarValuesAndLastBeat()
m_fLastBeat = fLastBeat;
}
void Song::GetSteps(
vector<Steps*>& arrayAddTo,
StepsType st,
Difficulty dc,
int iMeterLow,
int iMeterHigh,
const RString &sDescription,
bool bIncludeAutoGen,
unsigned uHash,
int iMaxToGet
) const
{
if( !iMaxToGet )
return;
const vector<Steps*> &vpSteps = st == STEPS_TYPE_INVALID ? GetAllSteps() : GetStepsByStepsType(st);
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
{
Steps* pSteps = vpSteps[i];
if( dc != DIFFICULTY_INVALID && dc != pSteps->GetDifficulty() )
continue;
if( iMeterLow != -1 && iMeterLow > pSteps->GetMeter() )
continue;
if( iMeterHigh != -1 && iMeterHigh < pSteps->GetMeter() )
continue;
if( sDescription.size() && sDescription != pSteps->GetDescription() )
continue;
if( uHash != 0 && uHash != pSteps->GetHash() )
continue;
if( !bIncludeAutoGen && pSteps->IsAutogen() )
continue;
arrayAddTo.push_back( pSteps );
if( iMaxToGet != -1 )
{
--iMaxToGet;
if( !iMaxToGet )
break;
}
}
}
Steps* Song::GetOneSteps(
StepsType st,
Difficulty dc,
int iMeterLow,
int iMeterHigh,
const RString &sDescription,
unsigned uHash,
bool bIncludeAutoGen
) const
{
vector<Steps*> vpSteps;
GetSteps( vpSteps, st, dc, iMeterLow, iMeterHigh, sDescription, bIncludeAutoGen, uHash, 1 ); // get max 1
if( vpSteps.empty() )
return NULL;
else
return vpSteps[0];
}
Steps* Song::GetStepsByDifficulty( StepsType st, Difficulty dc, bool bIncludeAutoGen ) const
{
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? GetAllSteps():GetStepsByStepsType(st);
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
{
Steps* pSteps = vpSteps[i];
if( dc != DIFFICULTY_INVALID && dc != pSteps->GetDifficulty() )
continue;
if( !bIncludeAutoGen && pSteps->IsAutogen() )
continue;
return pSteps;
}
return NULL;
}
Steps* Song::GetStepsByMeter( StepsType st, int iMeterLow, int iMeterHigh ) const
{
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? GetAllSteps():GetStepsByStepsType(st);
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
{
Steps* pSteps = vpSteps[i];
if( iMeterLow > pSteps->GetMeter() )
continue;
if( iMeterHigh < pSteps->GetMeter() )
continue;
return pSteps;
}
return NULL;
}
Steps* Song::GetStepsByDescription( StepsType st, RString sDescription ) const
{
vector<Steps*> vNotes;
GetSteps( vNotes, st, DIFFICULTY_INVALID, -1, -1, sDescription );
if( vNotes.size() == 0 )
return NULL;
else
return vNotes[0];
}
Steps* Song::GetClosestNotes( StepsType st, Difficulty dc, bool bIgnoreLocked ) const
{
ASSERT( dc != DIFFICULTY_INVALID );
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? GetAllSteps():GetStepsByStepsType(st);
Steps *pClosest = NULL;
int iClosestDistance = 999;
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
{
Steps* pSteps = vpSteps[i];
if( pSteps->GetDifficulty() == DIFFICULTY_EDIT && dc != DIFFICULTY_EDIT )
continue;
if( bIgnoreLocked && UNLOCKMAN->StepsIsLocked(this, pSteps) )
continue;
int iDistance = abs(dc - pSteps->GetDifficulty());
if( iDistance < iClosestDistance )
{
pClosest = pSteps;
iClosestDistance = iDistance;
}
}
return pClosest;
}
/* Return whether the song is playable in the given style. */
bool Song::SongCompleteForStyle( const Style *st ) const
{
@@ -979,12 +735,12 @@ bool Song::SongCompleteForStyle( const Style *st ) const
bool Song::HasStepsType( StepsType st ) const
{
return GetOneSteps( st ) != NULL;
return SongUtil::GetOneSteps( this, st ) != NULL;
}
bool Song::HasStepsTypeAndDifficulty( StepsType st, Difficulty dc ) const
{
return GetOneSteps( st, dc ) != NULL;
return SongUtil::GetOneSteps( this, st, dc ) != NULL;
}
void Song::Save()
@@ -1156,11 +912,11 @@ bool Song::IsEasy( StepsType st ) const
/* The easy marker indicates which songs a beginner, having selected "beginner",
* can play and actually get a very easy song: if there are actual beginner
* steps, or if the light steps are 1- or 2-foot. */
const Steps* pBeginnerNotes = GetStepsByDifficulty( st, DIFFICULTY_BEGINNER );
const Steps* pBeginnerNotes = SongUtil::GetStepsByDifficulty( this, st, DIFFICULTY_BEGINNER );
if( pBeginnerNotes )
return true;
const Steps* pEasyNotes = GetStepsByDifficulty( st, DIFFICULTY_EASY );
const Steps* pEasyNotes = SongUtil::GetStepsByDifficulty( this, st, DIFFICULTY_EASY );
if( pEasyNotes && pEasyNotes->GetMeter() == 1 )
return true;
@@ -1349,12 +1105,13 @@ void Song::AddSteps( Steps* pSteps )
m_vpStepsByType[pSteps->m_StepsType].push_back( pSteps );
}
void Song::DeleteSteps( const Steps* pSteps )
void Song::DeleteSteps( const Steps* pSteps, bool bReAutoGen )
{
// Avoid any stale Note::parent pointers by removing all AutoGen'd Steps,
// then adding them again.
RemoveAutoGenNotes();
if( bReAutoGen )
RemoveAutoGenNotes();
vector<Steps*> &vpSteps = m_vpStepsByType[pSteps->m_StepsType];
@@ -1378,7 +1135,8 @@ void Song::DeleteSteps( const Steps* pSteps )
}
}
AddAutoGenNotes();
if( bReAutoGen )
AddAutoGenNotes();
}
bool Song::Matches(RString sGroup, RString sSong) const
@@ -1404,7 +1162,7 @@ bool Song::Matches(RString sGroup, RString sSong) const
void Song::FreeAllLoadedFromProfile( ProfileSlot slot )
{
/* RemoveSteps will remove and recreate autogen notes, which may reorder
/* DeleteSteps will remove and recreate autogen notes, which may reorder
* m_vpSteps, so be careful not to skip over entries. */
vector<Steps*> apToRemove;
for( int s=m_vpSteps.size()-1; s>=0; s-- )
+3 -3
View File
@@ -1033,7 +1033,7 @@ Song *SongManager::GetSongFromSteps( Steps *pSteps )
FOREACH_CONST( Song*, vSongs, song )
{
vector<Steps*> vSteps;
(*song)->GetSteps( vSteps );
SongUtil::GetSteps( *song, vSteps );
FOREACH_CONST( Steps*, vSteps, steps )
{
@@ -1171,7 +1171,7 @@ void SongManager::GetExtraStageInfo( bool bExtra2, const Style *sd, Song*& pSong
Song* pSong = apSongs[s];
vector<Steps*> apSteps;
pSong->GetSteps( apSteps, sd->m_StepsType );
SongUtil::GetSteps( pSong, apSteps, sd->m_StepsType );
for( unsigned n=0; n<apSteps.size(); n++ ) // foreach Steps
{
Steps* pSteps = apSteps[n];
@@ -1678,7 +1678,7 @@ int SongManager::GetNumEditsLoadedFromProfile( ProfileSlot slot ) const
{
const Song *pSong = m_pSongs[s];
vector<Steps*> apSteps;
pSong->GetSteps( apSteps );
SongUtil::GetSteps( pSong, apSteps );
for( unsigned i = 0; i < apSteps.size(); ++i )
{
+257 -8
View File
@@ -13,14 +13,249 @@
#include "UnlockManager.h"
#include "ThemeMetric.h"
#include "LocalizedString.h"
#include "RageLog.h"
bool SongCriteria::Matches( const Song *p ) const
{
if( !m_sGroupName.empty() && m_sGroupName != p->m_sGroupName )
return false;
if( !m_sGenre.empty() && m_sGenre != p->m_sGenre )
return false;
return true;
}
void SongUtil::GetSteps(
const Song *pSong,
vector<Steps*>& arrayAddTo,
StepsType st,
Difficulty dc,
int iMeterLow,
int iMeterHigh,
const RString &sDescription,
bool bIncludeAutoGen,
unsigned uHash,
int iMaxToGet
)
{
if( !iMaxToGet )
return;
const vector<Steps*> &vpSteps = st == STEPS_TYPE_INVALID ? pSong->GetAllSteps() : pSong->GetStepsByStepsType(st);
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
{
Steps* pSteps = vpSteps[i];
if( dc != DIFFICULTY_INVALID && dc != pSteps->GetDifficulty() )
continue;
if( iMeterLow != -1 && iMeterLow > pSteps->GetMeter() )
continue;
if( iMeterHigh != -1 && iMeterHigh < pSteps->GetMeter() )
continue;
if( sDescription.size() && sDescription != pSteps->GetDescription() )
continue;
if( uHash != 0 && uHash != pSteps->GetHash() )
continue;
if( !bIncludeAutoGen && pSteps->IsAutogen() )
continue;
arrayAddTo.push_back( pSteps );
if( iMaxToGet != -1 )
{
--iMaxToGet;
if( !iMaxToGet )
break;
}
}
}
Steps* SongUtil::GetOneSteps(
const Song *pSong,
StepsType st,
Difficulty dc,
int iMeterLow,
int iMeterHigh,
const RString &sDescription,
unsigned uHash,
bool bIncludeAutoGen
)
{
vector<Steps*> vpSteps;
GetSteps( pSong, vpSteps, st, dc, iMeterLow, iMeterHigh, sDescription, bIncludeAutoGen, uHash, 1 ); // get max 1
if( vpSteps.empty() )
return NULL;
else
return vpSteps[0];
}
Steps* SongUtil::GetStepsByDifficulty( const Song *pSong, StepsType st, Difficulty dc, bool bIncludeAutoGen )
{
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? pSong->GetAllSteps() : pSong->GetStepsByStepsType(st);
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
{
Steps* pSteps = vpSteps[i];
if( dc != DIFFICULTY_INVALID && dc != pSteps->GetDifficulty() )
continue;
if( !bIncludeAutoGen && pSteps->IsAutogen() )
continue;
return pSteps;
}
return NULL;
}
Steps* SongUtil::GetStepsByMeter( const Song *pSong, StepsType st, int iMeterLow, int iMeterHigh )
{
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? pSong->GetAllSteps() : pSong->GetStepsByStepsType(st);
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
{
Steps* pSteps = vpSteps[i];
if( iMeterLow > pSteps->GetMeter() )
continue;
if( iMeterHigh < pSteps->GetMeter() )
continue;
return pSteps;
}
return NULL;
}
Steps* SongUtil::GetStepsByDescription( const Song *pSong, StepsType st, RString sDescription )
{
vector<Steps*> vNotes;
GetSteps( pSong, vNotes, st, DIFFICULTY_INVALID, -1, -1, sDescription );
if( vNotes.size() == 0 )
return NULL;
else
return vNotes[0];
}
Steps* SongUtil::GetClosestNotes( const Song *pSong, StepsType st, Difficulty dc, bool bIgnoreLocked )
{
ASSERT( dc != DIFFICULTY_INVALID );
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? pSong->GetAllSteps() : pSong->GetStepsByStepsType(st);
Steps *pClosest = NULL;
int iClosestDistance = 999;
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
{
Steps* pSteps = vpSteps[i];
if( pSteps->GetDifficulty() == DIFFICULTY_EDIT && dc != DIFFICULTY_EDIT )
continue;
if( bIgnoreLocked && UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
continue;
int iDistance = abs(dc - pSteps->GetDifficulty());
if( iDistance < iClosestDistance )
{
pClosest = pSteps;
iClosestDistance = iDistance;
}
}
return pClosest;
}
/* Make any duplicate difficulties edits. (Note that BMS files do a first pass
* on this; see BMSLoader::SlideDuplicateDifficulties.) */
void SongUtil::AdjustDuplicateSteps( Song *pSong )
{
FOREACH_StepsType( st )
{
FOREACH_Difficulty( dc )
{
if( dc == DIFFICULTY_EDIT )
continue;
vector<Steps*> vSteps;
SongUtil::GetSteps( pSong, vSteps, st, dc );
/* Delete steps that are completely identical. This happened due to a
* bug in an earlier version. */
DeleteDuplicateSteps( pSong, vSteps );
CHECKPOINT;
StepsUtil::SortNotesArrayByDifficulty( vSteps );
CHECKPOINT;
for( unsigned k=1; k<vSteps.size(); k++ )
{
vSteps[k]->SetDifficulty( DIFFICULTY_EDIT );
if( vSteps[k]->GetDescription() == "" )
{
/* "Hard Edit" */
RString EditName = Capitalize( DifficultyToString(dc) ) + " Edit";
vSteps[k]->SetDescription( EditName );
}
}
}
/* XXX: Don't allow edits to have descriptions that look like regular difficulties.
* These are confusing, and they're ambiguous when passed to GetStepsByID. */
}
}
static RString RemoveInitialWhitespace( RString s )
{
size_t i = s.find_first_not_of(" \t\r\n");
if( i != s.npos )
s.erase( 0, i );
return s;
}
/* This is called within TidyUpData, before autogen notes are added. */
void SongUtil::DeleteDuplicateSteps( Song *pSong, vector<Steps*> &vSteps )
{
/* vSteps have the same StepsType and Difficulty. Delete them if they have the
* same m_sDescription, m_iMeter and SMNoteData. */
CHECKPOINT;
for( unsigned i=0; i<vSteps.size(); i++ )
{
CHECKPOINT;
const Steps *s1 = vSteps[i];
for( unsigned j=i+1; j<vSteps.size(); j++ )
{
CHECKPOINT;
const Steps *s2 = vSteps[j];
if( s1->GetDescription() != s2->GetDescription() )
continue;
if( s1->GetMeter() != s2->GetMeter() )
continue;
/* Compare, ignoring whitespace. */
RString sSMNoteData1;
s1->GetSMNoteData( sSMNoteData1 );
RString sSMNoteData2;
s2->GetSMNoteData( sSMNoteData2 );
if( RemoveInitialWhitespace(sSMNoteData1) != RemoveInitialWhitespace(sSMNoteData2) )
continue;
LOG->Trace("Removed %p duplicate steps in song \"%s\" with description \"%s\" and meter \"%i\"",
s2, pSong->GetSongDir().c_str(), s1->GetDescription().c_str(), s1->GetMeter() );
pSong->DeleteSteps( s2, false );
vSteps.erase(vSteps.begin()+j);
--j;
}
}
}
static LocalizedString SORT_NOT_AVAILABLE( "Sort", "NotAvailable" );
static LocalizedString SORT_OTHER ( "Sort", "Other" );
/////////////////////////////////////
// Sorting
/////////////////////////////////////
static LocalizedString SORT_NOT_AVAILABLE( "Sort", "NotAvailable" );
static LocalizedString SORT_OTHER ( "Sort", "Other" );
/* Just calculating GetNumTimesPlayed within the sort is pretty slow, so let's precompute
* it. (This could be generalized with a template.) */
static map<const Song*, RString> g_mapSongSortVal;
@@ -280,28 +515,28 @@ RString SongUtil::GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so
}
case SORT_EASY_METER:
{
Steps* pSteps = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_EASY);
Steps* pSteps = GetStepsByDifficulty(pSong, GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_EASY);
if( pSteps && !UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
return ssprintf("%02d", pSteps->GetMeter() );
return SORT_NOT_AVAILABLE.GetValue();
}
case SORT_MEDIUM_METER:
{
Steps* pSteps = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_MEDIUM);
Steps* pSteps = GetStepsByDifficulty(pSong, GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_MEDIUM);
if( pSteps && !UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
return ssprintf("%02d", pSteps->GetMeter() );
return SORT_NOT_AVAILABLE.GetValue();
}
case SORT_HARD_METER:
{
Steps* pSteps = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_HARD);
Steps* pSteps = GetStepsByDifficulty(pSong, GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_HARD);
if( pSteps && !UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
return ssprintf("%02d", pSteps->GetMeter() );
return SORT_NOT_AVAILABLE.GetValue();
}
case SORT_CHALLENGE_METER:
{
Steps* pSteps = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_CHALLENGE);
Steps* pSteps = GetStepsByDifficulty(pSong, GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_CHALLENGE);
if( pSteps && !UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
return ssprintf("%02d", pSteps->GetMeter() );
return SORT_NOT_AVAILABLE.GetValue();
@@ -343,7 +578,7 @@ void SongUtil::SortSongPointerArrayByMeter( vector<Song*> &vpSongsInOut, Difficu
for(unsigned i = 0; i < vpSongsInOut.size(); ++i)
{
/* Ignore locked steps. */
const Steps* pSteps = vpSongsInOut[i]->GetClosestNotes( GAMESTATE->GetCurrentStyle()->m_StepsType, dc, true );
const Steps* pSteps = GetClosestNotes( vpSongsInOut[i], GAMESTATE->GetCurrentStyle()->m_StepsType, dc, true );
RString &s = g_mapSongSortVal[vpSongsInOut[i]];
s = ssprintf("%03d", pSteps ? pSteps->GetMeter() : 0);
@@ -448,7 +683,7 @@ bool SongUtil::ValidateCurrentEditStepsDescription( const RString &sAnswer, RStr
// Steps name must be unique for this song.
vector<Steps*> v;
pSong->GetSteps( v, STEPS_TYPE_INVALID, DIFFICULTY_EDIT );
GetSteps( pSong, v, STEPS_TYPE_INVALID, DIFFICULTY_EDIT );
FOREACH_CONST( Steps*, v, s )
{
if( pSteps == *s )
@@ -486,6 +721,20 @@ bool SongUtil::ValidateCurrentStepsDescription( const RString &sAnswer, RString
return true;
}
void SongUtil::GetAllSongGenres( vector<RString> &vsOut )
{
set<RString> genres;
FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), song )
{
if( !(*song)->m_sGenre.empty() )
genres.insert( (*song)->m_sGenre );
}
FOREACHS_CONST( RString, genres, s )
{
vsOut.push_back( *s );
}
}
//////////////////////////////////
+48 -1
View File
@@ -11,8 +11,52 @@ class Steps;
class Profile;
class XNode;
class SongCriteria
{
public:
RString m_sGroupName; // "" means don't match
RString m_sGenre; // "" means don't match
SongCriteria()
{
}
bool Matches( const Song *p ) const;
};
namespace SongUtil
{
void GetSteps(
const Song *pSong,
vector<Steps*>& arrayAddTo,
StepsType st = STEPS_TYPE_INVALID,
Difficulty dc = DIFFICULTY_INVALID,
int iMeterLow = -1,
int iMeterHigh = -1,
const RString &sDescription = "",
bool bIncludeAutoGen = true,
unsigned uHash = 0,
int iMaxToGet = -1
);
Steps* GetOneSteps(
const Song *pSong,
StepsType st = STEPS_TYPE_INVALID,
Difficulty dc = DIFFICULTY_INVALID,
int iMeterLow = -1,
int iMeterHigh = -1,
const RString &sDescription = "",
unsigned uHash = 0,
bool bIncludeAutoGen = true
);
Steps* GetStepsByDifficulty( const Song *pSong, StepsType st, Difficulty dc, bool bIncludeAutoGen = true );
Steps* GetStepsByMeter( const Song *pSong, StepsType st, int iMeterLow, int iMeterHigh );
Steps* GetStepsByDescription( const Song *pSong, StepsType st, RString sDescription );
Steps* GetClosestNotes( const Song *pSong, StepsType st, Difficulty dc, bool bIgnoreLocked=false );
void AdjustDuplicateSteps( Song *pSong ); // part of TidyUpData
void DeleteDuplicateSteps( Song *pSong, vector<Steps*> &vSteps );
RString MakeSortString( RString s );
void SortSongPointerArrayByTitle( vector<Song*> &vpSongsInOut );
void SortSongPointerArrayByBPM( vector<Song*> &vpSongsInOut );
@@ -24,7 +68,7 @@ namespace SongUtil
void SortSongPointerArrayByNumPlays( vector<Song*> &vpSongsInOut, ProfileSlot slot, bool bDescending );
void SortSongPointerArrayByNumPlays( vector<Song*> &vpSongsInOut, const Profile* pProfile, bool bDescending );
void SortSongPointerArrayByMeter( vector<Song*> &vpSongsInOut, Difficulty dc );
RString GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so );
RString GetSectionNameFromSongAndSort( const Song *pSong, SortOrder so );
void SortSongPointerArrayBySectionName( vector<Song*> &vpSongsInOut, SortOrder so );
void SortByMostRecentlyPlayedForMachine( vector<Song*> &vpSongsInOut );
@@ -34,6 +78,9 @@ namespace SongUtil
RString MakeUniqueEditDescription( const Song* pSong, StepsType st, const RString &sPreferredDescription );
bool ValidateCurrentEditStepsDescription( const RString &sAnswer, RString &sErrorOut );
bool ValidateCurrentStepsDescription( const RString &sAnswer, RString &sErrorOut );
void GetAllSongGenres( vector<RString> &vsOut );
void FilterSongs( const SongCriteria &sc, const vector<Song*> &in, vector<Song*> &out );
}
class SongID
+33 -4
View File
@@ -8,18 +8,47 @@
#include "GameManager.h"
#include "XmlFile.h"
#include "UnlockManager.h"
#include "SongUtil.h"
bool StepsCriteria::Matches( const Steps *p ) const
{
if( m_difficulty != DIFFICULTY_INVALID && p->GetDifficulty() != m_difficulty )
return false;
if( m_iLowMeter != -1 && p->GetMeter() < m_iLowMeter )
return false;
if( m_iHighMeter != -1 && p->GetMeter() > m_iHighMeter )
return false;
return true;
}
void StepsUtil::GetAllMatching( const SongCriteria &soc, const StepsCriteria &stc, vector<SongAndSteps> &out )
{
FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), so )
{
if( !soc.Matches(*so) )
continue;
FOREACH_CONST( Steps*, (*so)->GetAllSteps(), st )
{
if( !stc.Matches(*st) )
continue;
}
}
}
//
// Sorting stuff
//
map<const Steps*, RString> steps_sort_val;
bool CompareStepsPointersBySortValueAscending(const Steps *pSteps1, const Steps *pSteps2)
static bool CompareStepsPointersBySortValueAscending(const Steps *pSteps1, const Steps *pSteps2)
{
return steps_sort_val[pSteps1] < steps_sort_val[pSteps2];
}
bool CompareStepsPointersBySortValueDescending(const Steps *pSteps1, const Steps *pSteps2)
static bool CompareStepsPointersBySortValueDescending(const Steps *pSteps1, const Steps *pSteps2)
{
return steps_sort_val[pSteps1] > steps_sort_val[pSteps2];
}
@@ -191,11 +220,11 @@ Steps *StepsID::ToSteps( const Song *p, bool bAllowNull, bool bUseCache ) const
Steps *ret = NULL;
if( dc == DIFFICULTY_EDIT )
{
ret = p->GetOneSteps( st, dc, -1, -1, sDescription, uHash, true );
ret = SongUtil::GetOneSteps( p, st, dc, -1, -1, sDescription, uHash, true );
}
else
{
ret = p->GetOneSteps( st, dc, -1, -1, "", 0, true );
ret = SongUtil::GetOneSteps( p, st, dc, -1, -1, "", 0, true );
}
if( !bAllowNull && ret == NULL )
+30
View File
@@ -8,9 +8,39 @@ class Steps;
class Song;
class Profile;
class XNode;
class SongCriteria;
class StepsCriteria
{
public:
Difficulty m_difficulty; // don't filter if DIFFICULTY_INVALID
int m_iLowMeter; // don't filter if -1
int m_iHighMeter; // don't filter if -1
StepsCriteria()
{
m_difficulty = DIFFICULTY_INVALID;
m_iLowMeter = -1;
m_iHighMeter = -1;
}
bool Matches( const Steps *p ) const;
};
class SongAndSteps
{
public:
Song* pSong;
Steps* pSteps;
bool operator==( const SongAndSteps& other ) const { return pSong==other.pSong && pSteps==other.pSteps; }
bool operator<( const SongAndSteps& other ) const { return pSong<=other.pSong && pSteps<=other.pSteps; }
};
namespace StepsUtil
{
void GetAllMatching( const SongCriteria &soc, const StepsCriteria &stc, vector<SongAndSteps> &out ); // look up in SONGMAN
bool CompareNotesPointersByRadarValues(const Steps* pSteps1, const Steps* pSteps2);
bool CompareNotesPointersByMeter(const Steps *pSteps1, const Steps* pSteps2);
bool CompareNotesPointersByDifficulty(const Steps *pSteps1, const Steps *pSteps2);
+4 -3
View File
@@ -307,7 +307,8 @@ UnlockEntryStatus UnlockEntry::GetUnlockEntryStatus() const
if( m_bRequirePassHardSteps && m_pSong )
{
vector<Steps*> vp;
m_pSong->GetSteps(
SongUtil::GetSteps(
m_pSong,
vp,
STEPS_TYPE_INVALID,
DIFFICULTY_HARD
@@ -454,11 +455,11 @@ void UnlockManager::Load()
FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), s )
{
// If no hard steps to play to unlock, skip
if( (*s)->GetOneSteps(STEPS_TYPE_INVALID, DIFFICULTY_HARD) == NULL )
if( SongUtil::GetOneSteps(*s, STEPS_TYPE_INVALID, DIFFICULTY_HARD) == NULL )
continue;
// If no challenge steps to unlock, skip
if( (*s)->GetOneSteps(STEPS_TYPE_INVALID, DIFFICULTY_CHALLENGE) == NULL )
if( SongUtil::GetOneSteps(*s, STEPS_TYPE_INVALID, DIFFICULTY_CHALLENGE) == NULL )
continue;
if( SONGMAN->WasLoadedFromAdditionalSongs(*s) )
+1 -27
View File
@@ -186,30 +186,6 @@ public:
bool HasStepsTypeAndDifficulty( StepsType st, Difficulty dc ) const;
const vector<Steps*>& GetAllSteps() const { return m_vpSteps; }
const vector<Steps*>& GetStepsByStepsType( StepsType st ) const { return m_vpStepsByType[st]; }
void GetSteps(
vector<Steps*>& arrayAddTo,
StepsType st = STEPS_TYPE_INVALID,
Difficulty dc = DIFFICULTY_INVALID,
int iMeterLow = -1,
int iMeterHigh = -1,
const RString &sDescription = "",
bool bIncludeAutoGen = true,
unsigned uHash = 0,
int iMaxToGet = -1
) const;
Steps* GetOneSteps(
StepsType st = STEPS_TYPE_INVALID,
Difficulty dc = DIFFICULTY_INVALID,
int iMeterLow = -1,
int iMeterHigh = -1,
const RString &sDescription = "",
unsigned uHash = 0,
bool bIncludeAutoGen = true
) const;
Steps* GetStepsByDifficulty( StepsType st, Difficulty dc, bool bIncludeAutoGen = true ) const;
Steps* GetStepsByMeter( StepsType st, int iMeterLow, int iMeterHigh ) const;
Steps* GetStepsByDescription( StepsType st, RString sDescription ) const;
Steps* GetClosestNotes( StepsType st, Difficulty dc, bool bIgnoreLocked=false ) const;
bool IsEasy( StepsType st ) const;
bool IsTutorial() const;
bool HasEdits( StepsType st ) const;
@@ -220,7 +196,7 @@ public:
bool ShowInDemonstrationAndRanking() const;
void AddSteps( Steps* pSteps ); // we are responsible for deleting the memory pointed to by pSteps!
void DeleteSteps( const Steps* pSteps );
void DeleteSteps( const Steps* pSteps, bool bReAutoGen = true );
void FreeAllLoadedFromProfile( ProfileSlot slot = ProfileSlot_INVALID );
bool WasLoadedFromProfile() const { return m_LoadedFromProfile != ProfileSlot_INVALID; }
@@ -239,8 +215,6 @@ public:
void PushSelf( lua_State *L );
private:
void AdjustDuplicateSteps(); // part of TidyUpData
void DeleteDuplicateSteps( vector<Steps*> &vSteps );
vector<Steps*> m_vpSteps;
vector<Steps*> m_vpStepsByType[NUM_STEPS_TYPES];